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

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

Issue 2335343008: Add optional sw generated path coverage mask caching (Closed)
Patch Set: Add .fs to literals in new gm 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
« no previous file with comments | « 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 39 static bool get_shape_and_clip_bounds(int width, int height,
28 // path bounds would be empty. 40 const GrClip& clip,
29 bool get_shape_and_clip_bounds(int width, int height, 41 const GrShape& shape,
30 const GrClip& clip, 42 const SkMatrix& matrix,
31 const GrShape& shape, 43 SkIRect* unclippedDevShapeBounds,
32 const SkMatrix& matrix, 44 SkIRect* clippedDevShapeBounds,
33 SkIRect* devShapeBounds, 45 SkIRect* devClipBounds) {
34 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 }
64
65 void GrSoftwarePathRenderer::DrawNonAARect(GrDrawContext* drawContext, 63 void GrSoftwarePathRenderer::DrawNonAARect(GrDrawContext* drawContext,
66 const GrPaint& paint, 64 const GrPaint& paint,
67 const GrUserStencilSettings& userSten cilSettings, 65 const GrUserStencilSettings& userSten cilSettings,
68 const GrClip& clip, 66 const GrClip& clip,
69 const SkMatrix& viewMatrix, 67 const SkMatrix& viewMatrix,
70 const SkRect& rect, 68 const SkRect& rect,
71 const SkMatrix& localMatrix) { 69 const SkMatrix& localMatrix) {
72 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(paint.ge tColor(), 70 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(paint.ge tColor(),
73 viewMatr ix, rect, 71 viewMatr ix, rect,
74 nullptr, &localMatrix)); 72 nullptr, &localMatrix));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 if (!fTexProvider) { 124 if (!fTexProvider) {
127 return false; 125 return false;
128 } 126 }
129 127
130 // We really need to know if the shape will be inverse filled or not 128 // We really need to know if the shape will be inverse filled or not
131 bool inverseFilled = false; 129 bool inverseFilled = false;
132 SkTLazy<GrShape> tmpShape; 130 SkTLazy<GrShape> tmpShape;
133 SkASSERT(!args.fShape->style().applies()); 131 SkASSERT(!args.fShape->style().applies());
134 inverseFilled = args.fShape->inverseFilled(); 132 inverseFilled = args.fShape->inverseFilled();
135 133
136 SkIRect devShapeBounds, devClipBounds; 134 SkIRect unclippedDevShapeBounds, clippedDevShapeBounds, devClipBounds;
135 // To prevent overloading the cache with entries during animations we limit the cache of masks
136 // to cases where the matrix preserves axis alignment.
137 bool useCache = fAllowCaching && !inverseFilled && args.fViewMatrix->preserv esAxisAlignment() &&
138 args.fShape->hasUnstyledKey() && args.fAntiAlias;
139
137 if (!get_shape_and_clip_bounds(args.fDrawContext->width(), args.fDrawContext ->height(), 140 if (!get_shape_and_clip_bounds(args.fDrawContext->width(), args.fDrawContext ->height(),
138 *args.fClip, *args.fShape, 141 *args.fClip, *args.fShape,
139 *args.fViewMatrix, &devShapeBounds, &devClipB ounds)) { 142 *args.fViewMatrix, &unclippedDevShapeBounds,
143 &clippedDevShapeBounds,
144 &devClipBounds)) {
140 if (inverseFilled) { 145 if (inverseFilled) {
141 DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStenci lSettings, 146 DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStenci lSettings,
142 *args.fClip, 147 *args.fClip,
143 *args.fViewMatrix, devClipBounds, devShapeBounds); 148 *args.fViewMatrix, devClipBounds, unclippedDevShap eBounds);
144 149
145 } 150 }
146 return true; 151 return true;
147 } 152 }
148 153
149 SkAutoTUnref<GrTexture> texture( 154 const SkIRect* boundsForMask = &clippedDevShapeBounds;
150 GrSWMaskHelper::DrawShapeMaskToTexture(fTexProvider, *args.fShape, d evShapeBounds, 155 if (useCache) {
151 args.fAntiAlias, args.fViewMa trix)); 156 // Use the cache only if >50% of the path is visible.
152 if (!texture) { 157 int unclippedWidth = unclippedDevShapeBounds.width();
153 return false; 158 int unclippedHeight = unclippedDevShapeBounds.height();
159 int unclippedArea = unclippedWidth * unclippedHeight;
160 int clippedArea = clippedDevShapeBounds.width() * clippedDevShapeBounds. height();
161 int maxTextureSize = args.fDrawContext->caps()->maxTextureSize();
162 if (unclippedArea > 2 * clippedArea || unclippedWidth > maxTextureSize | |
163 unclippedHeight > maxTextureSize) {
164 useCache = false;
165 } else {
166 boundsForMask = &unclippedDevShapeBounds;
167 }
154 } 168 }
155 169
156 GrSWMaskHelper::DrawToTargetWithShapeMask(texture, args.fDrawContext, *args. fPaint, 170 GrUniqueKey maskKey;
171 struct KeyData {
172 SkScalar fFractionalTranslateX;
173 SkScalar fFractionalTranslateY;
174 };
175
176 if (useCache) {
177 // We require the upper left 2x2 of the matrix to match exactly for a ca che hit.
178 SkScalar sx = args.fViewMatrix->get(SkMatrix::kMScaleX);
179 SkScalar sy = args.fViewMatrix->get(SkMatrix::kMScaleY);
180 SkScalar kx = args.fViewMatrix->get(SkMatrix::kMSkewX);
181 SkScalar ky = args.fViewMatrix->get(SkMatrix::kMSkewY);
182 SkScalar tx = args.fViewMatrix->get(SkMatrix::kMTransX);
183 SkScalar ty = args.fViewMatrix->get(SkMatrix::kMTransY);
184 // Allow 8 bits each in x and y of subpixel positioning.
185 SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
186 SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
187 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ;
188 GrUniqueKey::Builder builder(&maskKey, kDomain, 5 + args.fShape->unstyle dKeySize());
189 builder[0] = SkFloat2Bits(sx);
190 builder[1] = SkFloat2Bits(sy);
191 builder[2] = SkFloat2Bits(kx);
192 builder[3] = SkFloat2Bits(ky);
193 builder[4] = fracX | (fracY >> 8);
194 args.fShape->writeUnstyledKey(&builder[5]);
195 }
196
197 sk_sp<GrTexture> texture;
198 if (useCache) {
199 texture.reset(args.fResourceProvider->findAndRefTextureByUniqueKey(maskK ey));
200 }
201 if (!texture) {
202 GrSWMaskHelper::TextureType type = useCache ? GrSWMaskHelper::TextureTy pe::kExactFit
203 : GrSWMaskHelper::TextureTy pe::kApproximateFit;
204 texture.reset(GrSWMaskHelper::DrawShapeMaskToTexture(fTexProvider, *arg s.fShape,
205 *boundsForMask, ar gs.fAntiAlias,
206 type, args.fViewMa trix));
207 if (!texture) {
208 return false;
209 }
210 if (useCache) {
211 texture->resourcePriv().setUniqueKey(maskKey);
212 }
213 }
214
215 GrSWMaskHelper::DrawToTargetWithShapeMask(texture.get(), args.fDrawContext, *args.fPaint,
157 *args.fUserStencilSettings, 216 *args.fUserStencilSettings,
158 *args.fClip, *args.fViewMatrix, 217 *args.fClip, *args.fViewMatrix,
159 devShapeBounds); 218 SkIPoint {boundsForMask->fLeft, bo undsForMask->fTop},
219 *boundsForMask);
160 220
161 if (inverseFilled) { 221 if (inverseFilled) {
162 DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStencilSet tings, 222 DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStencilSet tings,
163 *args.fClip, 223 *args.fClip,
164 *args.fViewMatrix, devClipBounds, devShapeBounds); 224 *args.fViewMatrix, devClipBounds, unclippedDevShapeBou nds);
165 } 225 }
166 226
167 return true; 227 return true;
168 } 228 }
OLDNEW
« no previous file with comments | « src/gpu/GrSoftwarePathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698