Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/gpu/GrBlurUtils.cpp

Issue 1157773003: Move SkGpuDevice::internalDrawPath to GrBlurUtils::drawPathWithMaskFilter (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: more cleanup Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrBlurUtils.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrBlurUtils.h"
9 #include "GrDrawContext.h"
10 #include "GrContext.h"
11 #include "effects/GrSimpleTextureEffect.h"
12 #include "GrStrokeInfo.h"
13 #include "GrTexture.h"
14 #include "GrTextureProvider.h"
15 #include "SkDraw.h"
16 #include "SkGr.h"
17 #include "SkMaskFilter.h"
18 #include "SkPaint.h"
19
20 static bool clip_bounds_quick_reject(const SkIRect& clipBounds, const SkIRect& r ect) {
21 return clipBounds.isEmpty() || rect.isEmpty() || !SkIRect::Intersects(clipBo unds, rect);
22 }
23
24 // Draw a mask using the supplied paint. Since the coverage/geometry
25 // is already burnt into the mask this boils down to a rect draw.
26 // Return true if the mask was successfully drawn.
27 static bool draw_mask(GrDrawContext* drawContext,
28 GrRenderTarget* rt,
29 const GrClip& clip,
30 const SkMatrix& viewMatrix,
31 const SkRect& maskRect,
32 GrPaint* grp,
33 GrTexture* mask) {
34 SkMatrix matrix;
35 matrix.setTranslate(-maskRect.fLeft, -maskRect.fTop);
36 matrix.postIDiv(mask->width(), mask->height());
37
38 grp->addCoverageProcessor(GrSimpleTextureEffect::Create(mask, matrix,
39 kDevice_GrCoordSet)) ->unref();
40
41 SkMatrix inverse;
42 if (!viewMatrix.invert(&inverse)) {
43 return false;
44 }
45 drawContext->drawNonAARectWithLocalMatrix(rt, clip, *grp, SkMatrix::I(), mas kRect, inverse);
46 return true;
47 }
48
49 static bool draw_with_mask_filter(GrDrawContext* drawContext,
50 GrTextureProvider* textureProvider,
51 GrRenderTarget* rt,
52 const GrClip& clipData,
53 const SkMatrix& viewMatrix,
54 const SkPath& devPath,
55 SkMaskFilter* filter,
56 const SkIRect& clipBounds,
57 GrPaint* grp,
58 SkPaint::Style style) {
59 SkMask srcM, dstM;
60
61 if (!SkDraw::DrawToMask(devPath, &clipBounds, filter, &viewMatrix, &srcM,
62 SkMask::kComputeBoundsAndRenderImage_CreateMode, sty le)) {
63 return false;
64 }
65 SkAutoMaskFreeImage autoSrc(srcM.fImage);
66
67 if (!filter->filterMask(&dstM, srcM, viewMatrix, NULL)) {
68 return false;
69 }
70 // this will free-up dstM when we're done (allocated in filterMask())
71 SkAutoMaskFreeImage autoDst(dstM.fImage);
72
73 if (clip_bounds_quick_reject(clipBounds, dstM.fBounds)) {
74 return false;
75 }
76
77 // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
78 // the current clip (and identity matrix) and GrPaint settings
79 GrSurfaceDesc desc;
80 desc.fWidth = dstM.fBounds.width();
81 desc.fHeight = dstM.fBounds.height();
82 desc.fConfig = kAlpha_8_GrPixelConfig;
83
84 SkAutoTUnref<GrTexture> texture(textureProvider->refScratchTexture(
85 desc, GrTextureProvider::kApprox_ScratchTexMatch));
86 if (!texture) {
87 return false;
88 }
89 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
90 dstM.fImage, dstM.fRowBytes);
91
92 SkRect maskRect = SkRect::Make(dstM.fBounds);
93
94 return draw_mask(drawContext, rt, clipData, viewMatrix, maskRect, grp, textu re);
95 }
96
97 // Create a mask of 'devPath' and place the result in 'mask'.
98 static GrTexture* create_mask_GPU(GrContext* context,
99 const SkRect& maskRect,
100 const SkPath& devPath,
101 const GrStrokeInfo& strokeInfo,
102 bool doAA,
103 int sampleCnt) {
104 GrSurfaceDesc desc;
105 desc.fFlags = kRenderTarget_GrSurfaceFlag;
106 desc.fWidth = SkScalarCeilToInt(maskRect.width());
107 desc.fHeight = SkScalarCeilToInt(maskRect.height());
108 desc.fSampleCnt = doAA ? sampleCnt : 0;
109 // We actually only need A8, but it often isn't supported as a
110 // render target so default to RGBA_8888
111 desc.fConfig = kRGBA_8888_GrPixelConfig;
112
113 if (context->isConfigRenderable(kAlpha_8_GrPixelConfig, desc.fSampleCnt > 0) ) {
114 desc.fConfig = kAlpha_8_GrPixelConfig;
115 }
116
117 GrTexture* mask = context->textureProvider()->refScratchTexture(
118 desc, GrTextureProvider::kApprox_ScratchTexMatch);
119 if (NULL == mask) {
120 return NULL;
121 }
122
123 SkRect clipRect = SkRect::MakeWH(maskRect.width(), maskRect.height());
124
125 GrDrawContext* drawContext = context->drawContext();
126 if (!drawContext) {
127 return NULL;
128 }
129
130 drawContext->clear(mask->asRenderTarget(), NULL, 0x0, true);
131
132 GrPaint tempPaint;
133 tempPaint.setAntiAlias(doAA);
134 tempPaint.setCoverageSetOpXPFactory(SkRegion::kReplace_Op);
135
136 // setup new clip
137 GrClip clip(clipRect);
138
139 // Draw the mask into maskTexture with the path's top-left at the origin usi ng tempPaint.
140 SkMatrix translate;
141 translate.setTranslate(-maskRect.fLeft, -maskRect.fTop);
142 drawContext->drawPath(mask->asRenderTarget(), clip, tempPaint, translate, de vPath, strokeInfo);
143 return mask;
144 }
145
146 void GrBlurUtils::drawPathWithMaskFilter(GrContext* context,
147 GrDrawContext* drawContext,
148 GrRenderTarget* renderTarget,
149 const GrClip& clip,
150 const SkPath& origSrcPath,
151 const SkPaint& paint,
152 const SkMatrix& origViewMatrix,
153 const SkMatrix* prePathMatrix,
154 const SkIRect& clipBounds,
155 bool pathIsMutable) {
156 SkASSERT(!pathIsMutable || origSrcPath.isVolatile());
157
158 GrStrokeInfo strokeInfo(paint);
159
160 // If we have a prematrix, apply it to the path, optimizing for the case
161 // where the original path can in fact be modified in place (even though
162 // its parameter type is const).
163 SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
164 SkTLazy<SkPath> tmpPath;
165 SkTLazy<SkPath> effectPath;
166 SkPathEffect* pathEffect = paint.getPathEffect();
167
168 SkMatrix viewMatrix = origViewMatrix;
169
170 if (prePathMatrix) {
171 // stroking, path effects, and blurs are supposed to be applied *after* the prePathMatrix.
172 // The pre-path-matrix also should not affect shading.
173 if (NULL == paint.getMaskFilter() && NULL == pathEffect && NULL == paint .getShader() &&
174 (strokeInfo.isFillStyle() || strokeInfo.isHairlineStyle())) {
175 viewMatrix.preConcat(*prePathMatrix);
176 } else {
177 SkPath* result = pathPtr;
178
179 if (!pathIsMutable) {
180 result = tmpPath.init();
181 result->setIsVolatile(true);
182 pathIsMutable = true;
183 }
184 // should I push prePathMatrix on our MV stack temporarily, instead
185 // of applying it here? See SkDraw.cpp
186 pathPtr->transform(*prePathMatrix, result);
187 pathPtr = result;
188 }
189 }
190 // at this point we're done with prePathMatrix
191 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
192
193 GrPaint grPaint;
194 if (!SkPaint2GrPaint(context, renderTarget, paint, viewMatrix, true, &grPain t)) {
195 return;
196 }
197
198 const SkRect* cullRect = NULL; // TODO: what is our bounds?
199 if (!strokeInfo.isDashed() && pathEffect && pathEffect->filterPath(effectPat h.init(), *pathPtr,
200 &strokeIn fo, cullRect)) {
201 pathPtr = effectPath.get();
202 pathIsMutable = true;
203 }
204
205 if (paint.getMaskFilter()) {
206 if (!strokeInfo.isHairlineStyle()) {
207 SkPath* strokedPath = pathIsMutable ? pathPtr : tmpPath.init();
208 if (strokeInfo.isDashed()) {
209 if (pathEffect->filterPath(strokedPath, *pathPtr, &strokeInfo, c ullRect)) {
210 pathPtr = strokedPath;
211 pathIsMutable = true;
212 }
213 strokeInfo.removeDash();
214 }
215 if (strokeInfo.applyToPath(strokedPath, *pathPtr)) {
216 pathPtr = strokedPath;
217 pathIsMutable = true;
218 strokeInfo.setFillStyle();
219 }
220 }
221
222 // avoid possibly allocating a new path in transform if we can
223 SkPath* devPathPtr = pathIsMutable ? pathPtr : tmpPath.init();
224 if (!pathIsMutable) {
225 devPathPtr->setIsVolatile(true);
226 }
227
228 // transform the path into device space
229 pathPtr->transform(viewMatrix, devPathPtr);
230
231 SkRect maskRect;
232 if (paint.getMaskFilter()->canFilterMaskGPU(devPathPtr->getBounds(),
233 clipBounds,
234 viewMatrix,
235 &maskRect)) {
236 SkIRect finalIRect;
237 maskRect.roundOut(&finalIRect);
238 if (clip_bounds_quick_reject(clipBounds, finalIRect)) {
239 // clipped out
240 return;
241 }
242
243 if (paint.getMaskFilter()->directFilterMaskGPU(context,
244 renderTarget,
245 &grPaint,
246 clip,
247 viewMatrix,
248 strokeInfo,
249 *devPathPtr)) {
250 // the mask filter was able to draw itself directly, so there's nothing
251 // left to do.
252 return;
253 }
254
255
256 SkAutoTUnref<GrTexture> mask(create_mask_GPU(context,
257 maskRect,
258 *devPathPtr,
259 strokeInfo,
260 grPaint.isAntiAlias(),
261 renderTarget->numSample s()));
262 if (mask) {
263 GrTexture* filtered;
264
265 if (paint.getMaskFilter()->filterMaskGPU(mask, viewMatrix, maskR ect,
266 &filtered, true)) {
267 // filterMaskGPU gives us ownership of a ref to the result
268 SkAutoTUnref<GrTexture> atu(filtered);
269 if (draw_mask(drawContext,
270 renderTarget,
271 clip,
272 viewMatrix,
273 maskRect,
274 &grPaint,
275 filtered)) {
276 // This path is completely drawn
277 return;
278 }
279 }
280 }
281 }
282
283 // draw the mask on the CPU - this is a fallthrough path in case the
284 // GPU path fails
285 SkPaint::Style style = strokeInfo.isHairlineStyle() ? SkPaint::kStroke_S tyle :
286 SkPaint::kFill_Sty le;
287 draw_with_mask_filter(drawContext, context->textureProvider(), renderTar get,
288 clip, viewMatrix, *devPathPtr,
289 paint.getMaskFilter(), clipBounds, &grPaint, style );
290 return;
291 }
292
293 drawContext->drawPath(renderTarget, clip, grPaint, viewMatrix, *pathPtr, str okeInfo);
294 }
295
OLDNEW
« no previous file with comments | « src/gpu/GrBlurUtils.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698