From f641bd076d29666a5d2a10d5384e4924b0a0e524 Mon Sep 17 00:00:00 2001 From: reed Date: Sun, 8 Mar 2015 18:34:37 -0700 Subject: [PATCH] use colorfilter instead of imagefilter when possible big speed win w/ nanobench --match colorfilter_ BUG=skia: TBR= Will require rebaselining, so landing temporarily to trigger layouttests. Review URL: https://codereview.chromium.org/966233002 --- src/core/SkCanvas.cpp | 50 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index a47bd89c05..d80ad376f8 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -8,6 +8,7 @@ #include "SkCanvas.h" #include "SkCanvasPriv.h" #include "SkBitmapDevice.h" +#include "SkColorFilter.h" #include "SkDeviceImageFilterProxy.h" #include "SkDraw.h" #include "SkDrawable.h" @@ -283,6 +284,36 @@ private: ///////////////////////////////////////////////////////////////////////////// +static SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) { + return lazy->isValid() ? lazy->get() : lazy->set(orig); +} + +/** + * If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that + * colorfilter, else return NULL. + */ +static SkColorFilter* image_to_color_filter(const SkPaint& paint) { + SkImageFilter* imgf = paint.getImageFilter(); + if (!imgf) { + return NULL; + } + + SkColorFilter* imgCF; + if (!imgf->asAColorFilter(&imgCF)) { + return NULL; + } + + SkColorFilter* paintCF = paint.getColorFilter(); + if (NULL == paintCF) { + // there is no existing paint colorfilter, so we can just return the imagefilter's + return imgCF; + } + + // The paint has both a colorfilter and an imagefilter. + SkAutoTUnref autoImgCF(imgCF); + return SkColorFilter::CreateComposeFilter(imgCF, paintCF); +} + class AutoDrawLooper { public: AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint, @@ -295,9 +326,17 @@ public: fDoClearImageFilter = false; fDone = false; - if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { + SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint); + if (simplifiedCF) { + SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint); + paint->setColorFilter(simplifiedCF)->unref(); + paint->setImageFilter(NULL); + fPaint = paint; + } + + if (!skipLayerForImageFilter && fPaint->getImageFilter()) { SkPaint tmp; - tmp.setImageFilter(fOrigPaint.getImageFilter()); + tmp.setImageFilter(fPaint->getImageFilter()); (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag, true, SkCanvas::kFullLayer_SaveLayerStrategy); // we'll clear the imageFilter for the actual draws in next(), so @@ -319,7 +358,7 @@ public: uint32_t oldFlags = paint.getFlags(); fNewPaintFlags = filter_paint_flags(props, oldFlags); if (fIsSimple && (fNewPaintFlags != oldFlags)) { - SkPaint* paint = fLazyPaint.set(fOrigPaint); + SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint); paint->setFlags(fNewPaintFlags); fPaint = paint; // if we're not simple, doNext() will take care of calling setFlags() @@ -350,7 +389,7 @@ public: } private: - SkLazyPaint fLazyPaint; + SkLazyPaint fLazyPaintInit, fLazyPaintPerNext; SkCanvas* fCanvas; const SkPaint& fOrigPaint; SkDrawFilter* fFilter; @@ -371,7 +410,8 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { SkASSERT(!fIsSimple); SkASSERT(fLooperContext || fFilter || fDoClearImageFilter); - SkPaint* paint = fLazyPaint.set(fOrigPaint); + SkPaint* paint = fLazyPaintPerNext.set(fLazyPaintInit.isValid() ? + *fLazyPaintInit.get() : fOrigPaint); paint->setFlags(fNewPaintFlags); if (fDoClearImageFilter) {