Replace the asAFoo() functions in SkImageFilter with canFilterImageGPU() and
authorsenorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 1 Aug 2012 20:16:34 +0000 (20:16 +0000)
committersenorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 1 Aug 2012 20:16:34 +0000 (20:16 +0000)
onFilterImageGPU() virtuals.  This allows each filter to implement its own GPU
processing code, even for multi-pass filters.

Review URL:  http://codereview.appspot.com/6449075/

git-svn-id: http://skia.googlecode.com/svn/trunk@4900 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkImageFilter.h
include/effects/SkBlurImageFilter.h
include/effects/SkMorphologyImageFilter.h
src/core/SkPaint.cpp
src/effects/SkBlurImageFilter.cpp
src/effects/SkMorphologyImageFilter.cpp
src/gpu/SkGpuDevice.cpp

index 0915b90..b16fb0f 100644 (file)
@@ -90,28 +90,21 @@ public:
     virtual bool asNewCustomStage(GrCustomStage** stage, GrTexture*) const;
 
     /**
-     *  Experimental.
-     *
-     *  If the filter can be expressed as a gaussian-blur, return true and
-     *  set the sigma to the values for horizontal and vertical.
-     */
-    virtual bool asABlur(SkSize* sigma) const;
-
-    /**
-     *  Experimental.
-     *
-     *  If the filter can be expressed as an erode, return true and
-     *  set the radius in X and Y.
+     *  Returns true if the filter can be processed on the GPU.  This is most
+     *  often used for multi-pass effects, where intermediate results must be
+     *  rendered to textures.  For single-pass effects, use asNewCustomStage().
+     *  The default implementation returns false.
      */
-    virtual bool asAnErode(SkISize* radius) const;
+    virtual bool canFilterImageGPU() const;
 
     /**
-     *  Experimental.
-     *
-     *  If the filter can be expressed as a dilation, return true and
-     *  set the radius in X and Y.
+     *  Process this image filter on the GPU.  texture is the source texture
+     *  for processing, and rect is the effect region to process.  The
+     *  function must allocate a new texture of at least rect width/height
+     *  size, and return it to the caller.  The default implementation returns
+     *  NULL.
      */
-    virtual bool asADilate(SkISize* radius) const;
+    virtual GrTexture* onFilterImageGPU(GrTexture* texture, const SkRect& rect);
 
 protected:
     SkImageFilter() {}
index bf5173d..ab84a0e 100644 (file)
@@ -15,8 +15,6 @@ class SK_API SkBlurImageFilter : public SkImageFilter {
 public:
     SkBlurImageFilter(SkScalar sigmaX, SkScalar sigmaY);
 
-    virtual bool asABlur(SkSize* sigma) const SK_OVERRIDE;
-
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurImageFilter)
 
 protected:
@@ -26,6 +24,9 @@ protected:
     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
                                SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
 
+    bool canFilterImageGPU() const SK_OVERRIDE { return true; }
+    virtual GrTexture* onFilterImageGPU(GrTexture* src, const SkRect& rect) SK_OVERRIDE;
+
 private:
     SkSize   fSigma;
     typedef SkImageFilter INHERITED;
index 5450576..4df90ae 100644 (file)
@@ -18,6 +18,7 @@ public:
 protected:
     SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer);
     virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+    virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
 
     SkISize    radius() const { return fRadius; }
 
@@ -30,9 +31,9 @@ class SK_API SkDilateImageFilter : public SkMorphologyImageFilter {
 public:
     SkDilateImageFilter(int radiusX, int radiusY) : INHERITED(radiusX, radiusY) {}
 
-    virtual bool asADilate(SkISize* radius) const SK_OVERRIDE;
     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
                                SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+    virtual GrTexture* onFilterImageGPU(GrTexture* src, const SkRect& rect) SK_OVERRIDE;
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDilateImageFilter)
 
@@ -47,9 +48,9 @@ class SK_API SkErodeImageFilter : public SkMorphologyImageFilter {
 public:
     SkErodeImageFilter(int radiusX, int radiusY) : INHERITED(radiusX, radiusY) {}
 
-    virtual bool asAnErode(SkISize* radius) const SK_OVERRIDE;
     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
                                SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+    virtual GrTexture* onFilterImageGPU(GrTexture* src, const SkRect& rect) SK_OVERRIDE;
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkErodeImageFilter)
 
index 04a8f5a..94a4d22 100644 (file)
@@ -2280,25 +2280,21 @@ bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
     return false;
 }
 
-bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
-                                   SkIRect* dst) {
-    *dst = src;
-    return true;
-}
-
-bool SkImageFilter::asNewCustomStage(GrCustomStage**, GrTexture*) const {
+bool SkImageFilter::canFilterImageGPU() const {
     return false;
 }
 
-bool SkImageFilter::asABlur(SkSize* sigma) const {
-    return false;
+GrTexture* SkImageFilter::onFilterImageGPU(GrTexture* texture, const SkRect& rect) {
+    return NULL;
 }
 
-bool SkImageFilter::asAnErode(SkISize* radius) const {
-    return false;
+bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
+                                   SkIRect* dst) {
+    *dst = src;
+    return true;
 }
 
-bool SkImageFilter::asADilate(SkISize* radius) const {
+bool SkImageFilter::asNewCustomStage(GrCustomStage**, GrTexture*) const {
     return false;
 }
 
index e3ac346..ed76743 100644 (file)
@@ -8,6 +8,7 @@
 #include "SkBitmap.h"
 #include "SkBlurImageFilter.h"
 #include "SkColorPriv.h"
+#include "GrContext.h"
 
 SkBlurImageFilter::SkBlurImageFilter(SkFlattenableReadBuffer& buffer)
   : INHERITED(buffer) {
@@ -20,11 +21,6 @@ SkBlurImageFilter::SkBlurImageFilter(SkScalar sigmaX, SkScalar sigmaY)
     SkASSERT(sigmaX >= 0 && sigmaY >= 0);
 }
 
-bool SkBlurImageFilter::asABlur(SkSize* sigma) const {
-    *sigma = fSigma;
-    return true;
-}
-
 void SkBlurImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
     this->INHERITED::flatten(buffer);
     buffer.writeScalar(fSigma.fWidth);
@@ -187,4 +183,9 @@ bool SkBlurImageFilter::onFilterImage(Proxy*,
     return true;
 }
 
+GrTexture* SkBlurImageFilter::onFilterImageGPU(GrTexture* src, const SkRect& rect) {
+    return src->getContext()->gaussianBlur(src, false, rect,
+                                           fSigma.width(), fSigma.height());
+}
+
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkBlurImageFilter)
index 869ba6d..3c2e385 100644 (file)
@@ -8,6 +8,8 @@
 #include "SkMorphologyImageFilter.h"
 #include "SkBitmap.h"
 #include "SkColorPriv.h"
+#include "GrContext.h"
+#include "GrTexture.h"
 
 SkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer)
   : INHERITED(buffer) {
@@ -210,14 +212,16 @@ bool SkDilateImageFilter::onFilterImage(Proxy*,
     return true;
 }
 
-bool SkDilateImageFilter::asADilate(SkISize* radius) const {
-    *radius = this->radius();
-    return true;
+GrTexture* SkDilateImageFilter::onFilterImageGPU(GrTexture* src, const SkRect& rect) {
+    return src->getContext()->applyMorphology(src, rect,
+                                              GrContext::kDilate_MorphologyType,
+                                              radius());
 }
 
-bool SkErodeImageFilter::asAnErode(SkISize* radius) const {
-    *radius = this->radius();
-    return true;
+GrTexture* SkErodeImageFilter::onFilterImageGPU(GrTexture* src, const SkRect& rect) {
+    return src->getContext()->applyMorphology(src, rect,
+                                              GrContext::kErode_MorphologyType,
+                                              radius());
 }
 
 SK_DEFINE_FLATTENABLE_REGISTRAR(SkDilateImageFilter)
index 8860d6e..27d3724 100644 (file)
@@ -1501,9 +1501,6 @@ static GrTexture* filter_texture(GrContext* context, GrTexture* texture,
                                  SkImageFilter* filter, const GrRect& rect) {
     GrAssert(filter);
 
-    SkSize blurSize;
-    SkISize radius;
-
     GrTextureDesc desc;
     desc.fFlags = kRenderTarget_GrTextureFlagBit,
     desc.fWidth = SkScalarCeilToInt(rect.width());
@@ -1511,23 +1508,13 @@ static GrTexture* filter_texture(GrContext* context, GrTexture* texture,
     desc.fConfig = kRGBA_8888_PM_GrPixelConfig;
     GrCustomStage* stage;
 
-    if (filter->asNewCustomStage(&stage, texture)) {
+    if (filter->canFilterImageGPU()) {
+        texture = filter->onFilterImageGPU(texture, rect);
+    } else if (filter->asNewCustomStage(&stage, texture)) {
         GrAutoScratchTexture dst(context, desc);
         apply_custom_stage(context, texture, dst.texture(), rect, stage);
         texture = dst.detach();
         stage->unref();
-    } else if (filter->asABlur(&blurSize)) {
-        texture = context->gaussianBlur(texture, false, rect,
-                                        blurSize.width(),
-                                        blurSize.height());
-    } else if (filter->asADilate(&radius)) {
-        texture = context->applyMorphology(texture, rect,
-                                           GrContext::kDilate_MorphologyType,
-                                           radius);
-    } else if (filter->asAnErode(&radius)) {
-        texture = context->applyMorphology(texture, rect,
-                                           GrContext::kErode_MorphologyType,
-                                           radius);
     }
     return texture;
 }
@@ -1635,13 +1622,8 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* device,
 }
 
 bool SkGpuDevice::canHandleImageFilter(SkImageFilter* filter) {
-    SkSize size;
-    SkISize radius;
-
     if (!filter->asNewCustomStage(NULL, NULL) &&
-        !filter->asABlur(&size) &&
-        !filter->asADilate(&radius) &&
-        !filter->asAnErode(&radius)) {
+        !filter->canFilterImageGPU()) {
         return false;
     }
     return true;