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

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

Issue 2335343008: Add optional sw generated path coverage mask caching (Closed)
Patch Set: comments Created 4 years, 3 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
« src/gpu/GrSWMaskHelper.h ('K') | « src/gpu/GrSoftwarePathRenderer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 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 "GrSoftwarePathRenderer.h" 8 #include "GrSoftwarePathRenderer.h"
9 #include "GrAuditTrail.h" 9 #include "GrAuditTrail.h"
10 #include "GrClip.h" 10 #include "GrClip.h"
11 #include "GrPipelineBuilder.h" 11 #include "GrPipelineBuilder.h"
12 #include "GrGpuResourcePriv.h"
12 #include "GrSWMaskHelper.h" 13 #include "GrSWMaskHelper.h"
13 #include "GrTextureProvider.h" 14 #include "GrTextureProvider.h"
14 #include "batches/GrRectBatchFactory.h" 15 #include "batches/GrRectBatchFactory.h"
15 16
16 //////////////////////////////////////////////////////////////////////////////// 17 ////////////////////////////////////////////////////////////////////////////////
17 bool GrSoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { 18 bool GrSoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
18 // Pass on any style that applies. The caller will apply the style if a suit able renderer is 19 // Pass on any style that applies. The caller will apply the style if a suit able renderer is
19 // not found and try again with the new GrShape. 20 // not found and try again with the new GrShape.
20 return !args.fShape->style().applies() && SkToBool(fTexProvider); 21 return !args.fShape->style().applies() && SkToBool(fTexProvider);
21 } 22 }
22 23
23 namespace { 24 ////////////////////////////////////////////////////////////////////////////////
25 static bool get_unclipped_shape_dev_bounds(const GrShape& shape, const SkMatrix& matrix,
26 SkIRect* devBounds) {
27 SkRect shapeBounds = shape.styledBounds();
28 if (shapeBounds.isEmpty()) {
29 return false;
30 }
31 SkRect shapeDevBounds;
32 matrix.mapRect(&shapeDevBounds, shapeBounds);
33 shapeDevBounds.roundOut(devBounds);
34 return true;
35 }
24 36
25 //////////////////////////////////////////////////////////////////////////////// 37 // Gets the shape bounds, the clip bounds, and the intersection (if any). Return s false if there
26 // gets device coord bounds of path (not considering the fill) and clip. The 38 // is no intersection.
27 // path bounds will be a subset of the clip bounds. returns false if
28 // path bounds would be empty.
29 bool get_shape_and_clip_bounds(int width, int height, 39 bool get_shape_and_clip_bounds(int width, int height,
robertphillips 2016/09/21 15:42:39 static here too ?
bsalomon 2016/09/21 16:01:09 Done.
30 const GrClip& clip, 40 const GrClip& clip,
31 const GrShape& shape, 41 const GrShape& shape,
32 const SkMatrix& matrix, 42 const SkMatrix& matrix,
33 SkIRect* devShapeBounds, 43 SkIRect* unclippedDevShapeBounds,
44 SkIRect* clippedDevShapeBounds,
34 SkIRect* devClipBounds) { 45 SkIRect* devClipBounds) {
35 // compute bounds as intersection of rt size, clip, and path 46 // compute bounds as intersection of rt size, clip, and path
36 clip.getConservativeBounds(width, height, devClipBounds); 47 clip.getConservativeBounds(width, height, devClipBounds);
37 48
38 if (devClipBounds->isEmpty()) { 49 if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) {
39 *devShapeBounds = SkIRect::MakeWH(width, height); 50 *unclippedDevShapeBounds = SkIRect::EmptyIRect();
51 *clippedDevShapeBounds = SkIRect::EmptyIRect();
40 return false; 52 return false;
41 } 53 }
42 SkRect shapeBounds = shape.styledBounds(); 54 if (!clippedDevShapeBounds->intersect(*devClipBounds, *unclippedDevShapeBoun ds)) {
43 if (!shapeBounds.isEmpty()) { 55 *clippedDevShapeBounds = SkIRect::EmptyIRect();
44 SkRect shapeSBounds;
45 matrix.mapRect(&shapeSBounds, shapeBounds);
46 SkIRect shapeIBounds;
47 shapeSBounds.roundOut(&shapeIBounds);
48 *devShapeBounds = *devClipBounds;
49 if (!devShapeBounds->intersect(shapeIBounds)) {
50 // set the correct path bounds, as this would be used later.
51 *devShapeBounds = shapeIBounds;
52 return false;
53 }
54 } else {
55 *devShapeBounds = SkIRect::EmptyIRect();
56 return false; 56 return false;
57 } 57 }
58 return true; 58 return true;
59 } 59 }
60 60
61
61 //////////////////////////////////////////////////////////////////////////////// 62 ////////////////////////////////////////////////////////////////////////////////
62 63
63 }
64
65 void GrSoftwarePathRenderer::DrawNonAARect(GrDrawContext* drawContext, 64 void GrSoftwarePathRenderer::DrawNonAARect(GrDrawContext* drawContext,
66 const GrPaint& paint, 65 const GrPaint& paint,
67 const GrUserStencilSettings& userSten cilSettings, 66 const GrUserStencilSettings& userSten cilSettings,
68 const GrClip& clip, 67 const GrClip& clip,
69 const SkMatrix& viewMatrix, 68 const SkMatrix& viewMatrix,
70 const SkRect& rect, 69 const SkRect& rect,
71 const SkMatrix& localMatrix) { 70 const SkMatrix& localMatrix) {
72 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(paint.ge tColor(), 71 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(paint.ge tColor(),
73 viewMatr ix, rect, 72 viewMatr ix, rect,
74 nullptr, &localMatrix)); 73 nullptr, &localMatrix));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 if (!fTexProvider) { 125 if (!fTexProvider) {
127 return false; 126 return false;
128 } 127 }
129 128
130 // We really need to know if the shape will be inverse filled or not 129 // We really need to know if the shape will be inverse filled or not
131 bool inverseFilled = false; 130 bool inverseFilled = false;
132 SkTLazy<GrShape> tmpShape; 131 SkTLazy<GrShape> tmpShape;
133 SkASSERT(!args.fShape->style().applies()); 132 SkASSERT(!args.fShape->style().applies());
134 inverseFilled = args.fShape->inverseFilled(); 133 inverseFilled = args.fShape->inverseFilled();
135 134
136 SkIRect devShapeBounds, devClipBounds; 135 SkIRect unclippedDevShapeBounds, clippedDevShapeBounds, devClipBounds;
136 // To prevent overloading the cache with entries during animations we limit the cache of masks
137 // to cases where the matrix preserves axis alignment.
138 bool useCache = fAllowCaching && !inverseFilled && args.fViewMatrix->preserv esAxisAlignment() &&
139 args.fShape->hasUnstyledKey() && args.fAntiAlias;
140
137 if (!get_shape_and_clip_bounds(args.fDrawContext->width(), args.fDrawContext ->height(), 141 if (!get_shape_and_clip_bounds(args.fDrawContext->width(), args.fDrawContext ->height(),
138 *args.fClip, *args.fShape, 142 *args.fClip, *args.fShape,
139 *args.fViewMatrix, &devShapeBounds, &devClipB ounds)) { 143 *args.fViewMatrix, &unclippedDevShapeBounds,
144 &clippedDevShapeBounds,
145 &devClipBounds)) {
140 if (inverseFilled) { 146 if (inverseFilled) {
141 DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStenci lSettings, 147 DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStenci lSettings,
142 *args.fClip, 148 *args.fClip,
143 *args.fViewMatrix, devClipBounds, devShapeBounds); 149 *args.fViewMatrix, devClipBounds, unclippedDevShap eBounds);
144 150
145 } 151 }
146 return true; 152 return true;
147 } 153 }
148 154
149 SkAutoTUnref<GrTexture> texture( 155 const SkIRect* boundsForMask = &clippedDevShapeBounds;
150 GrSWMaskHelper::DrawShapeMaskToTexture(fTexProvider, *args.fShape, d evShapeBounds, 156 if (useCache) {
151 args.fAntiAlias, args.fViewMa trix)); 157 // Use the cache only if >50% of the path is visible.
152 if (!texture) { 158 int unclippedWidth = unclippedDevShapeBounds.width();
153 return false; 159 int unclippedHeight = unclippedDevShapeBounds.height();
160 int unclippedArea = unclippedWidth * unclippedHeight;
161 int clippedArea = clippedDevShapeBounds.width() * clippedDevShapeBounds. height();
162 int maxTextureSize = args.fDrawContext->caps()->maxTextureSize();
163 if (unclippedArea > 2 * clippedArea || unclippedWidth > maxTextureSize | |
164 unclippedHeight > maxTextureSize) {
165 useCache = false;
166 } else {
167 boundsForMask = &unclippedDevShapeBounds;
168 }
154 } 169 }
155 170
156 GrSWMaskHelper::DrawToTargetWithShapeMask(texture, args.fDrawContext, *args. fPaint, 171 GrUniqueKey maskKey;
172 struct KeyData {
173 SkScalar fFractionalTranslateX;
174 SkScalar fFractionalTranslateY;
175 };
176
177 if (useCache) {
178 // We require the upper left 2x2 of the matrix to match exactly for a ca che hit.
179 SkScalar sx = args.fViewMatrix->get(SkMatrix::kMScaleX);
180 SkScalar sy = args.fViewMatrix->get(SkMatrix::kMScaleY);
181 SkScalar kx = args.fViewMatrix->get(SkMatrix::kMSkewX);
182 SkScalar ky = args.fViewMatrix->get(SkMatrix::kMSkewY);
183 SkScalar tx = args.fViewMatrix->get(SkMatrix::kMTransX);
184 SkScalar ty = args.fViewMatrix->get(SkMatrix::kMTransY);
185 // Allow 8 bits each in x and y of subpixel positioning.
186 SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
187 SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
188 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ;
189 GrUniqueKey::Builder builder(&maskKey, kDomain, 5 + args.fShape->unstyle dKeySize());
190 builder[0] = SkFloat2Bits(sx);
191 builder[1] = SkFloat2Bits(sy);
192 builder[2] = SkFloat2Bits(kx);
193 builder[3] = SkFloat2Bits(ky);
194 builder[4] = fracX | (fracY >> 8);
195 args.fShape->writeUnstyledKey(&builder[5]);
196 }
197
198 sk_sp<GrTexture> texture;
199 if (useCache) {
200 texture.reset(args.fResourceProvider->findAndRefTextureByUniqueKey(maskK ey));
201 }
202 if (!texture) {
203 GrSWMaskHelper::TextureType type = useCache ? GrSWMaskHelper::TextureTy pe::kExactFit
204 : GrSWMaskHelper::TextureTy pe::kApproximateFit;
205 texture.reset(GrSWMaskHelper::DrawShapeMaskToTexture(fTexProvider, *arg s.fShape,
206 *boundsForMask, ar gs.fAntiAlias,
207 type, args.fViewMa trix));
208 if (!texture) {
209 return false;
210 }
211 if (useCache) {
212 texture->resourcePriv().setUniqueKey(maskKey);
213 }
214 }
215
216 GrSWMaskHelper::DrawToTargetWithShapeMask(texture.get(), args.fDrawContext, *args.fPaint,
157 *args.fUserStencilSettings, 217 *args.fUserStencilSettings,
158 *args.fClip, *args.fViewMatrix, 218 *args.fClip, *args.fViewMatrix,
159 devShapeBounds); 219 SkIPoint {boundsForMask->fLeft, bo undsForMask->fTop},
220 *boundsForMask);
160 221
161 if (inverseFilled) { 222 if (inverseFilled) {
162 DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStencilSet tings, 223 DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStencilSet tings,
163 *args.fClip, 224 *args.fClip,
164 *args.fViewMatrix, devClipBounds, devShapeBounds); 225 *args.fViewMatrix, devClipBounds, unclippedDevShapeBou nds);
165 } 226 }
166 227
167 return true; 228 return true;
168 } 229 }
OLDNEW
« src/gpu/GrSWMaskHelper.h ('K') | « src/gpu/GrSoftwarePathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698