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

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

Issue 2064753003: Remove style application from GrPathRenderer subclasses (Closed) Base URL: https://chromium.googlesource.com/skia.git@pathshape
Patch Set: Remove random style from DF batch test create, since it now only allows simple fill Created 4 years, 5 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
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 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 "GrAADistanceFieldPathRenderer.h" 8 #include "GrAADistanceFieldPathRenderer.h"
9 9
10 #include "GrBatchFlushState.h" 10 #include "GrBatchFlushState.h"
(...skipping 13 matching lines...) Expand all
24 24
25 #define ATLAS_TEXTURE_WIDTH 2048 25 #define ATLAS_TEXTURE_WIDTH 2048
26 #define ATLAS_TEXTURE_HEIGHT 2048 26 #define ATLAS_TEXTURE_HEIGHT 2048
27 #define PLOT_WIDTH 512 27 #define PLOT_WIDTH 512
28 #define PLOT_HEIGHT 256 28 #define PLOT_HEIGHT 256
29 29
30 #define NUM_PLOTS_X (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH) 30 #define NUM_PLOTS_X (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH)
31 #define NUM_PLOTS_Y (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT) 31 #define NUM_PLOTS_Y (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT)
32 32
33 #ifdef DF_PATH_TRACKING 33 #ifdef DF_PATH_TRACKING
34 static int g_NumCachedPaths = 0; 34 static int g_NumCachedShapes = 0;
35 static int g_NumFreedPaths = 0; 35 static int g_NumFreedShapes = 0;
36 #endif 36 #endif
37 37
38 // mip levels 38 // mip levels
39 static const int kSmallMIP = 32; 39 static const int kSmallMIP = 32;
40 static const int kMediumMIP = 73; 40 static const int kMediumMIP = 73;
41 static const int kLargeMIP = 162; 41 static const int kLargeMIP = 162;
42 42
43 // Callback to clear out internal path cache when eviction occurs 43 // Callback to clear out internal path cache when eviction occurs
44 void GrAADistanceFieldPathRenderer::HandleEviction(GrBatchAtlas::AtlasID id, voi d* pr) { 44 void GrAADistanceFieldPathRenderer::HandleEviction(GrBatchAtlas::AtlasID id, voi d* pr) {
45 GrAADistanceFieldPathRenderer* dfpr = (GrAADistanceFieldPathRenderer*)pr; 45 GrAADistanceFieldPathRenderer* dfpr = (GrAADistanceFieldPathRenderer*)pr;
46 // remove any paths that use this plot 46 // remove any paths that use this plot
47 PathDataList::Iter iter; 47 ShapeDataList::Iter iter;
48 iter.init(dfpr->fPathList, PathDataList::Iter::kHead_IterStart); 48 iter.init(dfpr->fShapeList, ShapeDataList::Iter::kHead_IterStart);
49 PathData* pathData; 49 ShapeData* shapeData;
50 while ((pathData = iter.get())) { 50 while ((shapeData = iter.get())) {
51 iter.next(); 51 iter.next();
52 if (id == pathData->fID) { 52 if (id == shapeData->fID) {
53 dfpr->fPathCache.remove(pathData->fKey); 53 dfpr->fShapeCache.remove(shapeData->fKey);
54 dfpr->fPathList.remove(pathData); 54 dfpr->fShapeList.remove(shapeData);
55 delete pathData; 55 delete shapeData;
56 #ifdef DF_PATH_TRACKING 56 #ifdef DF_PATH_TRACKING
57 ++g_NumFreedPaths; 57 ++g_NumFreedPaths;
58 #endif 58 #endif
59 } 59 }
60 } 60 }
61 } 61 }
62 62
63 //////////////////////////////////////////////////////////////////////////////// 63 ////////////////////////////////////////////////////////////////////////////////
64 GrAADistanceFieldPathRenderer::GrAADistanceFieldPathRenderer() : fAtlas(nullptr) {} 64 GrAADistanceFieldPathRenderer::GrAADistanceFieldPathRenderer() : fAtlas(nullptr) {}
65 65
66 GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() { 66 GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() {
67 PathDataList::Iter iter; 67 ShapeDataList::Iter iter;
68 iter.init(fPathList, PathDataList::Iter::kHead_IterStart); 68 iter.init(fShapeList, ShapeDataList::Iter::kHead_IterStart);
69 PathData* pathData; 69 ShapeData* shapeData;
70 while ((pathData = iter.get())) { 70 while ((shapeData = iter.get())) {
71 iter.next(); 71 iter.next();
72 fPathList.remove(pathData); 72 delete shapeData;
73 delete pathData;
74 } 73 }
75 delete fAtlas; 74 delete fAtlas;
76 75
77 #ifdef DF_PATH_TRACKING 76 #ifdef DF_PATH_TRACKING
78 SkDebugf("Cached paths: %d, freed paths: %d\n", g_NumCachedPaths, g_NumFreed Paths); 77 SkDebugf("Cached shapes: %d, freed shapes: %d\n", g_NumCachedShapes, g_NumFr eedShapes);
79 #endif 78 #endif
80 } 79 }
81 80
82 //////////////////////////////////////////////////////////////////////////////// 81 ////////////////////////////////////////////////////////////////////////////////
83 bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c onst { 82 bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c onst {
84 // We don't currently apply the dash or factor it into the DF key. (skbug.co m/5082) 83 if (!args.fShaderCaps->shaderDerivativeSupport()) {
85 if (args.fShape->style().pathEffect()) { 84 return false;
85 }
86 // If the shape has no key then we won't get any reuse.
87 if (!args.fShape->hasUnstyledKey()) {
88 return false;
89 }
90 // This only supports filled paths, however, the caller may apply the style to make a filled
91 // path and try again.
92 if (!args.fShape->style().isSimpleFill()) {
93 return false;
94 }
95 // This does non-inverse antialiased fills.
96 if (!args.fAntiAlias) {
86 return false; 97 return false;
87 } 98 }
88 // TODO: Support inverse fill 99 // TODO: Support inverse fill
89 if (!args.fShaderCaps->shaderDerivativeSupport() || !args.fAntiAlias || 100 if (!args.fShape->inverseFilled()) {
90 args.fShape->style().isSimpleHairline() || args.fShape->mayBeInverseFill edAfterStyling() ||
91 !args.fShape->hasUnstyledKey()) {
92 return false; 101 return false;
93 } 102 }
94
95 // currently don't support perspective 103 // currently don't support perspective
96 if (args.fViewMatrix->hasPerspective()) { 104 if (args.fViewMatrix->hasPerspective()) {
97 return false; 105 return false;
98 } 106 }
99 107
100 // only support paths with bounds within kMediumMIP by kMediumMIP, 108 // only support paths with bounds within kMediumMIP by kMediumMIP,
101 // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP 109 // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP
102 // the goal is to accelerate rendering of lots of small paths that may be sc aling 110 // the goal is to accelerate rendering of lots of small paths that may be sc aling
103 SkScalar maxScale = args.fViewMatrix->getMaxScale(); 111 SkScalar maxScale = args.fViewMatrix->getMaxScale();
104 SkRect bounds; 112 SkRect bounds;
105 args.fShape->styledBounds(&bounds); 113 args.fShape->styledBounds(&bounds);
106 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); 114 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
107 115
108 return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP; 116 return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP;
109 } 117 }
110 118
111 //////////////////////////////////////////////////////////////////////////////// 119 ////////////////////////////////////////////////////////////////////////////////
112 120
113 // padding around path bounds to allow for antialiased pixels 121 // padding around path bounds to allow for antialiased pixels
114 static const SkScalar kAntiAliasPad = 1.0f; 122 static const SkScalar kAntiAliasPad = 1.0f;
115 123
116 class AADistanceFieldPathBatch : public GrVertexBatch { 124 class AADistanceFieldPathBatch : public GrVertexBatch {
117 public: 125 public:
118 DEFINE_BATCH_CLASS_ID 126 DEFINE_BATCH_CLASS_ID
119 127
120 typedef GrAADistanceFieldPathRenderer::PathData PathData; 128 typedef GrAADistanceFieldPathRenderer::ShapeData ShapeData;
121 typedef SkTDynamicHash<PathData, PathData::Key> PathCache; 129 typedef SkTDynamicHash<ShapeData, ShapeData::Key> ShapeCache;
122 typedef GrAADistanceFieldPathRenderer::PathDataList PathDataList; 130 typedef GrAADistanceFieldPathRenderer::ShapeDataList ShapeDataList;
123 131
124 struct Geometry { 132 struct Geometry {
125 Geometry(const SkStrokeRec& stroke) : fStroke(stroke) { 133 GrShape fShape;
126 if (!stroke.needToApply()) {
127 // purify unused values to ensure binary equality
128 fStroke.setStrokeParams(SkPaint::kDefault_Cap, SkPaint::kDefault _Join,
129 SkIntToScalar(4));
130 if (fStroke.getWidth() < 0) {
131 fStroke.setStrokeStyle(-1.0f);
132 }
133 }
134 }
135 SkPath fPath;
136 // The unique ID of the path involved in this draw. This may be differen t than the ID
137 // in fPath since that path may have resulted from a SkStrokeRec::applyT oPath call.
138 uint32_t fGenID;
139 SkStrokeRec fStroke;
140 GrColor fColor; 134 GrColor fColor;
141 bool fAntiAlias; 135 bool fAntiAlias;
142 }; 136 };
143 137
144 static GrDrawBatch* Create(const Geometry& geometry, const SkMatrix& viewMat rix, 138 static GrDrawBatch* Create(const Geometry& geometry, const SkMatrix& viewMat rix,
145 GrBatchAtlas* atlas, PathCache* pathCache, PathDa taList* pathList, 139 GrBatchAtlas* atlas, ShapeCache* shapeCache,
146 bool gammaCorrect) { 140 ShapeDataList* shapeList, bool gammaCorrect) {
147 return new AADistanceFieldPathBatch(geometry, viewMatrix, atlas, pathCac he, pathList, 141 return new AADistanceFieldPathBatch(geometry, viewMatrix, atlas, shapeCa che, shapeList,
148 gammaCorrect); 142 gammaCorrect);
149 } 143 }
150 144
151 const char* name() const override { return "AADistanceFieldPathBatch"; } 145 const char* name() const override { return "AADistanceFieldPathBatch"; }
152 146
153 void computePipelineOptimizations(GrInitInvariantOutput* color, 147 void computePipelineOptimizations(GrInitInvariantOutput* color,
154 GrInitInvariantOutput* coverage, 148 GrInitInvariantOutput* coverage,
155 GrBatchToXPOverrides* overrides) const ove rride { 149 GrBatchToXPOverrides* overrides) const ove rride {
156 color->setKnownFourComponents(fGeoData[0].fColor); 150 color->setKnownFourComponents(fGeoData[0].fColor);
157 coverage->setUnknownSingleComponent(); 151 coverage->setUnknownSingleComponent();
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 SkDebugf("Could not allocate vertices\n"); 216 SkDebugf("Could not allocate vertices\n");
223 return; 217 return;
224 } 218 }
225 219
226 flushInfo.fInstancesToFlush = 0; 220 flushInfo.fInstancesToFlush = 0;
227 for (int i = 0; i < instanceCount; i++) { 221 for (int i = 0; i < instanceCount; i++) {
228 const Geometry& args = fGeoData[i]; 222 const Geometry& args = fGeoData[i];
229 223
230 // get mip level 224 // get mip level
231 SkScalar maxScale = this->viewMatrix().getMaxScale(); 225 SkScalar maxScale = this->viewMatrix().getMaxScale();
232 const SkRect& bounds = args.fPath.getBounds(); 226 const SkRect& bounds = args.fShape.bounds();
233 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); 227 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
234 SkScalar size = maxScale * maxDim; 228 SkScalar size = maxScale * maxDim;
235 uint32_t desiredDimension; 229 uint32_t desiredDimension;
236 if (size <= kSmallMIP) { 230 if (size <= kSmallMIP) {
237 desiredDimension = kSmallMIP; 231 desiredDimension = kSmallMIP;
238 } else if (size <= kMediumMIP) { 232 } else if (size <= kMediumMIP) {
239 desiredDimension = kMediumMIP; 233 desiredDimension = kMediumMIP;
240 } else { 234 } else {
241 desiredDimension = kLargeMIP; 235 desiredDimension = kLargeMIP;
242 } 236 }
243 237
244 // check to see if path is cached 238 // check to see if path is cached
245 PathData::Key key(args.fGenID, desiredDimension, args.fStroke); 239 ShapeData::Key key(args.fShape, desiredDimension);
246 PathData* pathData = fPathCache->find(key); 240 ShapeData* shapeData = fShapeCache->find(key);
247 if (nullptr == pathData || !atlas->hasID(pathData->fID)) { 241 if (nullptr == shapeData || !atlas->hasID(shapeData->fID)) {
248 // Remove the stale cache entry 242 // Remove the stale cache entry
249 if (pathData) { 243 if (shapeData) {
250 fPathCache->remove(pathData->fKey); 244 fShapeCache->remove(shapeData->fKey);
251 fPathList->remove(pathData); 245 fShapeList->remove(shapeData);
252 delete pathData; 246 delete shapeData;
253 } 247 }
254 SkScalar scale = desiredDimension/maxDim; 248 SkScalar scale = desiredDimension/maxDim;
255 pathData = new PathData; 249 shapeData = new ShapeData;
256 if (!this->addPathToAtlas(target, 250 if (!this->addPathToAtlas(target,
257 &flushInfo, 251 &flushInfo,
258 atlas, 252 atlas,
259 pathData, 253 shapeData,
260 args.fPath, 254 args.fShape,
261 args.fGenID,
262 args.fStroke,
263 args.fAntiAlias, 255 args.fAntiAlias,
264 desiredDimension, 256 desiredDimension,
265 scale)) { 257 scale)) {
266 SkDebugf("Can't rasterize path\n"); 258 SkDebugf("Can't rasterize path\n");
267 return; 259 return;
268 } 260 }
269 } 261 }
270 262
271 atlas->setLastUseToken(pathData->fID, target->nextDrawToken()); 263 atlas->setLastUseToken(shapeData->fID, target->nextDrawToken());
272 264
273 // Now set vertices 265 // Now set vertices
274 intptr_t offset = reinterpret_cast<intptr_t>(vertices); 266 intptr_t offset = reinterpret_cast<intptr_t>(vertices);
275 offset += i * kVerticesPerQuad * vertexStride; 267 offset += i * kVerticesPerQuad * vertexStride;
276 this->writePathVertices(target, 268 this->writePathVertices(target,
277 atlas, 269 atlas,
278 offset, 270 offset,
279 args.fColor, 271 args.fColor,
280 vertexStride, 272 vertexStride,
281 this->viewMatrix(), 273 this->viewMatrix(),
282 args.fPath, 274 args.fShape,
283 pathData); 275 shapeData);
284 flushInfo.fInstancesToFlush++; 276 flushInfo.fInstancesToFlush++;
285 } 277 }
286 278
287 this->flush(target, &flushInfo); 279 this->flush(target, &flushInfo);
288 } 280 }
289 281
290 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
291
292 AADistanceFieldPathBatch(const Geometry& geometry, 282 AADistanceFieldPathBatch(const Geometry& geometry,
293 const SkMatrix& viewMatrix, 283 const SkMatrix& viewMatrix,
294 GrBatchAtlas* atlas, 284 GrBatchAtlas* atlas,
295 PathCache* pathCache, PathDataList* pathList, 285 ShapeCache* shapeCache, ShapeDataList* shapeList,
296 bool gammaCorrect) 286 bool gammaCorrect)
297 : INHERITED(ClassID()) { 287 : INHERITED(ClassID()) {
288 SkASSERT(geometry.fShape.hasUnstyledKey());
298 fBatch.fViewMatrix = viewMatrix; 289 fBatch.fViewMatrix = viewMatrix;
299 fGeoData.push_back(geometry); 290 fGeoData.push_back(geometry);
291 SkASSERT(fGeoData[0].fShape.hasUnstyledKey());
300 292
301 fAtlas = atlas; 293 fAtlas = atlas;
302 fPathCache = pathCache; 294 fShapeCache = shapeCache;
303 fPathList = pathList; 295 fShapeList = shapeList;
304 fGammaCorrect = gammaCorrect; 296 fGammaCorrect = gammaCorrect;
305 297
306 // Compute bounds 298 // Compute bounds
307 fBounds = geometry.fPath.getBounds(); 299 fBounds = geometry.fShape.bounds();
308 viewMatrix.mapRect(&fBounds); 300 viewMatrix.mapRect(&fBounds);
309 } 301 }
310 302
311 bool addPathToAtlas(GrVertexBatch::Target* target, 303 bool addPathToAtlas(GrVertexBatch::Target* target,
312 FlushInfo* flushInfo, 304 FlushInfo* flushInfo,
313 GrBatchAtlas* atlas, 305 GrBatchAtlas* atlas,
314 PathData* pathData, 306 ShapeData* shapeData,
315 const SkPath& path, 307 const GrShape& shape,
316 uint32_t genID,
317 const SkStrokeRec& stroke,
318 bool antiAlias, 308 bool antiAlias,
319 uint32_t dimension, 309 uint32_t dimension,
320 SkScalar scale) const { 310 SkScalar scale) const {
321 const SkRect& bounds = path.getBounds(); 311 const SkRect& bounds = shape.bounds();
322 312
323 // generate bounding rect for bitmap draw 313 // generate bounding rect for bitmap draw
324 SkRect scaledBounds = bounds; 314 SkRect scaledBounds = bounds;
325 // scale to mip level size 315 // scale to mip level size
326 scaledBounds.fLeft *= scale; 316 scaledBounds.fLeft *= scale;
327 scaledBounds.fTop *= scale; 317 scaledBounds.fTop *= scale;
328 scaledBounds.fRight *= scale; 318 scaledBounds.fRight *= scale;
329 scaledBounds.fBottom *= scale; 319 scaledBounds.fBottom *= scale;
330 // move the origin to an integer boundary (gives better results) 320 // move the origin to an integer boundary (gives better results)
331 SkScalar dx = SkScalarFraction(scaledBounds.fLeft); 321 SkScalar dx = SkScalarFraction(scaledBounds.fLeft);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 358
369 SkDraw draw; 359 SkDraw draw;
370 sk_bzero(&draw, sizeof(draw)); 360 sk_bzero(&draw, sizeof(draw));
371 361
372 SkRasterClip rasterClip; 362 SkRasterClip rasterClip;
373 rasterClip.setRect(devPathBounds); 363 rasterClip.setRect(devPathBounds);
374 draw.fRC = &rasterClip; 364 draw.fRC = &rasterClip;
375 draw.fMatrix = &drawMatrix; 365 draw.fMatrix = &drawMatrix;
376 draw.fDst = dst; 366 draw.fDst = dst;
377 367
368 SkPath path;
369 shape.asPath(&path);
378 draw.drawPathCoverage(path, paint); 370 draw.drawPathCoverage(path, paint);
379 371
380 // generate signed distance field 372 // generate signed distance field
381 devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad); 373 devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
382 width = devPathBounds.width(); 374 width = devPathBounds.width();
383 height = devPathBounds.height(); 375 height = devPathBounds.height();
384 // TODO We should really generate this directly into the plot somehow 376 // TODO We should really generate this directly into the plot somehow
385 SkAutoSMalloc<1024> dfStorage(width * height * sizeof(unsigned char)); 377 SkAutoSMalloc<1024> dfStorage(width * height * sizeof(unsigned char));
386 378
387 // Generate signed distance field 379 // Generate signed distance field
388 SkGenerateDistanceFieldFromA8Image((unsigned char*)dfStorage.get(), 380 SkGenerateDistanceFieldFromA8Image((unsigned char*)dfStorage.get(),
389 (const unsigned char*)dst.addr(), 381 (const unsigned char*)dst.addr(),
390 dst.width(), dst.height(), dst.rowByt es()); 382 dst.width(), dst.height(), dst.rowByt es());
391 383
392 // add to atlas 384 // add to atlas
393 SkIPoint16 atlasLocation; 385 SkIPoint16 atlasLocation;
394 GrBatchAtlas::AtlasID id; 386 GrBatchAtlas::AtlasID id;
395 bool success = atlas->addToAtlas(&id, target, width, height, dfStorage.g et(), 387 bool success = atlas->addToAtlas(&id, target, width, height, dfStorage.g et(),
396 &atlasLocation); 388 &atlasLocation);
397 if (!success) { 389 if (!success) {
398 this->flush(target, flushInfo); 390 this->flush(target, flushInfo);
399 391
400 SkDEBUGCODE(success =) atlas->addToAtlas(&id, target, width, height, 392 SkDEBUGCODE(success =) atlas->addToAtlas(&id, target, width, height,
401 dfStorage.get(), &atlasLoca tion); 393 dfStorage.get(), &atlasLoca tion);
402 SkASSERT(success); 394 SkASSERT(success);
403 395
404 } 396 }
405 397
406 // add to cache 398 // add to cache
407 pathData->fKey = PathData::Key(genID, dimension, stroke); 399 shapeData->fKey.set(shape, dimension);
408 pathData->fScale = scale; 400 shapeData->fScale = scale;
409 pathData->fID = id; 401 shapeData->fID = id;
410 // change the scaled rect to match the size of the inset distance field 402 // change the scaled rect to match the size of the inset distance field
411 scaledBounds.fRight = scaledBounds.fLeft + 403 scaledBounds.fRight = scaledBounds.fLeft +
412 SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset); 404 SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset);
413 scaledBounds.fBottom = scaledBounds.fTop + 405 scaledBounds.fBottom = scaledBounds.fTop +
414 SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset); 406 SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset);
415 // shift the origin to the correct place relative to the distance field 407 // shift the origin to the correct place relative to the distance field
416 // need to also restore the fractional translation 408 // need to also restore the fractional translation
417 scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPa d + dx, 409 scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPa d + dx,
418 -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPa d + dy); 410 -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPa d + dy);
419 pathData->fBounds = scaledBounds; 411 shapeData->fBounds = scaledBounds;
420 // origin we render from is inset from distance field edge 412 // origin we render from is inset from distance field edge
421 atlasLocation.fX += SK_DistanceFieldInset; 413 atlasLocation.fX += SK_DistanceFieldInset;
422 atlasLocation.fY += SK_DistanceFieldInset; 414 atlasLocation.fY += SK_DistanceFieldInset;
423 pathData->fAtlasLocation = atlasLocation; 415 shapeData->fAtlasLocation = atlasLocation;
424 416
425 fPathCache->add(pathData); 417 fShapeCache->add(shapeData);
426 fPathList->addToTail(pathData); 418 fShapeList->addToTail(shapeData);
427 #ifdef DF_PATH_TRACKING 419 #ifdef DF_PATH_TRACKING
428 ++g_NumCachedPaths; 420 ++g_NumCachedPaths;
429 #endif 421 #endif
430 return true; 422 return true;
431 } 423 }
432 424
433 void writePathVertices(GrDrawBatch::Target* target, 425 void writePathVertices(GrDrawBatch::Target* target,
434 GrBatchAtlas* atlas, 426 GrBatchAtlas* atlas,
435 intptr_t offset, 427 intptr_t offset,
436 GrColor color, 428 GrColor color,
437 size_t vertexStride, 429 size_t vertexStride,
438 const SkMatrix& viewMatrix, 430 const SkMatrix& viewMatrix,
439 const SkPath& path, 431 const GrShape& shape,
440 const PathData* pathData) const { 432 const ShapeData* shapeData) const {
441 GrTexture* texture = atlas->getTexture(); 433 GrTexture* texture = atlas->getTexture();
442 434
443 SkScalar dx = pathData->fBounds.fLeft; 435 SkScalar dx = shapeData->fBounds.fLeft;
444 SkScalar dy = pathData->fBounds.fTop; 436 SkScalar dy = shapeData->fBounds.fTop;
445 SkScalar width = pathData->fBounds.width(); 437 SkScalar width = shapeData->fBounds.width();
446 SkScalar height = pathData->fBounds.height(); 438 SkScalar height = shapeData->fBounds.height();
447 439
448 SkScalar invScale = 1.0f / pathData->fScale; 440 SkScalar invScale = 1.0f / shapeData->fScale;
449 dx *= invScale; 441 dx *= invScale;
450 dy *= invScale; 442 dy *= invScale;
451 width *= invScale; 443 width *= invScale;
452 height *= invScale; 444 height *= invScale;
453 445
454 SkPoint* positions = reinterpret_cast<SkPoint*>(offset); 446 SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
455 447
456 // vertex positions 448 // vertex positions
457 // TODO make the vertex attributes a struct 449 // TODO make the vertex attributes a struct
458 SkRect r = SkRect::MakeXYWH(dx, dy, width, height); 450 SkRect r = SkRect::MakeXYWH(dx, dy, width, height);
459 positions->setRectFan(r.left(), r.top(), r.right(), r.bottom(), vertexSt ride); 451 positions->setRectFan(r.left(), r.top(), r.right(), r.bottom(), vertexSt ride);
460 452
461 // colors 453 // colors
462 for (int i = 0; i < kVerticesPerQuad; i++) { 454 for (int i = 0; i < kVerticesPerQuad; i++) {
463 GrColor* colorPtr = (GrColor*)(offset + sizeof(SkPoint) + i * vertex Stride); 455 GrColor* colorPtr = (GrColor*)(offset + sizeof(SkPoint) + i * vertex Stride);
464 *colorPtr = color; 456 *colorPtr = color;
465 } 457 }
466 458
467 const SkScalar tx = SkIntToScalar(pathData->fAtlasLocation.fX); 459 const SkScalar tx = SkIntToScalar(shapeData->fAtlasLocation.fX);
468 const SkScalar ty = SkIntToScalar(pathData->fAtlasLocation.fY); 460 const SkScalar ty = SkIntToScalar(shapeData->fAtlasLocation.fY);
469 461
470 // vertex texture coords 462 // vertex texture coords
471 SkPoint* textureCoords = (SkPoint*)(offset + sizeof(SkPoint) + sizeof(Gr Color)); 463 SkPoint* textureCoords = (SkPoint*)(offset + sizeof(SkPoint) + sizeof(Gr Color));
472 textureCoords->setRectFan(tx / texture->width(), 464 textureCoords->setRectFan(tx / texture->width(),
473 ty / texture->height(), 465 ty / texture->height(),
474 (tx + pathData->fBounds.width()) / texture->wi dth(), 466 (tx + shapeData->fBounds.width()) / texture->w idth(),
475 (ty + pathData->fBounds.height()) / texture-> height(), 467 (ty + shapeData->fBounds.height()) / texture- >height(),
476 vertexStride); 468 vertexStride);
477 } 469 }
478 470
479 void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const { 471 void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const {
480 GrMesh mesh; 472 GrMesh mesh;
481 int maxInstancesPerDraw = 473 int maxInstancesPerDraw =
482 static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(u int16_t) / 6); 474 static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(u int16_t) / 6);
483 mesh.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer, 475 mesh.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer,
484 flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerQuad, 476 flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerQuad,
485 kIndicesPerQuad, flushInfo->fInstancesToFlush, maxInstancesPerDraw); 477 kIndicesPerQuad, flushInfo->fInstancesToFlush, maxInstancesPerDraw);
(...skipping 11 matching lines...) Expand all
497 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), 489 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
498 that->bounds(), caps)) { 490 that->bounds(), caps)) {
499 return false; 491 return false;
500 } 492 }
501 493
502 // TODO We can position on the cpu 494 // TODO We can position on the cpu
503 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { 495 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
504 return false; 496 return false;
505 } 497 }
506 498
507 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; 499 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin());
508 this->joinBounds(that->bounds()); 500 this->joinBounds(that->bounds());
509 return true; 501 return true;
510 } 502 }
511 503
512 struct BatchTracker { 504 struct BatchTracker {
513 SkMatrix fViewMatrix; 505 SkMatrix fViewMatrix;
514 bool fUsesLocalCoords; 506 bool fUsesLocalCoords;
515 bool fColorIgnored; 507 bool fColorIgnored;
516 bool fCoverageIgnored; 508 bool fCoverageIgnored;
517 }; 509 };
518 510
519 BatchTracker fBatch; 511 BatchTracker fBatch;
520 SkSTArray<1, Geometry, true> fGeoData; 512 SkSTArray<1, Geometry> fGeoData;
521 GrBatchAtlas* fAtlas; 513 GrBatchAtlas* fAtlas;
522 PathCache* fPathCache; 514 ShapeCache* fShapeCache;
523 PathDataList* fPathList; 515 ShapeDataList* fShapeList;
524 bool fGammaCorrect; 516 bool fGammaCorrect;
525 517
526 typedef GrVertexBatch INHERITED; 518 typedef GrVertexBatch INHERITED;
527 }; 519 };
528 520
529 bool GrAADistanceFieldPathRenderer::onDrawPath(const DrawPathArgs& args) { 521 bool GrAADistanceFieldPathRenderer::onDrawPath(const DrawPathArgs& args) {
530 GR_AUDIT_TRAIL_AUTO_FRAME(args.fDrawContext->auditTrail(), 522 GR_AUDIT_TRAIL_AUTO_FRAME(args.fDrawContext->auditTrail(),
531 "GrAADistanceFieldPathRenderer::onDrawPath"); 523 "GrAADistanceFieldPathRenderer::onDrawPath");
532 SkASSERT(!args.fDrawContext->isUnifiedMultisampled()); 524 SkASSERT(!args.fDrawContext->isUnifiedMultisampled());
525 SkASSERT(args.fShape->style().isSimpleFill());
533 526
534 // we've already bailed on inverse filled paths, so this is safe 527 // we've already bailed on inverse filled paths, so this is safe
535 SkASSERT(!args.fShape->isEmpty()); 528 SkASSERT(!args.fShape->isEmpty());
536 529 SkASSERT(args.fShape->hasUnstyledKey());
537 if (!fAtlas) { 530 if (!fAtlas) {
538 fAtlas = args.fResourceProvider->createAtlas(kAlpha_8_GrPixelConfig, 531 fAtlas = args.fResourceProvider->createAtlas(kAlpha_8_GrPixelConfig,
539 ATLAS_TEXTURE_WIDTH, ATLAS_ TEXTURE_HEIGHT, 532 ATLAS_TEXTURE_WIDTH, ATLAS_ TEXTURE_HEIGHT,
540 NUM_PLOTS_X, NUM_PLOTS_Y, 533 NUM_PLOTS_X, NUM_PLOTS_Y,
541 &GrAADistanceFieldPathRende rer::HandleEviction, 534 &GrAADistanceFieldPathRende rer::HandleEviction,
542 (void*)this); 535 (void*)this);
543 if (!fAtlas) { 536 if (!fAtlas) {
544 return false; 537 return false;
545 } 538 }
546 } 539 }
547 540
548 const GrStyle& style = args.fShape->style(); 541 AADistanceFieldPathBatch::Geometry geometry;
549 // It's ok to ignore style's path effect because canDrawPath filtered out pa th effects. 542 geometry.fShape = *args.fShape;
550 AADistanceFieldPathBatch::Geometry geometry(style.strokeRec());
551 args.fShape->asPath(&geometry.fPath);
552 // Note: this is the generation ID of the _original_ path. When a new path i s
553 // generated due to stroking it is important that the original path's id is used
554 // for caching.
555 geometry.fGenID = geometry.fPath.getGenerationID();
556 if (!style.isSimpleFill()) {
557 style.strokeRec().applyToPath(&geometry.fPath, geometry.fPath);
558 }
559 geometry.fColor = args.fColor; 543 geometry.fColor = args.fColor;
560 geometry.fAntiAlias = args.fAntiAlias; 544 geometry.fAntiAlias = args.fAntiAlias;
561 545
562 SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry, 546 SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry,
563 *args.fView Matrix, fAtlas, 547 *args.fView Matrix, fAtlas,
564 &fPathCache , &fPathList, 548 &fShapeCach e, &fShapeList,
565 args.fGamma Correct)); 549 args.fGamma Correct));
566 550
567 GrPipelineBuilder pipelineBuilder(*args.fPaint); 551 GrPipelineBuilder pipelineBuilder(*args.fPaint);
568 pipelineBuilder.setUserStencil(args.fUserStencilSettings); 552 pipelineBuilder.setUserStencil(args.fUserStencilSettings);
569 553
570 args.fDrawContext->drawBatch(pipelineBuilder, *args.fClip, batch); 554 args.fDrawContext->drawBatch(pipelineBuilder, *args.fClip, batch);
571 555
572 return true; 556 return true;
573 } 557 }
574 558
575 //////////////////////////////////////////////////////////////////////////////// /////////////////// 559 //////////////////////////////////////////////////////////////////////////////// ///////////////////
576 560
577 #ifdef GR_TEST_UTILS 561 #ifdef GR_TEST_UTILS
578 562
579 struct PathTestStruct { 563 struct PathTestStruct {
580 typedef GrAADistanceFieldPathRenderer::PathCache PathCache; 564 typedef GrAADistanceFieldPathRenderer::ShapeCache ShapeCache;
581 typedef GrAADistanceFieldPathRenderer::PathData PathData; 565 typedef GrAADistanceFieldPathRenderer::ShapeData ShapeData;
582 typedef GrAADistanceFieldPathRenderer::PathDataList PathDataList; 566 typedef GrAADistanceFieldPathRenderer::ShapeDataList ShapeDataList;
583 PathTestStruct() : fContextID(SK_InvalidGenID), fAtlas(nullptr) {} 567 PathTestStruct() : fContextID(SK_InvalidGenID), fAtlas(nullptr) {}
584 ~PathTestStruct() { this->reset(); } 568 ~PathTestStruct() { this->reset(); }
585 569
586 void reset() { 570 void reset() {
587 PathDataList::Iter iter; 571 ShapeDataList::Iter iter;
588 iter.init(fPathList, PathDataList::Iter::kHead_IterStart); 572 iter.init(fShapeList, ShapeDataList::Iter::kHead_IterStart);
589 PathData* pathData; 573 ShapeData* shapeData;
590 while ((pathData = iter.get())) { 574 while ((shapeData = iter.get())) {
591 iter.next(); 575 iter.next();
592 fPathList.remove(pathData); 576 fShapeList.remove(shapeData);
593 delete pathData; 577 delete shapeData;
594 } 578 }
595 delete fAtlas; 579 delete fAtlas;
596 fPathCache.reset(); 580 fShapeCache.reset();
597 } 581 }
598 582
599 static void HandleEviction(GrBatchAtlas::AtlasID id, void* pr) { 583 static void HandleEviction(GrBatchAtlas::AtlasID id, void* pr) {
600 PathTestStruct* dfpr = (PathTestStruct*)pr; 584 PathTestStruct* dfpr = (PathTestStruct*)pr;
601 // remove any paths that use this plot 585 // remove any paths that use this plot
602 PathDataList::Iter iter; 586 ShapeDataList::Iter iter;
603 iter.init(dfpr->fPathList, PathDataList::Iter::kHead_IterStart); 587 iter.init(dfpr->fShapeList, ShapeDataList::Iter::kHead_IterStart);
604 PathData* pathData; 588 ShapeData* shapeData;
605 while ((pathData = iter.get())) { 589 while ((shapeData = iter.get())) {
606 iter.next(); 590 iter.next();
607 if (id == pathData->fID) { 591 if (id == shapeData->fID) {
608 dfpr->fPathCache.remove(pathData->fKey); 592 dfpr->fShapeCache.remove(shapeData->fKey);
609 dfpr->fPathList.remove(pathData); 593 dfpr->fShapeList.remove(shapeData);
610 delete pathData; 594 delete shapeData;
611 } 595 }
612 } 596 }
613 } 597 }
614 598
615 uint32_t fContextID; 599 uint32_t fContextID;
616 GrBatchAtlas* fAtlas; 600 GrBatchAtlas* fAtlas;
617 PathCache fPathCache; 601 ShapeCache fShapeCache;
618 PathDataList fPathList; 602 ShapeDataList fShapeList;
619 }; 603 };
620 604
621 DRAW_BATCH_TEST_DEFINE(AADistanceFieldPathBatch) { 605 DRAW_BATCH_TEST_DEFINE(AADistanceFieldPathBatch) {
622 static PathTestStruct gTestStruct; 606 static PathTestStruct gTestStruct;
623 607
624 if (context->uniqueID() != gTestStruct.fContextID) { 608 if (context->uniqueID() != gTestStruct.fContextID) {
625 gTestStruct.fContextID = context->uniqueID(); 609 gTestStruct.fContextID = context->uniqueID();
626 gTestStruct.reset(); 610 gTestStruct.reset();
627 gTestStruct.fAtlas = 611 gTestStruct.fAtlas =
628 context->resourceProvider()->createAtlas(kAlpha_8_GrPixelConfig, 612 context->resourceProvider()->createAtlas(kAlpha_8_GrPixelConfig,
629 ATLAS_TEXTURE_WIDTH, ATLAS_ TEXTURE_HEIGHT, 613 ATLAS_TEXTURE_WIDTH, ATLAS_ TEXTURE_HEIGHT,
630 NUM_PLOTS_X, NUM_PLOTS_Y, 614 NUM_PLOTS_X, NUM_PLOTS_Y,
631 &PathTestStruct::HandleEvic tion, 615 &PathTestStruct::HandleEvic tion,
632 (void*)&gTestStruct); 616 (void*)&gTestStruct);
633 } 617 }
634 618
635 SkMatrix viewMatrix = GrTest::TestMatrix(random); 619 SkMatrix viewMatrix = GrTest::TestMatrix(random);
636 GrColor color = GrRandomColor(random); 620 GrColor color = GrRandomColor(random);
637 bool gammaCorrect = random->nextBool(); 621 bool gammaCorrect = random->nextBool();
638 622
639 AADistanceFieldPathBatch::Geometry geometry(GrTest::TestStrokeRec(random)); 623 AADistanceFieldPathBatch::Geometry geometry;
624 // This path renderer only allows fill styles.
625 GrShape shape(GrTest::TestPath(random), GrStyle::SimpleFill());
626 geometry.fShape = shape;
640 geometry.fColor = color; 627 geometry.fColor = color;
641 geometry.fPath = GrTest::TestPath(random);
642 geometry.fAntiAlias = random->nextBool(); 628 geometry.fAntiAlias = random->nextBool();
643 geometry.fGenID = random->nextU();
644 629
645 return AADistanceFieldPathBatch::Create(geometry, viewMatrix, 630 return AADistanceFieldPathBatch::Create(geometry, viewMatrix,
646 gTestStruct.fAtlas, 631 gTestStruct.fAtlas,
647 &gTestStruct.fPathCache, 632 &gTestStruct.fShapeCache,
648 &gTestStruct.fPathList, 633 &gTestStruct.fShapeList,
649 gammaCorrect); 634 gammaCorrect);
650 } 635 }
651 636
652 #endif 637 #endif
OLDNEW
« no previous file with comments | « src/gpu/batches/GrAADistanceFieldPathRenderer.h ('k') | src/gpu/batches/GrDefaultPathRenderer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698