Index: src/gpu/GrBlurUtils.cpp |
diff --git a/src/gpu/GrBlurUtils.cpp b/src/gpu/GrBlurUtils.cpp |
index c6cff60b342377b1bd7c82003ee7e048086ac823..54689247d2371896143a66002a5a5d16ae7720fa 100644 |
--- a/src/gpu/GrBlurUtils.cpp |
+++ b/src/gpu/GrBlurUtils.cpp |
@@ -36,7 +36,7 @@ static bool draw_mask(GrDrawContext* drawContext, |
matrix.postIDiv(mask->width(), mask->height()); |
grp->addCoverageFragmentProcessor(GrSimpleTextureEffect::Create(mask, matrix, |
- kDevice_GrCoordSet))->unref(); |
+ kDevice_GrCoordSet, drawContext->rt_remove_me()))->unref(); |
SkMatrix inverse; |
if (!viewMatrix.invert(&inverse)) { |
@@ -84,15 +84,21 @@ static bool draw_with_mask_filter(GrDrawContext* drawContext, |
if (!texture) { |
return false; |
} |
- texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, |
+ texture->writePixels(NULL, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig, |
dstM.fImage, dstM.fRowBytes); |
+ texture->setFromRawPixels(true); |
+ texture->setException(true); |
+ |
SkRect maskRect = SkRect::Make(dstM.fBounds); |
return draw_mask(drawContext, clipData, viewMatrix, maskRect, grp, texture); |
} |
// Create a mask of 'devPath' and place the result in 'mask'. |
+// If this returns non-NULL then 'outputDrawContext' will be set to the |
+// drawContext used to create it (and it will have an associated rendertarget). |
+// TODO: just return drawContext? |
static GrTexture* create_mask_GPU(GrContext* context, |
SkRect* maskRect, |
const SkPath& devPath, |
@@ -315,7 +321,7 @@ void GrBlurUtils::drawPathWithMaskFilter(GrContext* context, |
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) |
GrPaint grPaint; |
- if (!SkPaintToGrPaint(context, paint, viewMatrix, &grPaint)) { |
+ if (!SkPaintToGrPaint(context, paint, viewMatrix, &grPaint, renderTarget)) { |
return; |
} |
@@ -331,7 +337,79 @@ void GrBlurUtils::drawPathWithMaskFilter(GrContext* context, |
pathPtr->setIsVolatile(true); |
pathIsMutable = true; |
} |
+#if 1 |
drawContext->drawPath(clip, grPaint, viewMatrix, *pathPtr, strokeInfo); |
+#else |
+ // avoid possibly allocating a new path in transform if we can |
+ SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init(); |
+ if (!pathIsMutable) { |
+ devPathPtr->setIsVolatile(true); |
+ } |
+ |
+ // transform the path into device space |
+ pathPtr->transform(viewMatrix, devPathPtr); |
+ |
+ SkRect maskRect; |
+ if (paint.getMaskFilter()->canFilterMaskGPU(SkRRect::MakeRect(devPathPtr->getBounds()), |
+ clipBounds, |
+ viewMatrix, |
+ &maskRect)) { |
+ SkIRect finalIRect; |
+ maskRect.roundOut(&finalIRect); |
+ if (clip_bounds_quick_reject(clipBounds, finalIRect)) { |
+ // clipped out |
+ return; |
+ } |
+ |
+ if (paint.getMaskFilter()->directFilterMaskGPU(context->textureProvider(), |
+ drawContext, |
+ &grPaint, |
+ clip, |
+ viewMatrix, |
+ strokeInfo, |
+ *devPathPtr)) { |
+ // the mask filter was able to draw itself directly, so there's nothing |
+ // left to do. |
+ return; |
+ } |
+ |
+ SkAutoTUnref<GrTexture> mask(create_mask_GPU(context, |
+ &maskRect, |
+ *devPathPtr, |
+ strokeInfo, |
+ grPaint.isAntiAlias(), |
+ renderTarget->numColorSamples())); |
+ if (mask) { |
+ SkASSERT(mask->asRenderTarget()); |
+ |
+ GrTexture* filtered; |
+ |
+ if (paint.getMaskFilter()->filterMaskGPU(mask, viewMatrix, maskRect, |
+ &filtered, true)) { |
+ // filterMaskGPU gives us ownership of a ref to the result |
+ SkAutoTUnref<GrTexture> atu(filtered); |
+ if (draw_mask(drawContext, |
+ clip, |
+ viewMatrix, |
+ maskRect, |
+ &grPaint, |
+ filtered)) { |
+ // This path is completely drawn |
+ return; |
+ } |
+ } |
+ } |
+ } |
+ |
+ // draw the mask on the CPU - this is a fallthrough path in case the |
+ // GPU path fails |
+ SkPaint::Style style = strokeInfo.isHairlineStyle() ? SkPaint::kStroke_Style : |
+ SkPaint::kFill_Style; |
+ draw_with_mask_filter(drawContext, context->textureProvider(), |
+ clip, viewMatrix, *devPathPtr, |
+ paint.getMaskFilter(), clipBounds, &grPaint, style); |
+ return; |
+#endif |
} |
} |