aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkMaskFilter.h56
-rw-r--r--src/core/SkMaskFilter.cpp53
-rw-r--r--src/effects/SkBlurMaskFilter.cpp5
-rw-r--r--src/gpu/SkGpuDevice.cpp4
4 files changed, 35 insertions, 83 deletions
diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h
index f4448ddddb..ce0debd442 100644
--- a/include/core/SkMaskFilter.h
+++ b/include/core/SkMaskFilter.h
@@ -63,25 +63,30 @@ public:
#if SK_SUPPORT_GPU
/**
- * Returns true if the filter can be expressed a single-pass
- * GrEffect, used to process this filter on the GPU, or false if
- * not.
+ * Returns true if the filter can be expressed a single-pass GrEffect without requiring an
+ * explicit input mask. Per-pixel, the effect receives the incoming mask's coverage as
+ * the input color and outputs the filtered covereage value. This means that each pixel's
+ * filtered coverage must only depend on the unfiltered mask value for that pixel and not on
+ * surrounding values.
*
- * If effect is non-NULL, a new GrEffect instance is stored
- * in it. The caller assumes ownership of the stage, and it is up to the
- * caller to unref it.
+ * If effect is non-NULL, a new GrEffect instance is stored in it. The caller assumes ownership
+ * of the effect and must unref it.
*/
- virtual bool asNewEffect(GrEffectRef** effect, GrTexture*) const;
+ virtual bool asNewEffect(GrEffectRef** effect,
+ GrTexture*,
+ const SkMatrix& ctm) const;
/**
- * 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 asNewEffect().
+ * If asNewEffect() fails the filter may be implemented on the GPU by a subclass overriding
+ * filterMaskGPU (declared below). That code path requires constructing a src mask as input.
+ * Since that is a potentially expensive operation, the subclass must also override this
+ * function to indicate whether filterTextureMaskGPU would succeeed if the mask were to be
+ * created.
*
- * 'maskRect' returns the device space portion of the mask the the filter
- * needs. The mask passed into 'filterMaskGPU' should have the same extent
- * as 'maskRect' but be translated to the upper-left corner of the mask
- * (i.e., (maskRect.fLeft, maskRect.fTop) appears at (0, 0) in the mask).
+ * 'maskRect' returns the device space portion of the mask that the filter needs. The mask
+ * passed into 'filterMaskGPU' should have the same extent as 'maskRect' but be translated
+ * to the upper-left corner of the mask (i.e., (maskRect.fLeft, maskRect.fTop) appears at
+ * (0, 0) in the mask).
*/
virtual bool canFilterMaskGPU(const SkRect& devBounds,
const SkIRect& clipBounds,
@@ -89,24 +94,15 @@ public:
SkRect* maskRect) const;
/**
- * Perform this mask filter 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 asNewEffect(). 'src' is the
- * source image for processing, as a texture-backed bitmap. 'result' is
- * the destination bitmap, which should contain a texture-backed pixelref
- * on success. 'maskRect' should be the rect returned from canFilterMaskGPU.
- */
- bool filterMaskGPU(GrContext* context,
- const SkBitmap& src,
- const SkRect& maskRect,
- SkBitmap* result) const;
-
- /**
- * This flavor of 'filterMaskGPU' provides a more direct means of accessing
- * the filtering capabilities. Setting 'canOverwriteSrc' can allow some
- * filters to skip the allocation of an additional texture.
+ * This function is used to implement filters that require an explicit src mask. It should only
+ * be called if canFilterMaskGPU returned true and the maskRect param should be the output from
+ * that call. canOverwriteSrc indicates whether the implementation may treat src as a scratch
+ * texture and overwrite its contents. When true it is also legal to return src as the result.
+ * Implementations are free to get the GrContext from the src texture in order to create
+ * additional textures and perform multiple passes.
*/
virtual bool filterMaskGPU(GrTexture* src,
+ const SkMatrix& ctm,
const SkRect& maskRect,
GrTexture** result,
bool canOverwriteSrc) const;
diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp
index 1bc17bb47f..ebcdbea4d2 100644
--- a/src/core/SkMaskFilter.cpp
+++ b/src/core/SkMaskFilter.cpp
@@ -298,7 +298,7 @@ SkMaskFilter::filterRectsToNine(const SkRect[], int count, const SkMatrix&,
}
#if SK_SUPPORT_GPU
-bool SkMaskFilter::asNewEffect(GrEffectRef** effect, GrTexture*) const {
+bool SkMaskFilter::asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix&) const {
return false;
}
@@ -309,58 +309,9 @@ bool SkMaskFilter::canFilterMaskGPU(const SkRect& devBounds,
return false;
}
-bool SkMaskFilter::filterMaskGPU(GrContext* context,
- const SkBitmap& srcBM,
- const SkRect& maskRect,
- SkBitmap* resultBM) const {
- SkAutoTUnref<GrTexture> src;
- bool canOverwriteSrc = false;
- if (NULL == srcBM.getTexture()) {
- GrTextureDesc desc;
- // Needs to be a render target to be overwritten in filterMaskGPU
- desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
- desc.fConfig = SkBitmapConfig2GrPixelConfig(srcBM.config());
- desc.fWidth = srcBM.width();
- desc.fHeight = srcBM.height();
-
- // TODO: right now this is exact to guard against out of bounds reads
- // by the filter code. More thought needs to be devoted to the
- // "filterMaskGPU" contract and then enforced (i.e., clamp the code
- // in "filterMaskGPU" so it never samples beyond maskRect)
- GrAutoScratchTexture ast(context, desc, GrContext::kExact_ScratchTexMatch);
- if (NULL == ast.texture()) {
- return false;
- }
-
- SkAutoLockPixels alp(srcBM);
- ast.texture()->writePixels(0, 0, srcBM.width(), srcBM.height(),
- desc.fConfig,
- srcBM.getPixels(), srcBM.rowBytes());
-
- src.reset(ast.detach());
- canOverwriteSrc = true;
- } else {
- src.reset((GrTexture*) srcBM.getTexture());
- src.get()->ref();
- }
- GrTexture* dst;
-
- bool result = this->filterMaskGPU(src, maskRect, &dst, canOverwriteSrc);
- if (!result) {
- return false;
- }
- SkAutoUnref aur(dst);
-
- SkImageInfo info;
- resultBM->setConfig(srcBM.config(), dst->width(), dst->height());
- if (!resultBM->asImageInfo(&info)) {
- return false;
- }
- resultBM->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, dst)))->unref();
- return true;
-}
bool SkMaskFilter::filterMaskGPU(GrTexture* src,
+ const SkMatrix& ctm,
const SkRect& maskRect,
GrTexture** result,
bool canOverwriteSrc) const {
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index d2c43d719b..f4d032f08f 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -38,9 +38,10 @@ public:
const SkMatrix& ctm,
SkRect* maskRect) const SK_OVERRIDE;
virtual bool filterMaskGPU(GrTexture* src,
+ const SkMatrix& ctm,
const SkRect& maskRect,
GrTexture** result,
- bool canOverwriteSrc) const;
+ bool canOverwriteSrc) const SK_OVERRIDE;
#endif
virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE;
@@ -540,6 +541,7 @@ bool SkBlurMaskFilterImpl::canFilterMaskGPU(const SkRect& srcBounds,
}
bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
+ const SkMatrix& matrix,
const SkRect& maskRect,
GrTexture** result,
bool canOverwriteSrc) const {
@@ -549,6 +551,7 @@ bool SkBlurMaskFilterImpl::filterMaskGPU(GrTexture* src,
GrContext::AutoWideOpenIdentityDraw awo(context, NULL);
+ // FIXME: This isn't the right matrix.
SkScalar xformedSigma = this->computeXformedSigma(context->getMatrix());
SkASSERT(xformedSigma > 0);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 25aacca509..86c8ba90f8 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -939,7 +939,9 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
grPaint.isAntiAlias(), &mask)) {
GrTexture* filtered;
- if (paint.getMaskFilter()->filterMaskGPU(mask.texture(), maskRect, &filtered, true)) {
+ if (paint.getMaskFilter()->filterMaskGPU(mask.texture(),
+ fContext->getMatrix(), maskRect,
+ &filtered, true)) {
// filterMaskGPU gives us ownership of a ref to the result
SkAutoTUnref<GrTexture> atu(filtered);