change colorfilter to return an array of frag processors
authorreed <reed@google.com>
Tue, 3 Mar 2015 14:41:45 +0000 (06:41 -0800)
committerCommit bot <commit-bot@chromium.org>
Tue, 3 Mar 2015 14:41:45 +0000 (06:41 -0800)
BUG=skia:

Review URL: https://codereview.chromium.org/973593002

15 files changed:
gm/tablecolorfilter.cpp
include/core/SkColorFilter.h
include/effects/SkColorCubeFilter.h
include/effects/SkColorMatrixFilter.h
include/effects/SkLumaColorFilter.h
include/effects/SkModeColorFilter.h
src/core/SkColorFilter.cpp
src/effects/SkColorCubeFilter.cpp
src/effects/SkColorFilters.cpp
src/effects/SkColorMatrixFilter.cpp
src/effects/SkLumaColorFilter.cpp
src/effects/SkPerlinNoiseShader.cpp
src/effects/SkTableColorFilter.cpp
src/gpu/SkGr.cpp
tests/GpuColorFilterTest.cpp

index 2acb15c677c3d50e2b58fbe2c5172666419c92db..0d6da8f475e06c4380c44e0eb84695f2fef814c2 100644 (file)
@@ -193,16 +193,29 @@ DEF_GM( return new TableColorFilterGM; )
 //////////////////////////////////////////////////////////////////////////////
 
 class ComposeColorFilterGM : public skiagm::GM {
+    enum {
+        COLOR_COUNT = 3,
+        MODE_COUNT = 4,
+    };
+    const SkColor*          fColors;
+    const SkXfermode::Mode* fModes;
+    SkString                fName;
+
 public:
-    ComposeColorFilterGM() {}
+    ComposeColorFilterGM(const SkColor colors[], const SkXfermode::Mode modes[],
+                         const char suffix[])
+        : fColors(colors), fModes(modes)
+    {
+        fName.printf("colorcomposefilter_%s", suffix);
+    }
     
 protected:
     virtual SkString onShortName() {
-        return SkString("composecolorfilter");
+        return fName;
     }
     
     virtual SkISize onISize() {
-        return SkISize::Make(730, 730);
+        return SkISize::Make(790, 790);
     }
 
     virtual void onDraw(SkCanvas* canvas) {
@@ -211,20 +224,12 @@ protected:
 
         canvas->drawColor(0xFFDDDDDD);
 
-        SkColor colors[] = { SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW };
-        SkXfermode::Mode modes[] = {
-            SkXfermode::kOverlay_Mode,
-            SkXfermode::kDarken_Mode,
-            SkXfermode::kColorBurn_Mode,
-            SkXfermode::kExclusion_Mode,
-        };
-
-        const int MODES = SK_ARRAY_COUNT(modes) * SK_ARRAY_COUNT(colors);
+        const int MODES = MODE_COUNT * COLOR_COUNT;
         SkAutoTUnref<SkColorFilter> filters[MODES];
         int index = 0;
-        for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) {
-            for (size_t j = 0; j < SK_ARRAY_COUNT(colors); ++j) {
-                filters[index++].reset(SkColorFilter::CreateModeFilter(colors[j], modes[i]));
+        for (int i = 0; i < MODE_COUNT; ++i) {
+            for (int j = 0; j < COLOR_COUNT; ++j) {
+                filters[index++].reset(SkColorFilter::CreateModeFilter(fColors[j], fModes[i]));
             }
         }
 
@@ -235,9 +240,27 @@ protected:
 
         canvas->translate(spacer, spacer);
 
-        for (size_t y = 0; y < MODES; ++y) {
+        canvas->drawRect(r, paint); // orig
+
+        for (int i = 0; i < MODES; ++i) {
+            paint.setColorFilter(filters[i]);
+
+            canvas->save();
+            canvas->translate((i + 1) * (r.width() + spacer), 0);
+            canvas->drawRect(r, paint);
+            canvas->restore();
+
+            canvas->save();
+            canvas->translate(0, (i + 1) * (r.width() + spacer));
+            canvas->drawRect(r, paint);
+            canvas->restore();
+        }
+
+        canvas->translate(r.width() + spacer, r.width() + spacer);
+
+        for (int y = 0; y < MODES; ++y) {
             canvas->save();
-            for (size_t x = 0; x < MODES; ++x) {
+            for (int x = 0; x < MODES; ++x) {
                 SkAutoTUnref<SkColorFilter> compose(SkColorFilter::CreateComposeFilter(filters[y],
                                                                                        filters[x]));
                 paint.setColorFilter(compose);
@@ -252,5 +275,21 @@ protected:
 private:
     typedef GM INHERITED;
 };
-DEF_GM( return new ComposeColorFilterGM; )
 
+const SkColor gColors0[] = { SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW };
+const SkXfermode::Mode gModes0[] = {
+    SkXfermode::kOverlay_Mode,
+    SkXfermode::kDarken_Mode,
+    SkXfermode::kColorBurn_Mode,
+    SkXfermode::kExclusion_Mode,
+};
+DEF_GM( return new ComposeColorFilterGM(gColors0, gModes0, "wacky"); )
+
+const SkColor gColors1[] = { 0x80FF0000, 0x8000FF00, 0x800000FF };
+const SkXfermode::Mode gModes1[] = {
+    SkXfermode::kSrcOver_Mode,
+    SkXfermode::kXor_Mode,
+    SkXfermode::kDstOut_Mode,
+    SkXfermode::kSrcATop_Mode,
+};
+DEF_GM( return new ComposeColorFilterGM(gColors1, gModes1, "alpha"); )
index 31a4365a3cae426787ed84f1bfdbee473955a3e1..14d33069f01ae9a74c2ae04d15db5758a20ef58d 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2006 The Android Open Source Project
  *
@@ -6,12 +5,12 @@
  * found in the LICENSE file.
  */
 
-
 #ifndef SkColorFilter_DEFINED
 #define SkColorFilter_DEFINED
 
 #include "SkColor.h"
 #include "SkFlattenable.h"
+#include "SkTDArray.h"
 #include "SkXfermode.h"
 
 class SkBitmap;
@@ -138,10 +137,18 @@ public:
      */
     static SkColorFilter* CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner);
 
-    /** A subclass may implement this factory function to work with the GPU backend. If the return
-        is non-NULL then the caller owns a ref on the returned object.
+    /**
+     *  A subclass may implement this factory function to work with the GPU backend.
+     *  If it returns true, then 1 or more fragment processors will have been appended to the
+     *  array, each of which has been ref'd, so that the caller is responsible for calling unref()
+     *  on them when they are finished. If more than one processor is appended, they will be
+     *  applied in FIFO order.
+     *
+     *  If the subclass returns false, then it should not modify the array at all.
      */
-    virtual GrFragmentProcessor* asFragmentProcessor(GrContext*) const;
+    virtual bool asFragmentProcessors(GrContext*, SkTDArray<GrFragmentProcessor*>*) const {
+        return false;
+    }
 
     SK_TO_STRING_PUREVIRT()
 
index 1d4d0fd17d0ba266cfa01545dc9a3c3d41aa29d2..4500a0c292754e5dab2cd603959b039fc2632c52 100644 (file)
@@ -25,7 +25,7 @@ public:
     uint32_t getFlags() const SK_OVERRIDE;
 
 #if SK_SUPPORT_GPU
-   GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
+   bool asFragmentProcessors(GrContext*, SkTDArray<GrFragmentProcessor*>*) const SK_OVERRIDE;
 #endif
 
     SK_TO_STRING_OVERRIDE()
index ff806072a21bf83d3dc13431bcd61b02f2ccc062..58f37ffe4bb262b1334cd57a3d63d3916ce00fb5 100644 (file)
@@ -28,7 +28,7 @@ public:
     SkColorFilter* newComposed(const SkColorFilter*) const SK_OVERRIDE;
 
 #if SK_SUPPORT_GPU
-    GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
+    bool asFragmentProcessors(GrContext*, SkTDArray<GrFragmentProcessor*>*) const SK_OVERRIDE;
 #endif
 
     struct State {
index c7bb2db8bc2bba8569603727a1160fac1a47d099..c970e8c11509037aebfafb4234089d328e7ca030 100644 (file)
@@ -28,7 +28,7 @@ public:
     void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const SK_OVERRIDE;
 
 #if SK_SUPPORT_GPU
-    GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
+    bool asFragmentProcessors(GrContext*, SkTDArray<GrFragmentProcessor*>*) const SK_OVERRIDE;
 #endif
 
     SK_TO_STRING_OVERRIDE()
index 16c6e13359545af766839c4af90ae00a891d0fbc..4bb7a43db4a16ae976f9d152e634ae5aec64589b 100644 (file)
@@ -40,7 +40,7 @@ public:
 #endif
 
 #if SK_SUPPORT_GPU
-    GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
+    bool asFragmentProcessors(GrContext*, SkTDArray<GrFragmentProcessor*>*) const SK_OVERRIDE;
 #endif
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
 
index 2a78058106a01b2266190b0a7ccbc5b21fa6b377..fd76dd1c9be033912a2cae899079fff73ccc2f7b 100644 (file)
@@ -37,10 +37,6 @@ SkColor SkColorFilter::filterColor(SkColor c) const {
     return SkUnPreMultiply::PMColorToColor(dst);
 }
 
-GrFragmentProcessor* SkColorFilter::asFragmentProcessor(GrContext*) const {
-    return NULL;
-}
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 class SkComposeColorFilter : public SkColorFilter {
@@ -75,10 +71,13 @@ public:
     }
 #endif
 
-#if 0   // TODO: should we support composing the fragments?
 #if SK_SUPPORT_GPU
-    GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
-#endif
+    bool asFragmentProcessors(GrContext* context,
+                              SkTDArray<GrFragmentProcessor*>* array) const SK_OVERRIDE {
+        bool hasFrags = fInner->asFragmentProcessors(context, array);
+        hasFrags |= fOuter->asFragmentProcessors(context, array);
+        return hasFrags;
+    }
 #endif
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)
index f71f4719b4e3333a9a42c5b83776356c0e01543f..e2aade75e551bed39458775883d61cab26dfcb55 100644 (file)
@@ -337,7 +337,8 @@ void GrColorCubeEffect::GLProcessor::GenKey(const GrProcessor& proc,
                                             const GrGLCaps&, GrProcessorKeyBuilder* b) {
 }
 
-GrFragmentProcessor* SkColorCubeFilter::asFragmentProcessor(GrContext* context) const {
+bool SkColorCubeFilter::asFragmentProcessors(GrContext* context,
+                                             SkTDArray<GrFragmentProcessor*>* array) const {
     static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
     GrUniqueKey key;
     GrUniqueKey::Builder builder(&key, kDomain, 2);
@@ -358,6 +359,13 @@ GrFragmentProcessor* SkColorCubeFilter::asFragmentProcessor(GrContext* context)
         }
     }
 
-    return textureCube ? GrColorCubeEffect::Create(textureCube) : NULL;
+    GrFragmentProcessor* frag = textureCube ? GrColorCubeEffect::Create(textureCube) : NULL;
+    if (frag) {
+        if (array) {
+            *array->append() = frag;
+        }
+        return true;
+    }
+    return false;
 }
 #endif
index 10e69585700bab508f63c6580436b551a667eecb..6f7d6886f815d6618725bd55cafe68c0fe788f35 100644 (file)
@@ -366,11 +366,18 @@ GrFragmentProcessor* ModeColorFilterEffect::TestCreate(SkRandom* rand,
     return ModeColorFilterEffect::Create(color, mode);
 }
 
-GrFragmentProcessor* SkModeColorFilter::asFragmentProcessor(GrContext*) const {
+bool SkModeColorFilter::asFragmentProcessors(GrContext*,
+                                             SkTDArray<GrFragmentProcessor*>* array) const {
     if (SkXfermode::kDst_Mode != fMode) {
-        return ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
+        GrFragmentProcessor* frag = ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
+        if (frag) {
+            if (array) {
+                *array->append() = frag;
+            }
+            return true;
+        }
     }
-    return NULL;
+    return false;
 }
 
 #endif
index 6ab4a674875b849a5e3dc8d6a89a09af5978f111..bb3b6dda78b462e02454e3b536519cba51bf8d75 100644 (file)
@@ -494,8 +494,16 @@ GrFragmentProcessor* ColorMatrixEffect::TestCreate(SkRandom* random,
     return ColorMatrixEffect::Create(colorMatrix);
 }
 
-GrFragmentProcessor* SkColorMatrixFilter::asFragmentProcessor(GrContext*) const {
-    return ColorMatrixEffect::Create(fMatrix);
+bool SkColorMatrixFilter::asFragmentProcessors(GrContext*,
+                                               SkTDArray<GrFragmentProcessor*>* array) const {
+    GrFragmentProcessor* frag = ColorMatrixEffect::Create(fMatrix);
+    if (frag) {
+        if (array) {
+            *array->append() = frag;
+        }
+        return true;
+    }
+    return false;
 }
 
 #endif
index 20e0659dfeff0625bc1787054fff2f9d34d22c6f..b7860e0a0b9a1848fb73b49debd972fb332b6d8a 100644 (file)
@@ -119,7 +119,16 @@ private:
     }
 };
 
-GrFragmentProcessor* SkLumaColorFilter::asFragmentProcessor(GrContext*) const {
-    return LumaColorFilterEffect::Create();
+bool SkLumaColorFilter::asFragmentProcessors(GrContext*,
+                                             SkTDArray<GrFragmentProcessor*>* array) const {
+
+    GrFragmentProcessor* frag = LumaColorFilterEffect::Create();
+    if (frag) {
+        if (array) {
+            *array->append() = frag;
+        }
+        return true;
+    }
+    return false;
 }
 #endif
index b721296afe2d6c38cc75ea7cc5fdc99eded5a184..6e53253f292a5d55fb5911e3142ffd411c23a2be 100644 (file)
@@ -967,7 +967,11 @@ bool SkPerlinNoiseShader::asFragmentProcessor(GrContext* context, const SkPaint&
         }
         SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(
                                                 clearColor, SkXfermode::kSrc_Mode));
-        *fp = cf->asFragmentProcessor(context);
+        SkTDArray<GrFragmentProcessor*> array;
+        if (cf->asFragmentProcessors(context, &array)) {
+            SkASSERT(1 == array.count());   // modecolorfilter only returns one
+            *fp = array[0];                 // transfer ownership to fp
+        }
         return true;
     }
 
index d6c3e5f03274b7e772086bcf05ed5ac349efe564..073bc188053bde9cba1001d6e0bf99cc9665a276 100644 (file)
@@ -44,7 +44,7 @@ public:
     SkColorFilter* newComposed(const SkColorFilter* inner) const SK_OVERRIDE;
 
 #if SK_SUPPORT_GPU
-    GrFragmentProcessor* asFragmentProcessor(GrContext* context) const SK_OVERRIDE;
+    bool asFragmentProcessors(GrContext*, SkTDArray<GrFragmentProcessor*>*) const SK_OVERRIDE;
 #endif
 
     void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const SK_OVERRIDE;
@@ -567,14 +567,28 @@ GrFragmentProcessor* ColorTableEffect::TestCreate(SkRandom* random,
         (flags & (1 << 2)) ? luts[2] : NULL,
         (flags & (1 << 3)) ? luts[3] : NULL
     ));
-    return filter->asFragmentProcessor(context);
+
+    SkTDArray<GrFragmentProcessor*> array;
+    if (filter->asFragmentProcessors(context, &array)) {
+        SkASSERT(1 == array.count());   // TableColorFilter only returns 1
+        return array[0];
+    }
+    return NULL;
 }
 
-GrFragmentProcessor* SkTable_ColorFilter::asFragmentProcessor(GrContext* context) const {
+bool SkTable_ColorFilter::asFragmentProcessors(GrContext* context,
+                                               SkTDArray<GrFragmentProcessor*>* array) const {
     SkBitmap bitmap;
     this->asComponentTable(&bitmap);
 
-    return ColorTableEffect::Create(context, bitmap, fFlags);
+    GrFragmentProcessor* frag = ColorTableEffect::Create(context, bitmap, fFlags);
+    if (frag) {
+        if (array) {
+            *array->append() = frag;
+        }
+        return true;
+    }
+    return false;
 }
 
 #endif // SK_SUPPORT_GPU
index 401a50eca8b53145b17734b652271ce993a1707e..ff6f7fa098ed47cd254d82b9f1edafed023e3655 100644 (file)
@@ -662,9 +662,12 @@ void SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget* rt, const SkPai
             SkColor filtered = colorFilter->filterColor(skPaint.getColor());
             grPaint->setColor(SkColor2GrColor(filtered));
         } else {
-            SkAutoTUnref<GrFragmentProcessor> fp(colorFilter->asFragmentProcessor(context));
-            if (fp.get()) {
-                grPaint->addColorProcessor(fp);
+            SkTDArray<GrFragmentProcessor*> array;
+            if (colorFilter->asFragmentProcessors(context, &array)) {
+                for (int i = 0; i < array.count(); ++i) {
+                    grPaint->addColorProcessor(array[i]);
+                    array[i]->unref();
+                }
             }
         }
     }
index bf0ba3046a34b1c7f17af522043d6a3e11d3b314..037734eebcf5d1063f01af2f52dce778657aff5e 100644 (file)
@@ -99,14 +99,18 @@ static void test_getConstantColorComponents(skiatest::Reporter* reporter, GrCont
     for (size_t i = 0; i < SK_ARRAY_COUNT(filterTests); ++i) {
         const GetConstantComponentTestCase& test = filterTests[i];
         SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(test.filterColor, test.filterMode));
-        SkAutoTUnref<GrFragmentProcessor> effect(cf->asFragmentProcessor(grContext));
+        SkTDArray<GrFragmentProcessor*> array;
+        bool hasFrag = cf->asFragmentProcessors(grContext, &array);
+        REPORTER_ASSERT(reporter, hasFrag);
+        REPORTER_ASSERT(reporter, 1 == array.count());
         GrInvariantOutput inout(test.inputColor,
                                 static_cast<GrColorComponentFlags>(test.inputComponents),
                                 false);
-        effect->computeInvariantOutput(&inout);
+        array[0]->computeInvariantOutput(&inout);
 
         REPORTER_ASSERT(reporter, filterColor(inout.color(), inout.validFlags()) == test.outputColor);
         REPORTER_ASSERT(reporter, test.outputComponents == inout.validFlags());
+        array[0]->unref();
     }
 }