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

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

Issue 1306143005: Move Pathrenderers to batches folder (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 5 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/GrAADistanceFieldPathRenderer.h ('k') | src/gpu/GrAAHairLinePathRenderer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1
2 /*
3 * Copyright 2014 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9 #include "GrAADistanceFieldPathRenderer.h"
10
11 #include "GrBatchFlushState.h"
12 #include "GrBatchTest.h"
13 #include "GrContext.h"
14 #include "GrPipelineBuilder.h"
15 #include "GrResourceProvider.h"
16 #include "GrSurfacePriv.h"
17 #include "GrSWMaskHelper.h"
18 #include "GrTexturePriv.h"
19 #include "GrVertexBuffer.h"
20 #include "batches/GrVertexBatch.h"
21 #include "effects/GrDistanceFieldGeoProc.h"
22
23 #include "SkDistanceFieldGen.h"
24 #include "SkRTConf.h"
25
26 #define ATLAS_TEXTURE_WIDTH 1024
27 #define ATLAS_TEXTURE_HEIGHT 2048
28 #define PLOT_WIDTH 256
29 #define PLOT_HEIGHT 256
30
31 #define NUM_PLOTS_X (ATLAS_TEXTURE_WIDTH / PLOT_WIDTH)
32 #define NUM_PLOTS_Y (ATLAS_TEXTURE_HEIGHT / PLOT_HEIGHT)
33
34 #ifdef DF_PATH_TRACKING
35 static int g_NumCachedPaths = 0;
36 static int g_NumFreedPaths = 0;
37 #endif
38
39 // mip levels
40 static const int kSmallMIP = 32;
41 static const int kMediumMIP = 78;
42 static const int kLargeMIP = 192;
43
44 // Callback to clear out internal path cache when eviction occurs
45 void GrAADistanceFieldPathRenderer::HandleEviction(GrBatchAtlas::AtlasID id, voi d* pr) {
46 GrAADistanceFieldPathRenderer* dfpr = (GrAADistanceFieldPathRenderer*)pr;
47 // remove any paths that use this plot
48 PathDataList::Iter iter;
49 iter.init(dfpr->fPathList, PathDataList::Iter::kHead_IterStart);
50 PathData* pathData;
51 while ((pathData = iter.get())) {
52 iter.next();
53 if (id == pathData->fID) {
54 dfpr->fPathCache.remove(pathData->fKey);
55 dfpr->fPathList.remove(pathData);
56 delete pathData;
57 #ifdef DF_PATH_TRACKING
58 ++g_NumFreedPaths;
59 #endif
60 }
61 }
62 }
63
64 ////////////////////////////////////////////////////////////////////////////////
65 GrAADistanceFieldPathRenderer::GrAADistanceFieldPathRenderer() : fAtlas(nullptr) {}
66
67 GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() {
68 PathDataList::Iter iter;
69 iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
70 PathData* pathData;
71 while ((pathData = iter.get())) {
72 iter.next();
73 fPathList.remove(pathData);
74 delete pathData;
75 }
76 delete fAtlas;
77
78 #ifdef DF_PATH_TRACKING
79 SkDebugf("Cached paths: %d, freed paths: %d\n", g_NumCachedPaths, g_NumFreed Paths);
80 #endif
81 }
82
83 ////////////////////////////////////////////////////////////////////////////////
84 bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c onst {
85
86 // TODO: Support inverse fill
87 // TODO: Support strokes
88 if (!args.fShaderCaps->shaderDerivativeSupport() || !args.fAntiAlias ||
89 args.fPath->isInverseFillType() || args.fPath->isVolatile() ||
90 !args.fStroke->isFillStyle()) {
91 return false;
92 }
93
94 // currently don't support perspective
95 if (args.fViewMatrix->hasPerspective()) {
96 return false;
97 }
98
99 // only support paths smaller than 64x64, scaled to less than 256x256
100 // the goal is to accelerate rendering of lots of small paths that may be sc aling
101 SkScalar maxScale = args.fViewMatrix->getMaxScale();
102 const SkRect& bounds = args.fPath->getBounds();
103 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
104 return maxDim < 64.f && maxDim * maxScale < 256.f;
105 }
106
107 ////////////////////////////////////////////////////////////////////////////////
108
109 // padding around path bounds to allow for antialiased pixels
110 static const SkScalar kAntiAliasPad = 1.0f;
111
112 class AADistanceFieldPathBatch : public GrVertexBatch {
113 public:
114 typedef GrAADistanceFieldPathRenderer::PathData PathData;
115 typedef SkTDynamicHash<PathData, PathData::Key> PathCache;
116 typedef GrAADistanceFieldPathRenderer::PathDataList PathDataList;
117
118 struct Geometry {
119 Geometry(const SkStrokeRec& stroke) : fStroke(stroke) {}
120 SkPath fPath;
121 SkStrokeRec fStroke;
122 bool fAntiAlias;
123 PathData* fPathData;
124 };
125
126 static GrDrawBatch* Create(const Geometry& geometry, GrColor color, const Sk Matrix& viewMatrix,
127 GrBatchAtlas* atlas, PathCache* pathCache, PathDa taList* pathList) {
128 return new AADistanceFieldPathBatch(geometry, color, viewMatrix, atlas, pathCache,
129 pathList);
130 }
131
132 const char* name() const override { return "AADistanceFieldPathBatch"; }
133
134 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
135 out->setKnownFourComponents(fBatch.fColor);
136 }
137
138 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
139 out->setUnknownSingleComponent();
140 }
141
142 private:
143 void initBatchTracker(const GrPipelineOptimizations& opt) override {
144 // Handle any color overrides
145 if (!opt.readsColor()) {
146 fBatch.fColor = GrColor_ILLEGAL;
147 }
148 opt.getOverrideColorIfSet(&fBatch.fColor);
149
150 // setup batch properties
151 fBatch.fColorIgnored = !opt.readsColor();
152 fBatch.fUsesLocalCoords = opt.readsLocalCoords();
153 fBatch.fCoverageIgnored = !opt.readsCoverage();
154 }
155
156 struct FlushInfo {
157 SkAutoTUnref<const GrVertexBuffer> fVertexBuffer;
158 SkAutoTUnref<const GrIndexBuffer> fIndexBuffer;
159 int fVertexOffset;
160 int fInstancesToFlush;
161 };
162
163 void onPrepareDraws(Target* target) override {
164 int instanceCount = fGeoData.count();
165
166 SkMatrix invert;
167 if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) {
168 SkDebugf("Could not invert viewmatrix\n");
169 return;
170 }
171
172 uint32_t flags = 0;
173 flags |= this->viewMatrix().isSimilarity() ? kSimilarity_DistanceFieldEf fectFlag : 0;
174
175 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBil erp_FilterMode);
176
177 // Setup GrGeometryProcessor
178 GrBatchAtlas* atlas = fAtlas;
179 SkAutoTUnref<GrGeometryProcessor> dfProcessor(
180 GrDistanceFieldPathGeoProc::Create(this->color(),
181 this->viewMatrix(),
182 atlas->getTexture(),
183 params,
184 flags,
185 this->usesLocalCoords()));
186
187 target->initDraw(dfProcessor, this->pipeline());
188
189 FlushInfo flushInfo;
190
191 // allocate vertices
192 size_t vertexStride = dfProcessor->getVertexStride();
193 SkASSERT(vertexStride == 2 * sizeof(SkPoint));
194
195 const GrVertexBuffer* vertexBuffer;
196 void* vertices = target->makeVertexSpace(vertexStride,
197 kVerticesPerQuad * instanceCoun t,
198 &vertexBuffer,
199 &flushInfo.fVertexOffset);
200 flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer));
201 flushInfo.fIndexBuffer.reset(target->resourceProvider()->refQuadIndexBuf fer());
202 if (!vertices || !flushInfo.fIndexBuffer) {
203 SkDebugf("Could not allocate vertices\n");
204 return;
205 }
206
207 flushInfo.fInstancesToFlush = 0;
208 for (int i = 0; i < instanceCount; i++) {
209 Geometry& args = fGeoData[i];
210
211 // get mip level
212 SkScalar maxScale = this->viewMatrix().getMaxScale();
213 const SkRect& bounds = args.fPath.getBounds();
214 SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height());
215 SkScalar size = maxScale * maxDim;
216 uint32_t desiredDimension;
217 if (size <= kSmallMIP) {
218 desiredDimension = kSmallMIP;
219 } else if (size <= kMediumMIP) {
220 desiredDimension = kMediumMIP;
221 } else {
222 desiredDimension = kLargeMIP;
223 }
224
225 // check to see if path is cached
226 // TODO: handle stroked vs. filled version of same path
227 PathData::Key key = { args.fPath.getGenerationID(), desiredDimension };
228 args.fPathData = fPathCache->find(key);
229 if (nullptr == args.fPathData || !atlas->hasID(args.fPathData->fID)) {
230 // Remove the stale cache entry
231 if (args.fPathData) {
232 fPathCache->remove(args.fPathData->fKey);
233 fPathList->remove(args.fPathData);
234 delete args.fPathData;
235 }
236 SkScalar scale = desiredDimension/maxDim;
237 args.fPathData = new PathData;
238 if (!this->addPathToAtlas(target,
239 dfProcessor,
240 this->pipeline(),
241 &flushInfo,
242 atlas,
243 args.fPathData,
244 args.fPath,
245 args.fStroke,
246 args.fAntiAlias,
247 desiredDimension,
248 scale)) {
249 SkDebugf("Can't rasterize path\n");
250 return;
251 }
252 }
253
254 atlas->setLastUseToken(args.fPathData->fID, target->currentToken());
255
256 // Now set vertices
257 intptr_t offset = reinterpret_cast<intptr_t>(vertices);
258 offset += i * kVerticesPerQuad * vertexStride;
259 SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
260 this->writePathVertices(target,
261 atlas,
262 this->pipeline(),
263 dfProcessor,
264 positions,
265 vertexStride,
266 this->viewMatrix(),
267 args.fPath,
268 args.fPathData);
269 flushInfo.fInstancesToFlush++;
270 }
271
272 this->flush(target, &flushInfo);
273 }
274
275 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
276
277 AADistanceFieldPathBatch(const Geometry& geometry, GrColor color, const SkMa trix& viewMatrix,
278 GrBatchAtlas* atlas,
279 PathCache* pathCache, PathDataList* pathList) {
280 this->initClassID<AADistanceFieldPathBatch>();
281 fBatch.fColor = color;
282 fBatch.fViewMatrix = viewMatrix;
283 fGeoData.push_back(geometry);
284 fGeoData.back().fPathData = nullptr;
285
286 fAtlas = atlas;
287 fPathCache = pathCache;
288 fPathList = pathList;
289
290 // Compute bounds
291 fBounds = geometry.fPath.getBounds();
292 viewMatrix.mapRect(&fBounds);
293 }
294
295 bool addPathToAtlas(GrVertexBatch::Target* target,
296 const GrGeometryProcessor* dfProcessor,
297 const GrPipeline* pipeline,
298 FlushInfo* flushInfo,
299 GrBatchAtlas* atlas,
300 PathData* pathData,
301 const SkPath& path,
302 const SkStrokeRec&
303 stroke, bool antiAlias,
304 uint32_t dimension,
305 SkScalar scale) {
306 const SkRect& bounds = path.getBounds();
307
308 // generate bounding rect for bitmap draw
309 SkRect scaledBounds = bounds;
310 // scale to mip level size
311 scaledBounds.fLeft *= scale;
312 scaledBounds.fTop *= scale;
313 scaledBounds.fRight *= scale;
314 scaledBounds.fBottom *= scale;
315 // move the origin to an integer boundary (gives better results)
316 SkScalar dx = SkScalarFraction(scaledBounds.fLeft);
317 SkScalar dy = SkScalarFraction(scaledBounds.fTop);
318 scaledBounds.offset(-dx, -dy);
319 // get integer boundary
320 SkIRect devPathBounds;
321 scaledBounds.roundOut(&devPathBounds);
322 // pad to allow room for antialiasing
323 devPathBounds.outset(SkScalarCeilToInt(kAntiAliasPad), SkScalarCeilToInt (kAntiAliasPad));
324 // move origin to upper left corner
325 devPathBounds.offsetTo(0,0);
326
327 // draw path to bitmap
328 SkMatrix drawMatrix;
329 drawMatrix.setTranslate(-bounds.left(), -bounds.top());
330 drawMatrix.postScale(scale, scale);
331 drawMatrix.postTranslate(kAntiAliasPad, kAntiAliasPad);
332
333 // setup bitmap backing
334 // Now translate so the bound's UL corner is at the origin
335 drawMatrix.postTranslate(-devPathBounds.fLeft * SK_Scalar1,
336 -devPathBounds.fTop * SK_Scalar1);
337 SkIRect pathBounds = SkIRect::MakeWH(devPathBounds.width(),
338 devPathBounds.height());
339
340 SkAutoPixmapStorage dst;
341 if (!dst.tryAlloc(SkImageInfo::MakeA8(pathBounds.width(),
342 pathBounds.height()))) {
343 return false;
344 }
345 sk_bzero(dst.writable_addr(), dst.getSafeSize());
346
347 // rasterize path
348 SkPaint paint;
349 if (stroke.isHairlineStyle()) {
350 paint.setStyle(SkPaint::kStroke_Style);
351 paint.setStrokeWidth(SK_Scalar1);
352 } else {
353 if (stroke.isFillStyle()) {
354 paint.setStyle(SkPaint::kFill_Style);
355 } else {
356 paint.setStyle(SkPaint::kStroke_Style);
357 paint.setStrokeJoin(stroke.getJoin());
358 paint.setStrokeCap(stroke.getCap());
359 paint.setStrokeWidth(stroke.getWidth());
360 }
361 }
362 paint.setAntiAlias(antiAlias);
363
364 SkDraw draw;
365 sk_bzero(&draw, sizeof(draw));
366
367 SkRasterClip rasterClip;
368 rasterClip.setRect(pathBounds);
369 draw.fRC = &rasterClip;
370 draw.fClip = &rasterClip.bwRgn();
371 draw.fMatrix = &drawMatrix;
372 draw.fDst = dst;
373
374 draw.drawPathCoverage(path, paint);
375
376 // generate signed distance field
377 devPathBounds.outset(SK_DistanceFieldPad, SK_DistanceFieldPad);
378 int width = devPathBounds.width();
379 int height = devPathBounds.height();
380 // TODO We should really generate this directly into the plot somehow
381 SkAutoSMalloc<1024> dfStorage(width * height * sizeof(unsigned char));
382
383 // Generate signed distance field
384 SkGenerateDistanceFieldFromA8Image((unsigned char*)dfStorage.get(),
385 (const unsigned char*)dst.addr(),
386 dst.width(), dst.height(), dst.rowByt es());
387
388 // add to atlas
389 SkIPoint16 atlasLocation;
390 GrBatchAtlas::AtlasID id;
391 bool success = atlas->addToAtlas(&id, target, width, height, dfStorage.g et(),
392 &atlasLocation);
393 if (!success) {
394 this->flush(target, flushInfo);
395 target->initDraw(dfProcessor, pipeline);
396
397 SkDEBUGCODE(success =) atlas->addToAtlas(&id, target, width, height,
398 dfStorage.get(), &atlasLoca tion);
399 SkASSERT(success);
400
401 }
402
403 // add to cache
404 pathData->fKey.fGenID = path.getGenerationID();
405 pathData->fKey.fDimension = dimension;
406 pathData->fScale = scale;
407 pathData->fID = id;
408 // change the scaled rect to match the size of the inset distance field
409 scaledBounds.fRight = scaledBounds.fLeft +
410 SkIntToScalar(devPathBounds.width() - 2*SK_DistanceFieldInset);
411 scaledBounds.fBottom = scaledBounds.fTop +
412 SkIntToScalar(devPathBounds.height() - 2*SK_DistanceFieldInset);
413 // shift the origin to the correct place relative to the distance field
414 // need to also restore the fractional translation
415 scaledBounds.offset(-SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPa d + dx,
416 -SkIntToScalar(SK_DistanceFieldInset) - kAntiAliasPa d + dy);
417 pathData->fBounds = scaledBounds;
418 // origin we render from is inset from distance field edge
419 atlasLocation.fX += SK_DistanceFieldInset;
420 atlasLocation.fY += SK_DistanceFieldInset;
421 pathData->fAtlasLocation = atlasLocation;
422
423 fPathCache->add(pathData);
424 fPathList->addToTail(pathData);
425 #ifdef DF_PATH_TRACKING
426 ++g_NumCachedPaths;
427 #endif
428 return true;
429 }
430
431 void writePathVertices(GrDrawBatch::Target* target,
432 GrBatchAtlas* atlas,
433 const GrPipeline* pipeline,
434 const GrGeometryProcessor* gp,
435 SkPoint* positions,
436 size_t vertexStride,
437 const SkMatrix& viewMatrix,
438 const SkPath& path,
439 const PathData* pathData) {
440 GrTexture* texture = atlas->getTexture();
441
442 SkScalar dx = pathData->fBounds.fLeft;
443 SkScalar dy = pathData->fBounds.fTop;
444 SkScalar width = pathData->fBounds.width();
445 SkScalar height = pathData->fBounds.height();
446
447 SkScalar invScale = 1.0f / pathData->fScale;
448 dx *= invScale;
449 dy *= invScale;
450 width *= invScale;
451 height *= invScale;
452
453 SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX);
454 SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY);
455 SkFixed tw = SkScalarToFixed(pathData->fBounds.width());
456 SkFixed th = SkScalarToFixed(pathData->fBounds.height());
457
458 // vertex positions
459 // TODO make the vertex attributes a struct
460 SkRect r = SkRect::MakeXYWH(dx, dy, width, height);
461 positions->setRectFan(r.left(), r.top(), r.right(), r.bottom(), vertexSt ride);
462
463 // vertex texture coords
464 SkPoint* textureCoords = positions + 1;
465 textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normaliz eFixedX(tx)),
466 SkFixedToFloat(texture->texturePriv().normaliz eFixedY(ty)),
467 SkFixedToFloat(texture->texturePriv().normaliz eFixedX(tx + tw)),
468 SkFixedToFloat(texture->texturePriv().normaliz eFixedY(ty + th)),
469 vertexStride);
470 }
471
472 void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) {
473 GrVertices vertices;
474 int maxInstancesPerDraw = flushInfo->fIndexBuffer->maxQuads();
475 vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuf fer,
476 flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerQuad,
477 kIndicesPerQuad, flushInfo->fInstancesToFlush, maxInstancesPerDraw);
478 target->draw(vertices);
479 flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFl ush;
480 flushInfo->fInstancesToFlush = 0;
481 }
482
483 GrColor color() const { return fBatch.fColor; }
484 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
485 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
486
487 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
488 AADistanceFieldPathBatch* that = t->cast<AADistanceFieldPathBatch>();
489 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
490 that->bounds(), caps)) {
491 return false;
492 }
493
494 // TODO we could actually probably do a bunch of this work on the CPU, i e map viewMatrix,
495 // maybe upload color via attribute
496 if (this->color() != that->color()) {
497 return false;
498 }
499
500 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
501 return false;
502 }
503
504 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ;
505 this->joinBounds(that->bounds());
506 return true;
507 }
508
509 struct BatchTracker {
510 GrColor fColor;
511 SkMatrix fViewMatrix;
512 bool fUsesLocalCoords;
513 bool fColorIgnored;
514 bool fCoverageIgnored;
515 };
516
517 BatchTracker fBatch;
518 SkSTArray<1, Geometry, true> fGeoData;
519 GrBatchAtlas* fAtlas;
520 PathCache* fPathCache;
521 PathDataList* fPathList;
522 };
523
524 bool GrAADistanceFieldPathRenderer::onDrawPath(const DrawPathArgs& args) {
525 // we've already bailed on inverse filled paths, so this is safe
526 if (args.fPath->isEmpty()) {
527 return true;
528 }
529
530 if (!fAtlas) {
531 fAtlas = args.fResourceProvider->createAtlas(kAlpha_8_GrPixelConfig,
532 ATLAS_TEXTURE_WIDTH, ATLAS_ TEXTURE_HEIGHT,
533 NUM_PLOTS_X, NUM_PLOTS_Y,
534 &GrAADistanceFieldPathRende rer::HandleEviction,
535 (void*)this);
536 if (!fAtlas) {
537 return false;
538 }
539 }
540
541 AADistanceFieldPathBatch::Geometry geometry(*args.fStroke);
542 geometry.fPath = *args.fPath;
543 geometry.fAntiAlias = args.fAntiAlias;
544
545 SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry, a rgs.fColor,
546 *args.fView Matrix, fAtlas,
547 &fPathCache , &fPathList));
548 args.fTarget->drawBatch(*args.fPipelineBuilder, batch);
549
550 return true;
551 }
552
553 //////////////////////////////////////////////////////////////////////////////// ///////////////////
554
555 #ifdef GR_TEST_UTILS
556
557 struct PathTestStruct {
558 typedef GrAADistanceFieldPathRenderer::PathCache PathCache;
559 typedef GrAADistanceFieldPathRenderer::PathData PathData;
560 typedef GrAADistanceFieldPathRenderer::PathDataList PathDataList;
561 PathTestStruct() : fContextID(SK_InvalidGenID), fAtlas(nullptr) {}
562 ~PathTestStruct() { this->reset(); }
563
564 void reset() {
565 PathDataList::Iter iter;
566 iter.init(fPathList, PathDataList::Iter::kHead_IterStart);
567 PathData* pathData;
568 while ((pathData = iter.get())) {
569 iter.next();
570 fPathList.remove(pathData);
571 delete pathData;
572 }
573 delete fAtlas;
574 fPathCache.reset();
575 }
576
577 static void HandleEviction(GrBatchAtlas::AtlasID id, void* pr) {
578 PathTestStruct* dfpr = (PathTestStruct*)pr;
579 // remove any paths that use this plot
580 PathDataList::Iter iter;
581 iter.init(dfpr->fPathList, PathDataList::Iter::kHead_IterStart);
582 PathData* pathData;
583 while ((pathData = iter.get())) {
584 iter.next();
585 if (id == pathData->fID) {
586 dfpr->fPathCache.remove(pathData->fKey);
587 dfpr->fPathList.remove(pathData);
588 delete pathData;
589 }
590 }
591 }
592
593 uint32_t fContextID;
594 GrBatchAtlas* fAtlas;
595 PathCache fPathCache;
596 PathDataList fPathList;
597 };
598
599 DRAW_BATCH_TEST_DEFINE(AADistanceFieldPathBatch) {
600 static PathTestStruct gTestStruct;
601
602 if (context->uniqueID() != gTestStruct.fContextID) {
603 gTestStruct.fContextID = context->uniqueID();
604 gTestStruct.reset();
605 gTestStruct.fAtlas =
606 context->resourceProvider()->createAtlas(kAlpha_8_GrPixelConfig,
607 ATLAS_TEXTURE_WIDTH, ATLAS_ TEXTURE_HEIGHT,
608 NUM_PLOTS_X, NUM_PLOTS_Y,
609 &PathTestStruct::HandleEvic tion,
610 (void*)&gTestStruct);
611 }
612
613 SkMatrix viewMatrix = GrTest::TestMatrix(random);
614 GrColor color = GrRandomColor(random);
615
616 AADistanceFieldPathBatch::Geometry geometry(GrTest::TestStrokeRec(random));
617 geometry.fPath = GrTest::TestPath(random);
618 geometry.fAntiAlias = random->nextBool();
619
620 return AADistanceFieldPathBatch::Create(geometry, color, viewMatrix,
621 gTestStruct.fAtlas,
622 &gTestStruct.fPathCache,
623 &gTestStruct.fPathList);
624 }
625
626 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrAADistanceFieldPathRenderer.h ('k') | src/gpu/GrAAHairLinePathRenderer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698