Bug 884888 - Fix shadow drawing in SkiaGL r=snorp
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 27 Jun 2013 11:22:09 +1200
changeset 139189 b3d8eb2515762b43bf2d2e9b42df39ab4a87f474
parent 139188 2293c4eea18e45c1d8ee9e06e65e2c297acd9ed4
child 139190 ad853510b4d5ad26254efd2faa7a80112d69791b
push id24980
push userryanvm@gmail.com
push dateFri, 19 Jul 2013 17:42:29 +0000
treeherdermozilla-central@0983f1a0961c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs884888
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 884888 - Fix shadow drawing in SkiaGL r=snorp
gfx/skia/src/gpu/SkGpuDevice.cpp
--- a/gfx/skia/src/gpu/SkGpuDevice.cpp
+++ b/gfx/skia/src/gpu/SkGpuDevice.cpp
@@ -18,16 +18,17 @@
 #include "SkColorFilter.h"
 #include "SkDeviceImageFilterProxy.h"
 #include "SkDrawProcs.h"
 #include "SkGlyphCache.h"
 #include "SkImageFilter.h"
 #include "SkPathEffect.h"
 #include "SkStroke.h"
 #include "SkUtils.h"
+#include "SkRasterizer.h"
 
 #define CACHE_COMPATIBLE_DEVICE_TEXTURES 1
 
 #if 0
     extern bool (*gShouldDrawProc)();
     #define CHECK_SHOULD_DRAW(draw, forceI)                     \
         do {                                                    \
             if (gShouldDrawProc && !gShouldDrawProc()) return;  \
@@ -662,18 +663,20 @@ void SkGpuDevice::drawRect(const SkDraw&
     SkScalar width = paint.getStrokeWidth();
 
     /*
         We have special code for hairline strokes, miter-strokes, and fills.
         Anything else we just call our path code.
      */
     bool usePath = doStroke && width > 0 &&
                     paint.getStrokeJoin() != SkPaint::kMiter_Join;
-    // another two reasons we might need to call drawPath...
-    if (paint.getMaskFilter() || paint.getPathEffect()) {
+    // another three reasons we might need to call drawPath...
+    if (paint.getMaskFilter() ||
+        paint.getPathEffect() ||
+        paint.getRasterizer()) {
         usePath = true;
     }
     // until we aa rotated rects...
     if (!usePath && paint.isAntiAlias() && !fContext->getMatrix().rectStaysRect()) {
         usePath = true;
     }
     // small miter limit means right angles show bevel...
     if (SkPaint::kMiter_Join == paint.getStrokeJoin() &&
@@ -744,32 +747,43 @@ inline bool shouldDrawBlurWithCPU(const 
     if (rect.width() <= MIN_GPU_BLUR_SIZE &&
         rect.height() <= MIN_GPU_BLUR_SIZE &&
         radius <= MIN_GPU_BLUR_RADIUS) {
         return true;
     }
     return false;
 }
 
-bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath, const SkStrokeRec& stroke,
-                           SkMaskFilter* filter, const SkRegion& clip,
+bool drawWithGPUMaskFilter(GrContext* context, SkPath& path, bool pathIsMutable,
+                           const SkStrokeRec& stroke, SkMaskFilter* filter,
+                           SkRasterizer *rasterizer, const SkRegion& clip,
                            SkBounder* bounder, GrPaint* grp) {
+    if (rasterizer) {
+        return false;
+    }
+
     SkMaskFilter::BlurInfo info;
     SkMaskFilter::BlurType blurType = filter->asABlur(&info);
     if (SkMaskFilter::kNone_BlurType == blurType) {
         return false;
     }
     SkScalar radius = info.fIgnoreTransform ? info.fRadius
                                             : context->getMatrix().mapRadius(info.fRadius);
     radius = SkMinScalar(radius, MAX_BLUR_RADIUS);
     if (radius <= 0) {
         return false;
     }
 
-    SkRect srcRect = devPath.getBounds();
+    SkPath tmpPath;
+    SkPath* devPathPtr = pathIsMutable ? &path : &tmpPath;
+
+    // transform the path into device space
+    path.transform(context->getMatrix(), devPathPtr);
+
+    SkRect srcRect = devPathPtr->getBounds();
     if (shouldDrawBlurWithCPU(srcRect, radius)) {
         return false;
     }
 
     float sigma = SkScalarToFloat(radius) * BLUR_SIGMA_SCALE;
     float sigma3 = sigma * 3.0f;
 
     SkRect clipRect;
@@ -829,17 +843,17 @@ bool drawWithGPUMaskFilter(GrContext* co
         }
 
         GrContext::AutoMatrix am;
 
         // Draw hard shadow to pathTexture with path top-left at origin using tempPaint.
         SkMatrix translate;
         translate.setTranslate(offset.fX, offset.fY);
         am.set(context, translate);
-        context->drawPath(tempPaint, devPath, stroke);
+        context->drawPath(tempPaint, *devPathPtr, stroke);
 
         // If we're doing a normal blur, we can clobber the pathTexture in the
         // gaussianBlur.  Otherwise, we need to save it for later compositing.
         bool isNormalBlur = blurType == SkMaskFilter::kNormal_BlurType;
         blurTexture.reset(context->gaussianBlur(pathTexture, isNormalBlur,
                                                 srcRect, sigma, sigma));
         if (NULL == blurTexture) {
             return false;
@@ -885,32 +899,52 @@ bool drawWithGPUMaskFilter(GrContext* co
 
     grp->coverageStage(MASK_IDX)->reset();
     grp->coverageStage(MASK_IDX)->setEffect(
         GrSimpleTextureEffect::Create(blurTexture, matrix))->unref();
     context->drawRect(*grp, finalRect);
     return true;
 }
 
-bool drawWithMaskFilter(GrContext* context, const SkPath& devPath,
-                        SkMaskFilter* filter, const SkRegion& clip, SkBounder* bounder,
+bool drawWithMaskFilter(GrContext* context, SkPath& path, bool pathIsMutable,
+                        SkMaskFilter* filter, SkRasterizer* rasterizer,
+                        const SkRegion& clip, SkBounder* bounder,
                         GrPaint* grp, SkPaint::Style style) {
     SkMask  srcM, dstM;
 
-    if (!SkDraw::DrawToMask(devPath, &clip.getBounds(), filter, &context->getMatrix(), &srcM,
-                            SkMask::kComputeBoundsAndRenderImage_CreateMode, style)) {
-        return false;
+    if (rasterizer) {
+        if (!rasterizer->rasterize(path, context->getMatrix(),
+                                   &clip.getBounds(), filter, &srcM,
+                                   SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
+            return false;
+        }
+    } else {
+        SkPath tmpPath;
+        SkPath* devPathPtr = pathIsMutable ? &path : &tmpPath;
+
+        // transform the path into device space
+        path.transform(context->getMatrix(), devPathPtr);
+        if (!SkDraw::DrawToMask(*devPathPtr, &clip.getBounds(), filter, &context->getMatrix(),
+                                &srcM, SkMask::kComputeBoundsAndRenderImage_CreateMode,
+                                style)) {
+            return false;
+        }
     }
     SkAutoMaskFreeImage autoSrc(srcM.fImage);
 
-    if (!filter->filterMask(&dstM, srcM, context->getMatrix(), NULL)) {
+    if (filter && !filter->filterMask(&dstM, srcM, context->getMatrix(), NULL)) {
         return false;
+    } else if (!filter) {
+        dstM = srcM;
     }
-    // this will free-up dstM when we're done (allocated in filterMask())
-    SkAutoMaskFreeImage autoDst(dstM.fImage);
+
+    // this will free-up dstM when we're done (allocated in filterMask()).
+    // If we don't have a filter, then srcM and dstM are the same, so
+    // don't free it twice.
+    SkAutoMaskFreeImage autoDst(filter ? dstM.fImage : NULL);
 
     if (clip.quickReject(dstM.fBounds)) {
         return false;
     }
     if (bounder && !bounder->doIRect(dstM.fBounds)) {
         return false;
     }
 
@@ -1003,34 +1037,32 @@ void SkGpuDevice::drawPath(const SkDraw&
                                              cullRect)) {
         pathPtr = &effectPath;
     }
 
     if (!pathEffect && doHairLine) {
         stroke.setHairlineStyle();
     }
 
-    if (paint.getMaskFilter()) {
+    if (paint.getMaskFilter() || paint.getRasterizer()) {
         if (!stroke.isHairlineStyle()) {
             if (stroke.applyToPath(&tmpPath, *pathPtr)) {
                 pathPtr = &tmpPath;
                 stroke.setFillStyle();
             }
         }
 
-        // avoid possibly allocating a new path in transform if we can
-        SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
-
-        // transform the path into device space
-        pathPtr->transform(fContext->getMatrix(), devPathPtr);
-        if (!drawWithGPUMaskFilter(fContext, *devPathPtr, stroke, paint.getMaskFilter(),
-                                   *draw.fClip, draw.fBounder, &grPaint)) {
+        if (!drawWithGPUMaskFilter(fContext, *pathPtr, pathIsMutable,
+                                   stroke, paint.getMaskFilter(),
+                                   paint.getRasterizer(), *draw.fClip,
+                                   draw.fBounder, &grPaint)) {
             SkPaint::Style style = stroke.isHairlineStyle() ? SkPaint::kStroke_Style :
                                                               SkPaint::kFill_Style;
-            drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
+            drawWithMaskFilter(fContext, *pathPtr, pathIsMutable,
+                               paint.getMaskFilter(), paint.getRasterizer(),
                                *draw.fClip, draw.fBounder, &grPaint, style);
         }
         return;
     }
 
     fContext->drawPath(grPaint, *pathPtr, stroke);
 }