diff options
-rw-r--r-- | include/core/SkMaskFilter.h | 56 | ||||
-rw-r--r-- | src/core/SkMaskFilter.cpp | 53 | ||||
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 5 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 4 |
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); |