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() {}
public:
SkBlurImageFilter(SkScalar sigmaX, SkScalar sigmaY);
- virtual bool asABlur(SkSize* sigma) const SK_OVERRIDE;
-
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurImageFilter)
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;
protected:
SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
+ virtual bool canFilterImageGPU() const SK_OVERRIDE { return true; }
SkISize radius() const { return fRadius; }
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)
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)
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;
}
#include "SkBitmap.h"
#include "SkBlurImageFilter.h"
#include "SkColorPriv.h"
+#include "GrContext.h"
SkBlurImageFilter::SkBlurImageFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {
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);
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)
#include "SkMorphologyImageFilter.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
+#include "GrContext.h"
+#include "GrTexture.h"
SkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {
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)
SkImageFilter* filter, const GrRect& rect) {
GrAssert(filter);
- SkSize blurSize;
- SkISize radius;
-
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit,
desc.fWidth = SkScalarCeilToInt(rect.width());
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;
}
}
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;