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:
parent
a2d71482db
commit
302cffba86
@ -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() {}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user