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

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 ignored GMs 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
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
robertphillips 2014/10/29 19:55:02 Double plot height too ?
jvanverth1 2014/10/30 12:48:28 No, they can stay 256x256. I'm just trying to doub
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
robertphillips 2014/10/29 19:55:02 // The goal is to accelerate rendering of lots of
jvanverth1 2014/10/30 12:48:28 Done.
88 SkScalar maxScale = vm.getMaxScale();
83 const SkRect& bounds = path.getBounds(); 89 const SkRect& bounds = path.getBounds();
84 return bounds.width() < 64.f && bounds.height() < 64.f; 90 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
91 return maxDim < 64.f && maxDim*maxScale < 256.f;
85 } 92 }
86 93
87 94
88 GrPathRenderer::StencilSupport GrAADistanceFieldPathRenderer::onGetStencilSuppor t( 95 GrPathRenderer::StencilSupport GrAADistanceFieldPathRenderer::onGetStencilSuppor t(
89 const SkP ath&, 96 const SkP ath&,
90 const SkS trokeRec&, 97 const SkS trokeRec&,
91 const GrD rawTarget*) const { 98 const GrD rawTarget*) const {
92 return GrPathRenderer::kNoSupport_StencilSupport; 99 return GrPathRenderer::kNoSupport_StencilSupport;
93 } 100 }
94 101
(...skipping 10 matching lines...) Expand all
105 const SkStrokeRec& stroke, 112 const SkStrokeRec& stroke,
106 GrDrawTarget* target, 113 GrDrawTarget* target,
107 bool antiAlias) { 114 bool antiAlias) {
108 // we've already bailed on inverse filled paths, so this is safe 115 // we've already bailed on inverse filled paths, so this is safe
109 if (path.isEmpty()) { 116 if (path.isEmpty()) {
110 return true; 117 return true;
111 } 118 }
112 119
113 SkASSERT(fContext); 120 SkASSERT(fContext);
114 121
122 // get mip level
123 const GrDrawState& drawState = target->getDrawState();
124 const SkMatrix& vm = drawState.getViewMatrix();
125 SkScalar maxScale = vm.getMaxScale();
126 const SkRect& bounds = path.getBounds();
127 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
128 SkScalar size = maxScale*maxDim;
129 uint32_t mipLevel;
130 if (size <= kSmallMIP) {
131 mipLevel = kSmallMIP;
132 } else if (size <= kMediumMIP) {
133 mipLevel = kMediumMIP;
134 } else {
135 mipLevel = kLargeMIP;
136 }
137
115 // check to see if path is cached 138 // check to see if path is cached
116 // TODO: handle stroked vs. filled version of same path 139 // TODO: handle stroked vs. filled version of same path
117 PathData* pathData = fPathCache.find(path.getGenerationID()); 140 PathData::Key key = { path.getGenerationID(), mipLevel };
141 PathData* pathData = fPathCache.find(key);
118 if (NULL == pathData) { 142 if (NULL == pathData) {
119 pathData = this->addPathToAtlas(path, stroke, antiAlias); 143 SkScalar scale = mipLevel/maxDim;
144 pathData = this->addPathToAtlas(path, stroke, antiAlias, mipLevel, scale );
120 if (NULL == pathData) { 145 if (NULL == pathData) {
121 return false; 146 return false;
122 } 147 }
123 } 148 }
124 149
125 // use signed distance field to render 150 // use signed distance field to render
126 return this->internalDrawPath(path, pathData, target); 151 return this->internalDrawPath(path, pathData, target);
127 } 152 }
128 153
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 154 // padding around path bounds to allow for antialiased pixels
132 const SkScalar kAntiAliasPad = 1.0f; 155 const SkScalar kAntiAliasPad = 1.0f;
133 156
134 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT oAtlas( 157 GrAADistanceFieldPathRenderer::PathData* GrAADistanceFieldPathRenderer::addPathT oAtlas(
135 const Sk Path& path, 158 const Sk Path& path,
136 const Sk StrokeRec& stroke, 159 const Sk StrokeRec& stroke,
137 bool ant iAlias) { 160 bool ant iAlias,
161 uint32_t mipLevel,
162 SkScalar scale) {
138 163
139 // generate distance field and add to atlas 164 // generate distance field and add to atlas
140 if (NULL == fAtlas) { 165 if (NULL == fAtlas) {
141 SkISize textureSize = SkISize::Make(ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_H EIGHT); 166 SkISize textureSize = SkISize::Make(ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_H EIGHT);
142 fAtlas = SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kAlpha_8_GrPixelConfig , 167 fAtlas = SkNEW_ARGS(GrAtlas, (fContext->getGpu(), kAlpha_8_GrPixelConfig ,
143 kNone_GrSurfaceFlags, textureSize, 168 kNone_GrSurfaceFlags, textureSize,
144 NUM_PLOTS_X, NUM_PLOTS_Y, false)); 169 NUM_PLOTS_X, NUM_PLOTS_Y, false));
145 if (NULL == fAtlas) { 170 if (NULL == fAtlas) {
146 return NULL; 171 return NULL;
147 } 172 }
148 } 173 }
149 174
150 const SkRect& bounds = path.getBounds(); 175 const SkRect& bounds = path.getBounds();
151 176
152 // generate bounding rect for bitmap draw 177 // generate bounding rect for bitmap draw
153 SkRect scaledBounds = bounds; 178 SkRect scaledBounds = bounds;
154 // scale up to improve maxification range 179 // scale to mip level size
155 scaledBounds.fLeft *= kScaleFactor; 180 scaledBounds.fLeft *= scale;
156 scaledBounds.fTop *= kScaleFactor; 181 scaledBounds.fTop *= scale;
157 scaledBounds.fRight *= kScaleFactor; 182 scaledBounds.fRight *= scale;
158 scaledBounds.fBottom *= kScaleFactor; 183 scaledBounds.fBottom *= scale;
159 // move the origin to an integer boundary (gives better results) 184 // move the origin to an integer boundary (gives better results)
160 SkScalar dx = SkScalarFraction(scaledBounds.fLeft); 185 SkScalar dx = SkScalarFraction(scaledBounds.fLeft);
161 SkScalar dy = SkScalarFraction(scaledBounds.fTop); 186 SkScalar dy = SkScalarFraction(scaledBounds.fTop);
162 scaledBounds.offset(-dx, -dy); 187 scaledBounds.offset(-dx, -dy);
163 // get integer boundary 188 // get integer boundary
164 SkIRect devPathBounds; 189 SkIRect devPathBounds;
165 scaledBounds.roundOut(&devPathBounds); 190 scaledBounds.roundOut(&devPathBounds);
166 // pad to allow room for antialiasing 191 // pad to allow room for antialiasing
167 devPathBounds.outset(SkScalarCeilToInt(kAntiAliasPad), SkScalarCeilToInt(kAn tiAliasPad)); 192 devPathBounds.outset(SkScalarCeilToInt(kAntiAliasPad), SkScalarCeilToInt(kAn tiAliasPad));
168 // move origin to upper left corner 193 // move origin to upper left corner
169 devPathBounds.offsetTo(0,0); 194 devPathBounds.offsetTo(0,0);
170 195
171 // draw path to bitmap 196 // draw path to bitmap
172 SkMatrix drawMatrix; 197 SkMatrix drawMatrix;
173 drawMatrix.setTranslate(-bounds.left(), -bounds.top()); 198 drawMatrix.setTranslate(-bounds.left(), -bounds.top());
174 drawMatrix.postScale(kScaleFactor, kScaleFactor); 199 drawMatrix.postScale(scale, scale);
175 drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad); 200 drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad);
176 GrSWMaskHelper helper(fContext); 201 GrSWMaskHelper helper(fContext);
177 202
178 if (!helper.init(devPathBounds, &drawMatrix)) { 203 if (!helper.init(devPathBounds, &drawMatrix)) {
179 return NULL; 204 return NULL;
180 } 205 }
181 helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF); 206 helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF);
182 207
183 // generate signed distance field 208 // generate signed distance field
184 devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad); 209 devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 goto HAS_ATLAS; 244 goto HAS_ATLAS;
220 } 245 }
221 } 246 }
222 247
223 return NULL; 248 return NULL;
224 } 249 }
225 250
226 HAS_ATLAS: 251 HAS_ATLAS:
227 // add to cache 252 // add to cache
228 PathData* pathData = SkNEW(PathData); 253 PathData* pathData = SkNEW(PathData);
229 pathData->fGenID = path.getGenerationID(); 254 pathData->fKey.fGenID = path.getGenerationID();
255 pathData->fKey.fMipLevel = mipLevel;
256 pathData->fScale = scale;
230 pathData->fPlot = plot; 257 pathData->fPlot = plot;
231 // change the scaled rect to match the size of the inset distance field 258 // change the scaled rect to match the size of the inset distance field
232 scaledBounds.fRight = scaledBounds.fLeft + 259 scaledBounds.fRight = scaledBounds.fLeft +
233 SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset); 260 SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset);
234 scaledBounds.fBottom = scaledBounds.fTop + 261 scaledBounds.fBottom = scaledBounds.fTop +
235 SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset); 262 SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset);
236 // shift the origin to the correct place relative to the distance field 263 // shift the origin to the correct place relative to the distance field
237 // need to also restore the fractional translation 264 // need to also restore the fractional translation
238 scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dx, 265 scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dx,
239 -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dy); 266 -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPad + dy);
(...skipping 20 matching lines...) Expand all
260 } 287 }
261 plot->resetRects(); 288 plot->resetRects();
262 289
263 // remove any paths that use this plot 290 // remove any paths that use this plot
264 PathDataList::Iter iter; 291 PathDataList::Iter iter;
265 iter.init(fPathList, PathDataList::Iter::kHead_IterStart); 292 iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
266 PathData* pathData; 293 PathData* pathData;
267 while ((pathData = iter.get())) { 294 while ((pathData = iter.get())) {
268 iter.next(); 295 iter.next();
269 if (plot == pathData->fPlot) { 296 if (plot == pathData->fPlot) {
270 fPathCache.remove(pathData->fGenID); 297 fPathCache.remove(pathData->fKey);
271 fPathList.remove(pathData); 298 fPathList.remove(pathData);
272 SkDELETE(pathData); 299 SkDELETE(pathData);
273 #ifdef DF_PATH_TRACKING 300 #ifdef DF_PATH_TRACKING
274 ++g_NumFreedPaths; 301 ++g_NumFreedPaths;
275 #endif 302 #endif
276 } 303 }
277 } 304 }
278 305
279 // tell the atlas to free the plot 306 // tell the atlas to free the plot
280 GrAtlas::RemovePlot(&fPlotUsage, plot); 307 GrAtlas::RemovePlot(&fPlotUsage, plot);
(...skipping 17 matching lines...) Expand all
298 kSDFPathVASize); 325 kSDFPathVASize);
299 void* vertices = NULL; 326 void* vertices = NULL;
300 bool success = target->reserveVertexAndIndexSpace(4, 0, &vertices, NULL); 327 bool success = target->reserveVertexAndIndexSpace(4, 0, &vertices, NULL);
301 GrAlwaysAssert(success); 328 GrAlwaysAssert(success);
302 329
303 SkScalar dx = pathData->fBounds.fLeft; 330 SkScalar dx = pathData->fBounds.fLeft;
304 SkScalar dy = pathData->fBounds.fTop; 331 SkScalar dy = pathData->fBounds.fTop;
305 SkScalar width = pathData->fBounds.width(); 332 SkScalar width = pathData->fBounds.width();
306 SkScalar height = pathData->fBounds.height(); 333 SkScalar height = pathData->fBounds.height();
307 334
308 SkScalar invScale = 1.0f/kScaleFactor; 335 SkScalar invScale = 1.0f/pathData->fScale;
309 dx *= invScale; 336 dx *= invScale;
310 dy *= invScale; 337 dy *= invScale;
311 width *= invScale; 338 width *= invScale;
312 height *= invScale; 339 height *= invScale;
313 340
314 SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX); 341 SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX);
315 SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY); 342 SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY);
316 SkFixed tw = SkScalarToFixed(pathData->fBounds.width()); 343 SkFixed tw = SkScalarToFixed(pathData->fBounds.width());
317 SkFixed th = SkScalarToFixed(pathData->fBounds.height()); 344 SkFixed th = SkScalarToFixed(pathData->fBounds.height());
318 345
(...skipping 27 matching lines...) Expand all
346 drawState->setGeometryProcessor(fCachedGeometryProcessor.get()); 373 drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
347 374
348 vm.mapRect(&r); 375 vm.mapRect(&r);
349 target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); 376 target->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
350 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &r); 377 target->drawIndexedInstances(kTriangles_GrPrimitiveType, 1, 4, 6, &r);
351 target->resetVertexSource(); 378 target->resetVertexSource();
352 379
353 return true; 380 return true;
354 } 381 }
355 382
OLDNEW
« src/gpu/GrAADistanceFieldPathRenderer.h ('K') | « src/gpu/GrAADistanceFieldPathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698