| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrBlurUtils.h" | 8 #include "GrBlurUtils.h" |
| 9 #include "GrDrawContext.h" | 9 #include "GrDrawContext.h" |
| 10 #include "GrCaps.h" | 10 #include "GrCaps.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& r
ect) { | 21 static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& r
ect) { |
| 22 return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBo
unds, rect); | 22 return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBo
unds, rect); |
| 23 } | 23 } |
| 24 | 24 |
| 25 // Draw a mask using the supplied paint. Since the coverage/geometry | 25 // Draw a mask using the supplied paint. Since the coverage/geometry |
| 26 // is already burnt into the mask this boils down to a rect draw. | 26 // is already burnt into the mask this boils down to a rect draw. |
| 27 // Return true if the mask was successfully drawn. | 27 // Return true if the mask was successfully drawn. |
| 28 static bool draw_mask(GrDrawContext* drawContext, | 28 static bool draw_mask(GrDrawContext* drawContext, |
| 29 const GrClip& clip, | 29 const GrClip& clip, |
| 30 const SkMatrix& viewMatrix, | 30 const SkMatrix& viewMatrix, |
| 31 const SkRect& maskRect, | 31 const SkIRect& maskRect, |
| 32 GrPaint* grp, | 32 GrPaint* grp, |
| 33 GrTexture* mask) { | 33 GrTexture* mask) { |
| 34 SkMatrix matrix; | 34 SkMatrix matrix; |
| 35 matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop); | 35 matrix.setTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRect.
fTop)); |
| 36 matrix.postIDiv(mask->width(), mask->height()); | 36 matrix.postIDiv(mask->width(), mask->height()); |
| 37 | 37 |
| 38 grp->addCoverageFragmentProcessor(GrSimpleTextureEffect::Create(mask, matrix
, | 38 grp->addCoverageFragmentProcessor(GrSimpleTextureEffect::Create(mask, matrix
, |
| 39 kDevice_GrCo
ordSet))->unref(); | 39 kDevice_GrCo
ordSet))->unref(); |
| 40 | 40 |
| 41 SkMatrix inverse; | 41 SkMatrix inverse; |
| 42 if (!viewMatrix.invert(&inverse)) { | 42 if (!viewMatrix.invert(&inverse)) { |
| 43 return false; | 43 return false; |
| 44 } | 44 } |
| 45 drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), maskRect, in
verse); | 45 drawContext->fillRectWithLocalMatrix(clip, *grp, SkMatrix::I(), |
| 46 SkRect::Make(maskRect), inverse); |
| 46 return true; | 47 return true; |
| 47 } | 48 } |
| 48 | 49 |
| 49 static bool sw_draw_with_mask_filter(GrDrawContext* drawContext, | 50 static bool sw_draw_with_mask_filter(GrDrawContext* drawContext, |
| 50 GrTextureProvider* textureProvider, | 51 GrTextureProvider* textureProvider, |
| 51 const GrClip& clipData, | 52 const GrClip& clipData, |
| 52 const SkMatrix& viewMatrix, | 53 const SkMatrix& viewMatrix, |
| 53 const SkPath& devPath, | 54 const SkPath& devPath, |
| 54 const SkMaskFilter* filter, | 55 const SkMaskFilter* filter, |
| 55 const SkIRect& clipBounds, | 56 const SkIRect& clipBounds, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 79 desc.fHeight = dstM.fBounds.height(); | 80 desc.fHeight = dstM.fBounds.height(); |
| 80 desc.fConfig = kAlpha_8_GrPixelConfig; | 81 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 81 | 82 |
| 82 SkAutoTUnref<GrTexture> texture(textureProvider->createApproxTexture(desc)); | 83 SkAutoTUnref<GrTexture> texture(textureProvider->createApproxTexture(desc)); |
| 83 if (!texture) { | 84 if (!texture) { |
| 84 return false; | 85 return false; |
| 85 } | 86 } |
| 86 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, | 87 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, |
| 87 dstM.fImage, dstM.fRowBytes); | 88 dstM.fImage, dstM.fRowBytes); |
| 88 | 89 |
| 89 SkRect maskRect = SkRect::Make(dstM.fBounds); | 90 return draw_mask(drawContext, clipData, viewMatrix, dstM.fBounds, grp, textu
re); |
| 90 | |
| 91 return draw_mask(drawContext, clipData, viewMatrix, maskRect, grp, texture); | |
| 92 } | 91 } |
| 93 | 92 |
| 94 // Create a mask of 'devPath' and place the result in 'mask'. | 93 // Create a mask of 'devPath' and place the result in 'mask'. |
| 95 static sk_sp<GrTexture> create_mask_GPU(GrContext* context, | 94 static sk_sp<GrTexture> create_mask_GPU(GrContext* context, |
| 96 SkRect* maskRect, | 95 const SkIRect& maskRect, |
| 97 const SkPath& devPath, | 96 const SkPath& devPath, |
| 98 SkStrokeRec::InitStyle fillOrHairline, | 97 SkStrokeRec::InitStyle fillOrHairline, |
| 99 bool doAA, | 98 bool doAA, |
| 100 int sampleCnt) { | 99 int sampleCnt) { |
| 101 // This mask will ultimately be drawn as a non-AA rect (see draw_mask). | |
| 102 // Non-AA rects have a bad habit of snapping arbitrarily. Integerize here | |
| 103 // so the mask draws in a reproducible manner. | |
| 104 *maskRect = SkRect::Make(maskRect->roundOut()); | |
| 105 | |
| 106 if (!doAA) { | 100 if (!doAA) { |
| 107 // Don't need MSAA if mask isn't AA | 101 // Don't need MSAA if mask isn't AA |
| 108 sampleCnt = 0; | 102 sampleCnt = 0; |
| 109 } | 103 } |
| 110 | 104 |
| 111 // We actually only need A8, but it often isn't supported as a | 105 // We actually only need A8, but it often isn't supported as a |
| 112 // render target so default to RGBA_8888 | 106 // render target so default to RGBA_8888 |
| 113 GrPixelConfig config = kRGBA_8888_GrPixelConfig; | 107 GrPixelConfig config = kRGBA_8888_GrPixelConfig; |
| 114 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, sampleCnt >
0)) { | 108 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, sampleCnt >
0)) { |
| 115 config = kAlpha_8_GrPixelConfig; | 109 config = kAlpha_8_GrPixelConfig; |
| 116 } | 110 } |
| 117 | 111 |
| 118 sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kAppr
ox, | 112 sk_sp<GrDrawContext> drawContext(context->newDrawContext(SkBackingFit::kAppr
ox, |
| 119 SkScalarCeilToInt(m
askRect->width()), | 113 maskRect.width(), |
| 120 SkScalarCeilToInt(m
askRect->height()), | 114 maskRect.height(), |
| 121 config, | 115 config, |
| 122 sampleCnt)); | 116 sampleCnt)); |
| 123 if (!drawContext) { | 117 if (!drawContext) { |
| 124 return nullptr; | 118 return nullptr; |
| 125 } | 119 } |
| 126 | 120 |
| 127 drawContext->clear(nullptr, 0x0, true); | 121 drawContext->clear(nullptr, 0x0, true); |
| 128 | 122 |
| 129 GrPaint tempPaint; | 123 GrPaint tempPaint; |
| 130 tempPaint.setAntiAlias(doAA); | 124 tempPaint.setAntiAlias(doAA); |
| 131 tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); | 125 tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); |
| 132 | 126 |
| 133 // setup new clip | 127 // setup new clip |
| 134 const SkRect clipRect = SkRect::MakeWH(maskRect->width(), maskRect->height()
); | 128 const SkRect clipRect = SkRect::MakeIWH(maskRect.width(), maskRect.height())
; |
| 135 GrClip clip(clipRect); | 129 GrClip clip(clipRect); |
| 136 | 130 |
| 137 // Draw the mask into maskTexture with the path's integerized top-left at | 131 // Draw the mask into maskTexture with the path's integerized top-left at |
| 138 // the origin using tempPaint. | 132 // the origin using tempPaint. |
| 139 SkMatrix translate; | 133 SkMatrix translate; |
| 140 translate.setTranslate(-maskRect->fLeft, -maskRect->fTop); | 134 translate.setTranslate(-SkIntToScalar(maskRect.fLeft), -SkIntToScalar(maskRe
ct.fTop)); |
| 141 drawContext->drawPath(clip, tempPaint, translate, devPath, GrStyle(fillOrHai
rline)); | 135 drawContext->drawPath(clip, tempPaint, translate, devPath, GrStyle(fillOrHai
rline)); |
| 142 return drawContext->asTexture();; | 136 return drawContext->asTexture();; |
| 143 } | 137 } |
| 144 | 138 |
| 145 static void draw_path_with_mask_filter(GrContext* context, | 139 static void draw_path_with_mask_filter(GrContext* context, |
| 146 GrDrawContext* drawContext, | 140 GrDrawContext* drawContext, |
| 147 const GrClip& clip, | 141 const GrClip& clip, |
| 148 GrPaint* paint, | 142 GrPaint* paint, |
| 149 const SkMatrix& viewMatrix, | 143 const SkMatrix& viewMatrix, |
| 150 const SkMaskFilter* maskFilter, | 144 const SkMaskFilter* maskFilter, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 path = result; | 182 path = result; |
| 189 result->setIsVolatile(true); | 183 result->setIsVolatile(true); |
| 190 pathIsMutable = true; | 184 pathIsMutable = true; |
| 191 } | 185 } |
| 192 | 186 |
| 193 SkRect maskRect; | 187 SkRect maskRect; |
| 194 if (maskFilter->canFilterMaskGPU(SkRRect::MakeRect(path->getBounds()), | 188 if (maskFilter->canFilterMaskGPU(SkRRect::MakeRect(path->getBounds()), |
| 195 clipBounds, | 189 clipBounds, |
| 196 viewMatrix, | 190 viewMatrix, |
| 197 &maskRect)) { | 191 &maskRect)) { |
| 192 // This mask will ultimately be drawn as a non-AA rect (see draw_mask). |
| 193 // Non-AA rects have a bad habit of snapping arbitrarily. Integerize her
e |
| 194 // so the mask draws in a reproducible manner. |
| 198 SkIRect finalIRect; | 195 SkIRect finalIRect; |
| 199 maskRect.roundOut(&finalIRect); | 196 maskRect.roundOut(&finalIRect); |
| 200 if (clip_bounds_quick_reject(clipBounds, finalIRect)) { | 197 if (clip_bounds_quick_reject(clipBounds, finalIRect)) { |
| 201 // clipped out | 198 // clipped out |
| 202 return; | 199 return; |
| 203 } | 200 } |
| 204 | 201 |
| 205 if (maskFilter->directFilterMaskGPU(context->textureProvider(), | 202 if (maskFilter->directFilterMaskGPU(context->textureProvider(), |
| 206 drawContext, | 203 drawContext, |
| 207 paint, | 204 paint, |
| 208 clip, | 205 clip, |
| 209 viewMatrix, | 206 viewMatrix, |
| 210 SkStrokeRec(fillOrHairline), | 207 SkStrokeRec(fillOrHairline), |
| 211 *path)) { | 208 *path)) { |
| 212 // the mask filter was able to draw itself directly, so there's noth
ing | 209 // the mask filter was able to draw itself directly, so there's noth
ing |
| 213 // left to do. | 210 // left to do. |
| 214 return; | 211 return; |
| 215 } | 212 } |
| 216 | 213 |
| 217 sk_sp<GrTexture> mask(create_mask_GPU(context, | 214 sk_sp<GrTexture> mask(create_mask_GPU(context, |
| 218 &maskRect, | 215 finalIRect, |
| 219 *path, | 216 *path, |
| 220 fillOrHairline, | 217 fillOrHairline, |
| 221 paint->isAntiAlias(), | 218 paint->isAntiAlias(), |
| 222 drawContext->numColorSamples())); | 219 drawContext->numColorSamples())); |
| 223 if (mask) { | 220 if (mask) { |
| 224 GrTexture* filtered; | 221 GrTexture* filtered; |
| 225 | 222 |
| 226 if (maskFilter->filterMaskGPU(mask.get(), viewMatrix, maskRect, &fil
tered, true)) { | 223 if (maskFilter->filterMaskGPU(mask.get(), viewMatrix, finalIRect, &f
iltered, true)) { |
| 227 // filterMaskGPU gives us ownership of a ref to the result | 224 // filterMaskGPU gives us ownership of a ref to the result |
| 228 SkAutoTUnref<GrTexture> atu(filtered); | 225 SkAutoTUnref<GrTexture> atu(filtered); |
| 229 if (draw_mask(drawContext, clip, viewMatrix, maskRect, paint, fi
ltered)) { | 226 if (draw_mask(drawContext, clip, viewMatrix, finalIRect, paint,
filtered)) { |
| 230 // This path is completely drawn | 227 // This path is completely drawn |
| 231 return; | 228 return; |
| 232 } | 229 } |
| 233 } | 230 } |
| 234 } | 231 } |
| 235 } | 232 } |
| 236 | 233 |
| 237 sw_draw_with_mask_filter(drawContext, context->textureProvider(), | 234 sw_draw_with_mask_filter(drawContext, context->textureProvider(), |
| 238 clip, viewMatrix, *path, | 235 clip, viewMatrix, *path, |
| 239 maskFilter, clipBounds, paint, fillOrHairline); | 236 maskFilter, clipBounds, paint, fillOrHairline); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 } | 292 } |
| 296 | 293 |
| 297 if (paint.getMaskFilter()) { | 294 if (paint.getMaskFilter()) { |
| 298 draw_path_with_mask_filter(context, drawContext, clip, &grPaint, viewMat
rix, | 295 draw_path_with_mask_filter(context, drawContext, clip, &grPaint, viewMat
rix, |
| 299 paint.getMaskFilter(), style, | 296 paint.getMaskFilter(), style, |
| 300 path, pathIsMutable); | 297 path, pathIsMutable); |
| 301 } else { | 298 } else { |
| 302 drawContext->drawPath(clip, grPaint, viewMatrix, *path, style); | 299 drawContext->drawPath(clip, grPaint, viewMatrix, *path, style); |
| 303 } | 300 } |
| 304 } | 301 } |
| OLD | NEW |