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

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

Issue 687283002: Support multiple scales for dfpaths. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Update based on comments Created 6 years, 1 month 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/GrAADistanceFieldPathRenderer.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 /* 2 /*
3 * Copyright 2014 Google Inc. 3 * Copyright 2014 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 #include "GrAADistanceFieldPathRenderer.h" 9 #include "GrAADistanceFieldPathRenderer.h"
10 10
11 #include "GrAtlas.h" 11 #include "GrAtlas.h"
12 #include "GrContext.h" 12 #include "GrContext.h"
13 #include "GrDrawState.h" 13 #include "GrDrawState.h"
14 #include "GrSurfacePriv.h" 14 #include "GrSurfacePriv.h"
15 #include "GrSWMaskHelper.h" 15 #include "GrSWMaskHelper.h"
16 #include "GrTexturePriv.h" 16 #include "GrTexturePriv.h"
17 #include "effects/GrDistanceFieldTextureEffect.h" 17 #include "effects/GrDistanceFieldTextureEffect.h"
18 18
19 #include "SkDistanceFieldGen.h" 19 #include "SkDistanceFieldGen.h"
20 #include "SkRTConf.h" 20 #include "SkRTConf.h"
21 21
22 #define ATLAS_TEXTURE_WIDTH 1024 22 #define ATLAS_TEXTURE_WIDTH 1024
23 #define ATLAS_TEXTURE_HEIGHT 1024 23 #define ATLAS_TEXTURE_HEIGHT 2048
24 #define PLOT_WIDTH 256 24 #define PLOT_WIDTH 256
25 #define PLOT_HEIGHT 256 25 #define PLOT_HEIGHT 256
26 26
27 #define NUM_PLOTS_X (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH) 27 #define NUM_PLOTS_X (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH)
28 #define NUM_PLOTS_Y (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT) 28 #define NUM_PLOTS_Y (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT)
29 29
30 SK_CONF_DECLARE(bool, c_DumpPathCache, "gpu.dumpPathCache", false, 30 SK_CONF_DECLARE(bool, c_DumpPathCache, "gpu.dumpPathCache", false,
31 "Dump the contents of the path cache before every purge."); 31 "Dump the contents of the path cache before every purge.");
32 32
33 #ifdef DF_PATH_TRACKING 33 #ifdef DF_PATH_TRACKING
34 static int g_NumCachedPaths = 0; 34 static int g_NumCachedPaths = 0;
35 static int g_NumFreedPaths = 0; 35 static int g_NumFreedPaths = 0;
36 #endif 36 #endif
37 37
38 // mip levels
39 static const int kSmallMIP = 32;
40 static const int kMediumMIP = 64;
41 static const int kLargeMIP = 128;
42
38 //////////////////////////////////////////////////////////////////////////////// 43 ////////////////////////////////////////////////////////////////////////////////
39 GrAADistanceFieldPathRenderer::GrAADistanceFieldPathRenderer(GrContext* context) 44 GrAADistanceFieldPathRenderer::GrAADistanceFieldPathRenderer(GrContext* context)
40 : fContext(context) 45 : fContext(context)
41 , fAtlas(NULL) 46 , fAtlas(NULL)
42 , fEffectFlags(kInvalid_DistanceFieldEffectFlag) { 47 , fEffectFlags(kInvalid_DistanceFieldEffectFlag) {
43 } 48 }
44 49
45 GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() { 50 GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() {
46 PathDataList::Iter iter; 51 PathDataList::Iter iter;
47 iter.init(fPathList, PathDataList::Iter::kHead_IterStart); 52 iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
(...skipping 17 matching lines...) Expand all
65 const GrDrawTarget* target, 70 const GrDrawTarget* target,
66 bool antiAlias) const { 71 bool antiAlias) const {
67 72
68 // TODO: Support inverse fill 73 // TODO: Support inverse fill
69 // TODO: Support strokes 74 // TODO: Support strokes
70 if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInver seFillType() 75 if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInver seFillType()
71 || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) { 76 || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) {
72 return false; 77 return false;
73 } 78 }
74 79
75 // currently don't support perspective or scaling more than 3x 80 // currently don't support perspective
76 const GrDrawState& drawState = target->getDrawState(); 81 const GrDrawState& drawState = target->getDrawState();
77 const SkMatrix& vm = drawState.getViewMatrix(); 82 const SkMatrix& vm = drawState.getViewMatrix();
78 if (vm.hasPerspective() || vm.getMaxScale() > 3.0f) { 83 if (vm.hasPerspective()) {
79 return false; 84 return false;
80 } 85 }
81 86
82 // only support paths smaller than 64 x 64 87 // only support paths smaller than 64x64, scaled to less than 256x256
88 // the goal is to accelerate rendering of lots of small paths that may be sc aling
89 SkScalar maxScale = vm.getMaxScale();
83 const SkRect& bounds = path.getBounds(); 90 const SkRect& bounds = path.getBounds();
84 return bounds.width() < 64.f && bounds.height() < 64.f; 91 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
92 return maxDim < 64.f && maxDim*maxScale < 256.f;
85 } 93 }
86 94
87 95
88 GrPathRenderer::StencilSupport GrAADistanceFieldPathRenderer::onGetStencilSuppor t( 96 GrPathRenderer::StencilSupport GrAADistanceFieldPathRenderer::onGetStencilSuppor t(
89 const SkP ath&, 97 const SkP ath&,
90 const SkS trokeRec&, 98 const SkS trokeRec&,
91 const GrD rawTarget*) const { 99 const GrD rawTarget*) const {
92 return GrPathRenderer::kNoSupport_StencilSupport; 100 return GrPathRenderer::kNoSupport_StencilSupport;
93 } 101 }
94 102
(...skipping 10 matching lines...) Expand all
105 const SkStrokeRec& stroke, 113 const SkStrokeRec& stroke,
106 GrDrawTarget* target, 114 GrDrawTarget* target,
107 bool antiAlias) { 115 bool antiAlias) {
108 // we've already bailed on inverse filled paths, so this is safe 116 // we've already bailed on inverse filled paths, so this is safe
109 if (path.isEmpty()) { 117 if (path.isEmpty()) {
110 return true; 118 return true;
111 } 119 }
112 120
113 SkASSERT(fContext); 121 SkASSERT(fContext);
114 122
123 // get mip level
124 const GrDrawState& drawState = target->getDrawState();
125 const SkMatrix& vm = drawState.getViewMatrix();
126 SkScalar maxScale = vm.getMaxScale();
127 const SkRect& bounds = path.getBounds();
128 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
129 SkScalar size = maxScale*maxDim;
130 uint32_t desiredDimension;
131 if (size <= kSmallMIP) {
132 desiredDimension = kSmallMIP;
133 } else if (size <= kMediumMIP) {
134 desiredDimension = kMediumMIP;
135 } else {
136 desiredDimension = kLargeMIP;
137 }
138
115 // check to see if path is cached 139 // check to see if path is cached
116 // TODO: handle stroked vs. filled version of same path 140 // TODO: handle stroked vs. filled version of same path
117 PathData* pathData = fPathCache.find(path.getGenerationID()); 141 PathData::Key key = { path.getGenerationID(), desiredDimension };
142 PathData* pathData = fPathCache.find(key);
118 if (NULL == pathData) { 143 if (NULL == pathData) {
119 pathData = this->addPathToAtlas(path, stroke, antiAlias); 144 SkScalar scale = desiredDimension/maxDim;
145 pathData = this->addPathToAtlas(path, stroke, antiAlias, desiredDimensio n, scale);
120 if (NULL == pathData) { 146 if (NULL == pathData) {
121 return false; 147 return false;
122 } 148 }
123 } 149 }
124 150
125 // use signed distance field to render 151 // use signed distance field to render
126 return this->internalDrawPath(path, pathData, target); 152 return this->internalDrawPath(path, pathData, target);
127 } 153 }
128 154
129 // factor used to scale the path prior to building distance field
130 const SkScalar kScaleFactor = 2.0f;
131 // padding around path bounds to allow for antialiased pixels 155 // padding around path bounds to allow for antialiased pixels
132 const SkScalar kAntiAliasPad = 1.0f; 156 const SkScalar kAntiAliasPad = 1.0f;
133 157
134 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT oAtlas( 158 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT oAtlas(
135 const Sk Path& path, 159 const Sk Path& path,
136 const Sk StrokeRec& stroke, 160 const Sk StrokeRec& stroke,
137 bool ant iAlias) { 161 bool ant iAlias,
162 uint32_t dimension,
163 SkScalar scale) {
138 164
139 // generate distance field and add to atlas 165 // generate distance field and add to atlas
140 if (NULL == fAtlas) { 166 if (NULL == fAtlas) {
141 SkISize textureSize = SkISize::Make(ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_H EIGHT); 167 SkISize textureSize = SkISize::Make(ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_H EIGHT);
142 fAtlas = SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kAlpha_8_GrPixelConfig , 168 fAtlas = SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kAlpha_8_GrPixelConfig ,
143 kNone_GrSurfaceFlags, textureSize, 169 kNone_GrSurfaceFlags, textureSize,
144 NUM_PLOTS_X, NUM_PLOTS_Y, false)); 170 NUM_PLOTS_X, NUM_PLOTS_Y, false));
145 if (NULL == fAtlas) { 171 if (NULL == fAtlas) {
146 return NULL; 172 return NULL;
147 } 173 }
148 } 174 }
149 175
150 const SkRect& bounds = path.getBounds(); 176 const SkRect& bounds = path.getBounds();
151 177
152 // generate bounding rect for bitmap draw 178 // generate bounding rect for bitmap draw
153 SkRect scaledBounds = bounds; 179 SkRect scaledBounds = bounds;
154 // scale up to improve maxification range 180 // scale to mip level size
155 scaledBounds.fLeft *= kScaleFactor; 181 scaledBounds.fLeft *= scale;
156 scaledBounds.fTop *= kScaleFactor; 182 scaledBounds.fTop *= scale;
157 scaledBounds.fRight *= kScaleFactor; 183 scaledBounds.fRight *= scale;
158 scaledBounds.fBottom *= kScaleFactor; 184 scaledBounds.fBottom *= scale;
159 // move the origin to an integer boundary (gives better results) 185 // move the origin to an integer boundary (gives better results)
160 SkScalar dx = SkScalarFraction(scaledBounds.fLeft); 186 SkScalar dx = SkScalarFraction(scaledBounds.fLeft);
161 SkScalar dy = SkScalarFraction(scaledBounds.fTop); 187 SkScalar dy = SkScalarFraction(scaledBounds.fTop);
162 scaledBounds.offset(-dx, -dy); 188 scaledBounds.offset(-dx, -dy);
163 // get integer boundary 189 // get integer boundary
164 SkIRect devPathBounds; 190 SkIRect devPathBounds;
165 scaledBounds.roundOut(&devPathBounds); 191 scaledBounds.roundOut(&devPathBounds);
166 // pad to allow room for antialiasing 192 // pad to allow room for antialiasing
167 devPathBounds.outset(SkScalarCeilToInt(kAntiAliasPad), SkScalarCeilToInt(kAn tiAliasPad)); 193 devPathBounds.outset(SkScalarCeilToInt(kAntiAliasPad), SkScalarCeilToInt(kAn tiAliasPad));
168 // move origin to upper left corner 194 // move origin to upper left corner
169 devPathBounds.offsetTo(0,0); 195 devPathBounds.offsetTo(0,0);
170 196
171 // draw path to bitmap 197 // draw path to bitmap
172 SkMatrix drawMatrix; 198 SkMatrix drawMatrix;
173 drawMatrix.setTranslate(-bounds.left(), -bounds.top()); 199 drawMatrix.setTranslate(-bounds.left(), -bounds.top());
174 drawMatrix.postScale(kScaleFactor, kScaleFactor); 200 drawMatrix.postScale(scale, scale);
175 drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad); 201 drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad);
176 GrSWMaskHelper helper(fContext); 202 GrSWMaskHelper helper(fContext);
177 203
178 if (!helper.init(devPathBounds, &drawMatrix)) { 204 if (!helper.init(devPathBounds, &drawMatrix)) {
179 return NULL; 205 return NULL;
180 } 206 }
181 helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF); 207 helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF);
182 208
183 // generate signed distance field 209 // generate signed distance field
184 devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad); 210 devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 goto HAS_ATLAS; 245 goto HAS_ATLAS;
220 } 246 }
221 } 247 }
222 248
223 return NULL; 249 return NULL;
224 } 250 }
225 251
226 HAS_ATLAS: 252 HAS_ATLAS:
227 // add to cache 253 // add to cache
228 PathData* pathData = SkNEW(PathData); 254 PathData* pathData = SkNEW(PathData);
229 pathData->fGenID = path.getGenerationID(); 255 pathData->fKey.fGenID = path.getGenerationID();
256 pathData->fKey.fDimension = dimension;
257 pathData->fScale = scale;
230 pathData->fPlot = plot; 258 pathData->fPlot = plot;
231 // change the scaled rect to match the size of the inset distance field 259 // change the scaled rect to match the size of the inset distance field
232 scaledBounds.fRight = scaledBounds.fLeft + 260 scaledBounds.fRight = scaledBounds.fLeft +
233 SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset); 261 SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset);
234 scaledBounds.fBottom = scaledBounds.fTop + 262 scaledBounds.fBottom = scaledBounds.fTop +
235 SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset); 263 SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset);
236 // shift the origin to the correct place relative to the distance field 264 // shift the origin to the correct place relative to the distance field
237 // need to also restore the fractional translation 265 // need to also restore the fractional translation
238 scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dx, 266 scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dx,
239 -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dy); 267 -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dy);
(...skipping 20 matching lines...) Expand all
260 } 288 }
261 plot->resetRects(); 289 plot->resetRects();
262 290
263 // remove any paths that use this plot 291 // remove any paths that use this plot
264 PathDataList::Iter iter; 292 PathDataList::Iter iter;
265 iter.init(fPathList, PathDataList::Iter::kHead_IterStart); 293 iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
266 PathData* pathData; 294 PathData* pathData;
267 while ((pathData = iter.get())) { 295 while ((pathData = iter.get())) {
268 iter.next(); 296 iter.next();
269 if (plot == pathData->fPlot) { 297 if (plot == pathData->fPlot) {
270 fPathCache.remove(pathData->fGenID); 298 fPathCache.remove(pathData->fKey);
271 fPathList.remove(pathData); 299 fPathList.remove(pathData);
272 SkDELETE(pathData); 300 SkDELETE(pathData);
273 #ifdef DF_PATH_TRACKING 301 #ifdef DF_PATH_TRACKING
274 ++g_NumFreedPaths; 302 ++g_NumFreedPaths;
275 #endif 303 #endif
276 } 304 }
277 } 305 }
278 306
279 // tell the atlas to free the plot 307 // tell the atlas to free the plot
280 GrAtlas::RemovePlot(&fPlotUsage, plot); 308 GrAtlas::RemovePlot(&fPlotUsage, plot);
(...skipping 17 matching lines...) Expand all
298 kSDFPathVASize); 326 kSDFPathVASize);
299 void* vertices = NULL; 327 void* vertices = NULL;
300 bool success = target->reserveVertexAndIndexSpace(4, 0, &vertices, NULL); 328 bool success = target->reserveVertexAndIndexSpace(4, 0, &vertices, NULL);
301 GrAlwaysAssert(success); 329 GrAlwaysAssert(success);
302 330
303 SkScalar dx = pathData->fBounds.fLeft; 331 SkScalar dx = pathData->fBounds.fLeft;
304 SkScalar dy = pathData->fBounds.fTop; 332 SkScalar dy = pathData->fBounds.fTop;
305 SkScalar width = pathData->fBounds.width(); 333 SkScalar width = pathData->fBounds.width();
306 SkScalar height = pathData->fBounds.height(); 334 SkScalar height = pathData->fBounds.height();
307 335
308 SkScalar invScale = 1.0f/kScaleFactor; 336 SkScalar invScale = 1.0f/pathData->fScale;
309 dx *= invScale; 337 dx *= invScale;
310 dy *= invScale; 338 dy *= invScale;
311 width *= invScale; 339 width *= invScale;
312 height *= invScale; 340 height *= invScale;
313 341
314 SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX); 342 SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX);
315 SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY); 343 SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY);
316 SkFixed tw = SkScalarToFixed(pathData->fBounds.width()); 344 SkFixed tw = SkScalarToFixed(pathData->fBounds.width());
317 SkFixed th = SkScalarToFixed(pathData->fBounds.height()); 345 SkFixed th = SkScalarToFixed(pathData->fBounds.height());
318 346
(...skipping 27 matching lines...) Expand all
346 drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); 374 drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
347 375
348 vm.mapRect(&r); 376 vm.mapRect(&r);
349 target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); 377 target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
350 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &r); 378 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &r);
351 target->resetVertexSource(); 379 target->resetVertexSource();
352 380
353 return true; 381 return true;
354 } 382 }
355 383
OLDNEW
« no previous file with comments | « src/gpu/GrAADistanceFieldPathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698