Replace the asAFoo() functions in SkImageFilter with canFilterImageGPU() and

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
This commit is contained in:
senorblanco@chromium.org 2012-08-01 20:16:34 +00:00
parent a2d71482db
commit 302cffba86
7 changed files with 45 additions and 67 deletions

View 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.
* 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 asABlur(SkSize* sigma) const;
virtual bool canFilterImageGPU() const;
/**
* Experimental.
*
* If the filter can be expressed as an erode, 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 asAnErode(SkISize* radius) const;
/**
* Experimental.
*
* If the filter can be expressed as a dilation, return true and
* set the radius in X and Y.
*/
virtual bool asADilate(SkISize* radius) const;
virtual GrTexture* onFilterImageGPU(GrTexture* texture, const SkRect& rect);
protected:
SkImageFilter() {}

View 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;

View 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)

View File

@ -2280,6 +2280,14 @@ bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
return false;
}
bool SkImageFilter::canFilterImageGPU() const {
return false;
}
GrTexture* SkImageFilter::onFilterImageGPU(GrTexture* texture, const SkRect& rect) {
return NULL;
}
bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
SkIRect* dst) {
*dst = src;
@ -2290,18 +2298,6 @@ bool SkImageFilter::asNewCustomStage(GrCustomStage**, GrTexture*) const {
return false;
}
bool SkImageFilter::asABlur(SkSize* sigma) const {
return false;
}
bool SkImageFilter::asAnErode(SkISize* radius) const {
return false;
}
bool SkImageFilter::asADilate(SkISize* radius) const {
return false;
}
////////////////////
SK_DEFINE_INST_COUNT(SkDrawLooper)

View 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)

View 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)

View 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;