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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 } | 47 } |
48 | 48 |
49 static bool sw_draw_with_mask_filter(GrDrawContext* drawContext, | 49 static bool sw_draw_with_mask_filter(GrDrawContext* drawContext, |
50 GrTextureProvider* textureProvider, | 50 GrTextureProvider* textureProvider, |
51 const GrClip& clipData, | 51 const GrClip& clipData, |
52 const SkMatrix& viewMatrix, | 52 const SkMatrix& viewMatrix, |
53 const SkPath& devPath, | 53 const SkPath& devPath, |
54 const SkMaskFilter* filter, | 54 const SkMaskFilter* filter, |
55 const SkIRect& clipBounds, | 55 const SkIRect& clipBounds, |
56 GrPaint* grp, | 56 GrPaint* grp, |
57 SkPaint::Style style) { | 57 SkStrokeRec::InitStyle style) { |
58 SkMask srcM, dstM; | 58 SkMask srcM, dstM; |
59 | 59 |
60 if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM, | 60 if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM, |
61 SkMask::kComputeBoundsAndRenderImage_CreateMode, sty
le)) { | 61 SkMask::kComputeBoundsAndRenderImage_CreateMode, sty
le)) { |
62 return false; | 62 return false; |
63 } | 63 } |
64 SkAutoMaskFreeImage autoSrc(srcM.fImage); | 64 SkAutoMaskFreeImage autoSrc(srcM.fImage); |
65 | 65 |
66 if (!filter->filterMask(&dstM, srcM, viewMatrix, nullptr)) { | 66 if (!filter->filterMask(&dstM, srcM, viewMatrix, nullptr)) { |
67 return false; | 67 return false; |
(...skipping 21 matching lines...) Expand all Loading... |
89 | 89 |
90 SkRect maskRect = SkRect::Make(dstM.fBounds); | 90 SkRect maskRect = SkRect::Make(dstM.fBounds); |
91 | 91 |
92 return draw_mask(drawContext, clipData, viewMatrix, maskRect, grp, texture); | 92 return draw_mask(drawContext, clipData, viewMatrix, maskRect, grp, texture); |
93 } | 93 } |
94 | 94 |
95 // Create a mask of 'devPath' and place the result in 'mask'. | 95 // Create a mask of 'devPath' and place the result in 'mask'. |
96 static sk_sp<GrTexture> create_mask_GPU(GrContext* context, | 96 static sk_sp<GrTexture> create_mask_GPU(GrContext* context, |
97 SkRect* maskRect, | 97 SkRect* maskRect, |
98 const SkPath& devPath, | 98 const SkPath& devPath, |
99 const GrStrokeInfo& strokeInfo, | 99 SkStrokeRec::InitStyle style, |
100 bool doAA, | 100 bool doAA, |
101 int sampleCnt) { | 101 int sampleCnt) { |
102 // This mask will ultimately be drawn as a non-AA rect (see draw_mask). | 102 // This mask will ultimately be drawn as a non-AA rect (see draw_mask). |
103 // Non-AA rects have a bad habit of snapping arbitrarily. Integerize here | 103 // Non-AA rects have a bad habit of snapping arbitrarily. Integerize here |
104 // so the mask draws in a reproducible manner. | 104 // so the mask draws in a reproducible manner. |
105 *maskRect = SkRect::Make(maskRect->roundOut()); | 105 *maskRect = SkRect::Make(maskRect->roundOut()); |
106 | 106 |
107 if (!doAA) { | 107 if (!doAA) { |
108 // Don't need MSAA if mask isn't AA | 108 // Don't need MSAA if mask isn't AA |
109 sampleCnt = 0; | 109 sampleCnt = 0; |
(...skipping 22 matching lines...) Expand all Loading... |
132 tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); | 132 tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op); |
133 | 133 |
134 // setup new clip | 134 // setup new clip |
135 const SkRect clipRect = SkRect::MakeWH(maskRect->width(), maskRect->height()
); | 135 const SkRect clipRect = SkRect::MakeWH(maskRect->width(), maskRect->height()
); |
136 GrClip clip(clipRect); | 136 GrClip clip(clipRect); |
137 | 137 |
138 // Draw the mask into maskTexture with the path's integerized top-left at | 138 // Draw the mask into maskTexture with the path's integerized top-left at |
139 // the origin using tempPaint. | 139 // the origin using tempPaint. |
140 SkMatrix translate; | 140 SkMatrix translate; |
141 translate.setTranslate(-maskRect->fLeft, -maskRect->fTop); | 141 translate.setTranslate(-maskRect->fLeft, -maskRect->fTop); |
142 drawContext->drawPath(clip, tempPaint, translate, devPath, strokeInfo); | 142 drawContext->drawPath(clip, tempPaint, translate, devPath, GrStrokeInfo(styl
e)); |
143 return drawContext->asTexture();; | 143 return drawContext->asTexture();; |
144 } | 144 } |
145 | 145 |
146 static void draw_path_with_mask_filter(GrContext* context, | 146 static void draw_path_with_mask_filter(GrContext* context, |
147 GrDrawContext* drawContext, | 147 GrDrawContext* drawContext, |
148 const GrClip& clip, | 148 const GrClip& clip, |
149 GrPaint* paint, | 149 GrPaint* paint, |
150 const SkMatrix& viewMatrix, | 150 const SkMatrix& viewMatrix, |
151 const SkMaskFilter* maskFilter, | 151 const SkMaskFilter* maskFilter, |
152 const SkPathEffect* pathEffect, | 152 const SkPathEffect* pathEffect, |
153 const GrStrokeInfo& origStrokeInfo, | 153 const GrStrokeInfo& strokeInfo, |
154 SkPath* pathPtr, | 154 SkPath* pathPtr, |
155 bool pathIsMutable) { | 155 bool pathIsMutable) { |
156 SkASSERT(maskFilter); | 156 SkASSERT(maskFilter); |
157 | 157 |
158 SkIRect clipBounds; | 158 SkIRect clipBounds; |
159 clip.getConservativeBounds(drawContext->width(), drawContext->height(), &cli
pBounds); | 159 clip.getConservativeBounds(drawContext->width(), drawContext->height(), &cli
pBounds); |
160 SkTLazy<SkPath> tmpPath; | 160 SkTLazy<SkPath> tmpPath; |
161 GrStrokeInfo strokeInfo(origStrokeInfo); | |
162 | 161 |
163 static const SkRect* cullRect = nullptr; // TODO: what is our bounds? | 162 static const SkRect* cullRect = nullptr; // TODO: what is our bounds? |
164 | 163 |
165 SkASSERT(strokeInfo.isDashed() || !pathEffect); | 164 SkASSERT(strokeInfo.isDashed() || !pathEffect); |
166 | 165 SkStrokeRec::InitStyle maskStyle; |
167 if (!strokeInfo.isHairlineStyle()) { | 166 if (strokeInfo.isHairlineStyle()) { |
| 167 maskStyle = SkStrokeRec::kHairline_InitStyle; |
| 168 } else { |
168 SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init(); | 169 SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init(); |
| 170 SkStrokeRec rec = strokeInfo; |
169 if (strokeInfo.isDashed()) { | 171 if (strokeInfo.isDashed()) { |
170 if (pathEffect->filterPath(strokedPath, *pathPtr, &strokeInfo, cullR
ect)) { | 172 if (pathEffect->filterPath(strokedPath, *pathPtr, &rec, cullRect)) { |
171 pathPtr = strokedPath; | 173 pathPtr = strokedPath; |
172 pathPtr->setIsVolatile(true); | 174 pathPtr->setIsVolatile(true); |
173 pathIsMutable = true; | 175 pathIsMutable = true; |
174 } | 176 } |
175 strokeInfo.removeDash(); | |
176 } | 177 } |
177 if (strokeInfo.applyToPath(strokedPath, *pathPtr)) { | 178 if (rec.applyToPath(strokedPath, *pathPtr)) { |
178 // Apply the stroke to the path if there is one | 179 // Apply the stroke to the path if there is one |
179 pathPtr = strokedPath; | 180 pathPtr = strokedPath; |
180 pathPtr->setIsVolatile(true); | 181 pathPtr->setIsVolatile(true); |
181 pathIsMutable = true; | 182 pathIsMutable = true; |
182 strokeInfo.setFillStyle(); | |
183 } | 183 } |
| 184 maskStyle = SkStrokeRec::kFill_InitStyle; |
184 } | 185 } |
185 | 186 |
186 // avoid possibly allocating a new path in transform if we can | 187 // avoid possibly allocating a new path in transform if we can |
187 SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init(); | 188 SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init(); |
188 if (!pathIsMutable) { | 189 if (!pathIsMutable) { |
189 devPathPtr->setIsVolatile(true); | 190 devPathPtr->setIsVolatile(true); |
190 } | 191 } |
191 | 192 |
192 // transform the path into device space | 193 // transform the path into device space |
193 pathPtr->transform(viewMatrix, devPathPtr); | 194 pathPtr->transform(viewMatrix, devPathPtr); |
194 | 195 |
195 SkRect maskRect; | 196 SkRect maskRect; |
196 if (maskFilter->canFilterMaskGPU(SkRRect::MakeRect(devPathPtr->getBounds()), | 197 if (maskFilter->canFilterMaskGPU(SkRRect::MakeRect(devPathPtr->getBounds()), |
197 clipBounds, | 198 clipBounds, |
198 viewMatrix, | 199 viewMatrix, |
199 &maskRect)) { | 200 &maskRect)) { |
200 SkIRect finalIRect; | 201 SkIRect finalIRect; |
201 maskRect.roundOut(&finalIRect); | 202 maskRect.roundOut(&finalIRect); |
202 if (clip_bounds_quick_reject(clipBounds, finalIRect)) { | 203 if (clip_bounds_quick_reject(clipBounds, finalIRect)) { |
203 // clipped out | 204 // clipped out |
204 return; | 205 return; |
205 } | 206 } |
206 | 207 |
207 if (maskFilter->directFilterMaskGPU(context->textureProvider(), | 208 if (maskFilter->directFilterMaskGPU(context->textureProvider(), |
208 drawContext, | 209 drawContext, |
209 paint, | 210 paint, |
210 clip, | 211 clip, |
211 viewMatrix, | 212 viewMatrix, |
212 strokeInfo, | 213 SkStrokeRec(maskStyle), |
213 *devPathPtr)) { | 214 *devPathPtr)) { |
214 // the mask filter was able to draw itself directly, so there's noth
ing | 215 // the mask filter was able to draw itself directly, so there's noth
ing |
215 // left to do. | 216 // left to do. |
216 return; | 217 return; |
217 } | 218 } |
218 | 219 |
219 sk_sp<GrTexture> mask(create_mask_GPU(context, | 220 sk_sp<GrTexture> mask(create_mask_GPU(context, |
220 &maskRect, | 221 &maskRect, |
221 *devPathPtr, | 222 *devPathPtr, |
222 strokeInfo, | 223 maskStyle, |
223 paint->isAntiAlias(), | 224 paint->isAntiAlias(), |
224 drawContext->numColorSamples())); | 225 drawContext->numColorSamples())); |
225 if (mask) { | 226 if (mask) { |
226 GrTexture* filtered; | 227 GrTexture* filtered; |
227 | 228 |
228 if (maskFilter->filterMaskGPU(mask.get(), viewMatrix, maskRect, &fil
tered, true)) { | 229 if (maskFilter->filterMaskGPU(mask.get(), viewMatrix, maskRect, &fil
tered, true)) { |
229 // filterMaskGPU gives us ownership of a ref to the result | 230 // filterMaskGPU gives us ownership of a ref to the result |
230 SkAutoTUnref<GrTexture> atu(filtered); | 231 SkAutoTUnref<GrTexture> atu(filtered); |
231 if (draw_mask(drawContext, clip, viewMatrix, maskRect, paint, fi
ltered)) { | 232 if (draw_mask(drawContext, clip, viewMatrix, maskRect, paint, fi
ltered)) { |
232 // This path is completely drawn | 233 // This path is completely drawn |
233 return; | 234 return; |
234 } | 235 } |
235 } | 236 } |
236 } | 237 } |
237 } | 238 } |
238 | 239 |
239 // draw the mask on the CPU - this is a fallthrough path in case the | |
240 // GPU path fails | |
241 SkPaint::Style style = strokeInfo.isHairlineStyle() ? SkPaint::kStroke_Style
: | |
242 SkPaint::kFill_Style; | |
243 sw_draw_with_mask_filter(drawContext, context->textureProvider(), | 240 sw_draw_with_mask_filter(drawContext, context->textureProvider(), |
244 clip, viewMatrix, *devPathPtr, | 241 clip, viewMatrix, *devPathPtr, |
245 maskFilter, clipBounds, paint, style); | 242 maskFilter, clipBounds, paint, maskStyle); |
246 } | 243 } |
247 | 244 |
248 void GrBlurUtils::drawPathWithMaskFilter(GrContext* context, | 245 void GrBlurUtils::drawPathWithMaskFilter(GrContext* context, |
249 GrDrawContext* drawContext, | 246 GrDrawContext* drawContext, |
250 const GrClip& clip, | 247 const GrClip& clip, |
251 const SkPath& origPath, | 248 const SkPath& origPath, |
252 GrPaint* paint, | 249 GrPaint* paint, |
253 const SkMatrix& viewMatrix, | 250 const SkMatrix& viewMatrix, |
254 const SkMaskFilter* mf, | 251 const SkMaskFilter* mf, |
255 const SkPathEffect* pathEffect, | 252 const SkPathEffect* pathEffect, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 } | 335 } |
339 | 336 |
340 if (paint.getMaskFilter()) { | 337 if (paint.getMaskFilter()) { |
341 draw_path_with_mask_filter(context, drawContext, clip, &grPaint, viewMat
rix, | 338 draw_path_with_mask_filter(context, drawContext, clip, &grPaint, viewMat
rix, |
342 paint.getMaskFilter(), pathEffect, strokeInfo
, | 339 paint.getMaskFilter(), pathEffect, strokeInfo
, |
343 pathPtr, pathIsMutable); | 340 pathPtr, pathIsMutable); |
344 } else { | 341 } else { |
345 drawContext->drawPath(clip, grPaint, viewMatrix, *pathPtr, strokeInfo); | 342 drawContext->drawPath(clip, grPaint, viewMatrix, *pathPtr, strokeInfo); |
346 } | 343 } |
347 } | 344 } |
OLD | NEW |