OLD | NEW |
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 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 if (fStroke.getWidth() < 0) { | 135 if (fStroke.getWidth() < 0) { |
136 fStroke.setStrokeStyle(-1.0f); | 136 fStroke.setStrokeStyle(-1.0f); |
137 } | 137 } |
138 } | 138 } |
139 } | 139 } |
140 SkPath fPath; | 140 SkPath fPath; |
141 // The unique ID of the path involved in this draw. This may be differen
t than the ID | 141 // The unique ID of the path involved in this draw. This may be differen
t than the ID |
142 // in fPath since that path may have resulted from a SkStrokeRec::applyT
oPath call. | 142 // in fPath since that path may have resulted from a SkStrokeRec::applyT
oPath call. |
143 uint32_t fGenID; | 143 uint32_t fGenID; |
144 SkStrokeRec fStroke; | 144 SkStrokeRec fStroke; |
| 145 GrColor fColor; |
145 bool fAntiAlias; | 146 bool fAntiAlias; |
146 }; | 147 }; |
147 | 148 |
148 static GrDrawBatch* Create(const Geometry& geometry, GrColor color, const Sk
Matrix& viewMatrix, | 149 static GrDrawBatch* Create(const Geometry& geometry, const SkMatrix& viewMat
rix, |
149 GrBatchAtlas* atlas, PathCache* pathCache, PathDa
taList* pathList) { | 150 GrBatchAtlas* atlas, PathCache* pathCache, PathDa
taList* pathList) { |
150 return new AADistanceFieldPathBatch(geometry, color, viewMatrix, atlas,
pathCache, | 151 return new AADistanceFieldPathBatch(geometry, viewMatrix, atlas, pathCac
he, pathList); |
151 pathList); | |
152 } | 152 } |
153 | 153 |
154 const char* name() const override { return "AADistanceFieldPathBatch"; } | 154 const char* name() const override { return "AADistanceFieldPathBatch"; } |
155 | 155 |
156 void computePipelineOptimizations(GrInitInvariantOutput* color, | 156 void computePipelineOptimizations(GrInitInvariantOutput* color, |
157 GrInitInvariantOutput* coverage, | 157 GrInitInvariantOutput* coverage, |
158 GrBatchToXPOverrides* overrides) const ove
rride { | 158 GrBatchToXPOverrides* overrides) const ove
rride { |
159 color->setKnownFourComponents(fBatch.fColor); | 159 color->setKnownFourComponents(fGeoData[0].fColor); |
160 coverage->setUnknownSingleComponent(); | 160 coverage->setUnknownSingleComponent(); |
161 overrides->fUsePLSDstRead = false; | 161 overrides->fUsePLSDstRead = false; |
162 } | 162 } |
163 | 163 |
164 private: | 164 private: |
165 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | 165 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
166 // Handle any color overrides | 166 // Handle any color overrides |
167 if (!overrides.readsColor()) { | 167 if (!overrides.readsColor()) { |
168 fBatch.fColor = GrColor_ILLEGAL; | 168 fGeoData[0].fColor = GrColor_ILLEGAL; |
169 } | 169 } |
170 overrides.getOverrideColorIfSet(&fBatch.fColor); | 170 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); |
171 | 171 |
172 // setup batch properties | 172 // setup batch properties |
173 fBatch.fColorIgnored = !overrides.readsColor(); | 173 fBatch.fColorIgnored = !overrides.readsColor(); |
174 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); | 174 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); |
175 fBatch.fCoverageIgnored = !overrides.readsCoverage(); | 175 fBatch.fCoverageIgnored = !overrides.readsCoverage(); |
176 } | 176 } |
177 | 177 |
178 struct FlushInfo { | 178 struct FlushInfo { |
179 SkAutoTUnref<const GrVertexBuffer> fVertexBuffer; | 179 SkAutoTUnref<const GrVertexBuffer> fVertexBuffer; |
180 SkAutoTUnref<const GrIndexBuffer> fIndexBuffer; | 180 SkAutoTUnref<const GrIndexBuffer> fIndexBuffer; |
(...skipping 24 matching lines...) Expand all Loading... |
205 params, | 205 params, |
206 flags, | 206 flags, |
207 this->usesLocalCoords())); | 207 this->usesLocalCoords())); |
208 | 208 |
209 target->initDraw(dfProcessor, this->pipeline()); | 209 target->initDraw(dfProcessor, this->pipeline()); |
210 | 210 |
211 FlushInfo flushInfo; | 211 FlushInfo flushInfo; |
212 | 212 |
213 // allocate vertices | 213 // allocate vertices |
214 size_t vertexStride = dfProcessor->getVertexStride(); | 214 size_t vertexStride = dfProcessor->getVertexStride(); |
215 SkASSERT(vertexStride == 2 * sizeof(SkPoint)); | 215 SkASSERT(vertexStride == 2 * sizeof(SkPoint) + sizeof(GrColor)); |
216 | 216 |
217 const GrVertexBuffer* vertexBuffer; | 217 const GrVertexBuffer* vertexBuffer; |
218 void* vertices = target->makeVertexSpace(vertexStride, | 218 void* vertices = target->makeVertexSpace(vertexStride, |
219 kVerticesPerQuad * instanceCoun
t, | 219 kVerticesPerQuad * instanceCoun
t, |
220 &vertexBuffer, | 220 &vertexBuffer, |
221 &flushInfo.fVertexOffset); | 221 &flushInfo.fVertexOffset); |
222 flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer)); | 222 flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer)); |
223 flushInfo.fIndexBuffer.reset(target->resourceProvider()->refQuadIndexBuf
fer()); | 223 flushInfo.fIndexBuffer.reset(target->resourceProvider()->refQuadIndexBuf
fer()); |
224 if (!vertices || !flushInfo.fIndexBuffer) { | 224 if (!vertices || !flushInfo.fIndexBuffer) { |
225 SkDebugf("Could not allocate vertices\n"); | 225 SkDebugf("Could not allocate vertices\n"); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 SkDebugf("Can't rasterize path\n"); | 271 SkDebugf("Can't rasterize path\n"); |
272 return; | 272 return; |
273 } | 273 } |
274 } | 274 } |
275 | 275 |
276 atlas->setLastUseToken(pathData->fID, target->currentToken()); | 276 atlas->setLastUseToken(pathData->fID, target->currentToken()); |
277 | 277 |
278 // Now set vertices | 278 // Now set vertices |
279 intptr_t offset = reinterpret_cast<intptr_t>(vertices); | 279 intptr_t offset = reinterpret_cast<intptr_t>(vertices); |
280 offset += i * kVerticesPerQuad * vertexStride; | 280 offset += i * kVerticesPerQuad * vertexStride; |
281 SkPoint* positions = reinterpret_cast<SkPoint*>(offset); | |
282 this->writePathVertices(target, | 281 this->writePathVertices(target, |
283 atlas, | 282 atlas, |
284 this->pipeline(), | 283 this->pipeline(), |
285 dfProcessor, | 284 dfProcessor, |
286 positions, | 285 offset, |
| 286 args.fColor, |
287 vertexStride, | 287 vertexStride, |
288 this->viewMatrix(), | 288 this->viewMatrix(), |
289 args.fPath, | 289 args.fPath, |
290 pathData); | 290 pathData); |
291 flushInfo.fInstancesToFlush++; | 291 flushInfo.fInstancesToFlush++; |
292 } | 292 } |
293 | 293 |
294 this->flush(target, &flushInfo); | 294 this->flush(target, &flushInfo); |
295 } | 295 } |
296 | 296 |
297 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | 297 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
298 | 298 |
299 AADistanceFieldPathBatch(const Geometry& geometry, GrColor color, const SkMa
trix& viewMatrix, | 299 AADistanceFieldPathBatch(const Geometry& geometry, |
| 300 const SkMatrix& viewMatrix, |
300 GrBatchAtlas* atlas, | 301 GrBatchAtlas* atlas, |
301 PathCache* pathCache, PathDataList* pathList) | 302 PathCache* pathCache, PathDataList* pathList) |
302 : INHERITED(ClassID()) { | 303 : INHERITED(ClassID()) { |
303 fBatch.fColor = color; | |
304 fBatch.fViewMatrix = viewMatrix; | 304 fBatch.fViewMatrix = viewMatrix; |
305 fGeoData.push_back(geometry); | 305 fGeoData.push_back(geometry); |
306 | 306 |
307 fAtlas = atlas; | 307 fAtlas = atlas; |
308 fPathCache = pathCache; | 308 fPathCache = pathCache; |
309 fPathList = pathList; | 309 fPathList = pathList; |
310 | 310 |
311 // Compute bounds | 311 // Compute bounds |
312 fBounds = geometry.fPath.getBounds(); | 312 fBounds = geometry.fPath.getBounds(); |
313 viewMatrix.mapRect(&fBounds); | 313 viewMatrix.mapRect(&fBounds); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 #ifdef DF_PATH_TRACKING | 430 #ifdef DF_PATH_TRACKING |
431 ++g_NumCachedPaths; | 431 ++g_NumCachedPaths; |
432 #endif | 432 #endif |
433 return true; | 433 return true; |
434 } | 434 } |
435 | 435 |
436 void writePathVertices(GrDrawBatch::Target* target, | 436 void writePathVertices(GrDrawBatch::Target* target, |
437 GrBatchAtlas* atlas, | 437 GrBatchAtlas* atlas, |
438 const GrPipeline* pipeline, | 438 const GrPipeline* pipeline, |
439 const GrGeometryProcessor* gp, | 439 const GrGeometryProcessor* gp, |
440 SkPoint* positions, | 440 intptr_t offset, |
| 441 GrColor color, |
441 size_t vertexStride, | 442 size_t vertexStride, |
442 const SkMatrix& viewMatrix, | 443 const SkMatrix& viewMatrix, |
443 const SkPath& path, | 444 const SkPath& path, |
444 const PathData* pathData) const { | 445 const PathData* pathData) const { |
445 GrTexture* texture = atlas->getTexture(); | 446 GrTexture* texture = atlas->getTexture(); |
446 | 447 |
447 SkScalar dx = pathData->fBounds.fLeft; | 448 SkScalar dx = pathData->fBounds.fLeft; |
448 SkScalar dy = pathData->fBounds.fTop; | 449 SkScalar dy = pathData->fBounds.fTop; |
449 SkScalar width = pathData->fBounds.width(); | 450 SkScalar width = pathData->fBounds.width(); |
450 SkScalar height = pathData->fBounds.height(); | 451 SkScalar height = pathData->fBounds.height(); |
451 | 452 |
452 SkScalar invScale = 1.0f / pathData->fScale; | 453 SkScalar invScale = 1.0f / pathData->fScale; |
453 dx *= invScale; | 454 dx *= invScale; |
454 dy *= invScale; | 455 dy *= invScale; |
455 width *= invScale; | 456 width *= invScale; |
456 height *= invScale; | 457 height *= invScale; |
457 | 458 |
458 SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX); | 459 SkFixed tx = SkIntToFixed(pathData->fAtlasLocation.fX); |
459 SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY); | 460 SkFixed ty = SkIntToFixed(pathData->fAtlasLocation.fY); |
460 SkFixed tw = SkScalarToFixed(pathData->fBounds.width()); | 461 SkFixed tw = SkScalarToFixed(pathData->fBounds.width()); |
461 SkFixed th = SkScalarToFixed(pathData->fBounds.height()); | 462 SkFixed th = SkScalarToFixed(pathData->fBounds.height()); |
462 | 463 |
| 464 SkPoint* positions = reinterpret_cast<SkPoint*>(offset); |
| 465 |
463 // vertex positions | 466 // vertex positions |
464 // TODO make the vertex attributes a struct | 467 // TODO make the vertex attributes a struct |
465 SkRect r = SkRect::MakeXYWH(dx, dy, width, height); | 468 SkRect r = SkRect::MakeXYWH(dx, dy, width, height); |
466 positions->setRectFan(r.left(), r.top(), r.right(), r.bottom(), vertexSt
ride); | 469 positions->setRectFan(r.left(), r.top(), r.right(), r.bottom(), vertexSt
ride); |
467 | 470 |
| 471 // colors |
| 472 for (int i = 0; i < kVerticesPerQuad; i++) { |
| 473 GrColor* colorPtr = (GrColor*)(offset + sizeof(SkPoint) + i * vertex
Stride); |
| 474 *colorPtr = color; |
| 475 } |
| 476 |
468 // vertex texture coords | 477 // vertex texture coords |
469 SkPoint* textureCoords = positions + 1; | 478 SkPoint* textureCoords = (SkPoint*)(offset + sizeof(SkPoint) + sizeof(Gr
Color)); |
470 textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normaliz
eFixedX(tx)), | 479 textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normaliz
eFixedX(tx)), |
471 SkFixedToFloat(texture->texturePriv().normaliz
eFixedY(ty)), | 480 SkFixedToFloat(texture->texturePriv().normaliz
eFixedY(ty)), |
472 SkFixedToFloat(texture->texturePriv().normaliz
eFixedX(tx + tw)), | 481 SkFixedToFloat(texture->texturePriv().normaliz
eFixedX(tx + tw)), |
473 SkFixedToFloat(texture->texturePriv().normaliz
eFixedY(ty + th)), | 482 SkFixedToFloat(texture->texturePriv().normaliz
eFixedY(ty + th)), |
474 vertexStride); | 483 vertexStride); |
475 } | 484 } |
476 | 485 |
477 void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const { | 486 void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) const { |
478 GrVertices vertices; | 487 GrVertices vertices; |
479 int maxInstancesPerDraw = flushInfo->fIndexBuffer->maxQuads(); | 488 int maxInstancesPerDraw = flushInfo->fIndexBuffer->maxQuads(); |
480 vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuf
fer, | 489 vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuf
fer, |
481 flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerQuad, | 490 flushInfo->fIndexBuffer, flushInfo->fVertexOffset, kVerticesPerQuad, |
482 kIndicesPerQuad, flushInfo->fInstancesToFlush, maxInstancesPerDraw); | 491 kIndicesPerQuad, flushInfo->fInstancesToFlush, maxInstancesPerDraw); |
483 target->draw(vertices); | 492 target->draw(vertices); |
484 flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFl
ush; | 493 flushInfo->fVertexOffset += kVerticesPerQuad * flushInfo->fInstancesToFl
ush; |
485 flushInfo->fInstancesToFlush = 0; | 494 flushInfo->fInstancesToFlush = 0; |
486 } | 495 } |
487 | 496 |
488 GrColor color() const { return fBatch.fColor; } | 497 GrColor color() const { return fGeoData[0].fColor; } |
489 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } | 498 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } |
490 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | 499 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
491 | 500 |
492 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 501 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
493 AADistanceFieldPathBatch* that = t->cast<AADistanceFieldPathBatch>(); | 502 AADistanceFieldPathBatch* that = t->cast<AADistanceFieldPathBatch>(); |
494 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | 503 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), |
495 that->bounds(), caps)) { | 504 that->bounds(), caps)) { |
496 return false; | 505 return false; |
497 } | 506 } |
498 | 507 |
499 // TODO we could actually probably do a bunch of this work on the CPU, i
e map viewMatrix, | 508 // TODO We can position on the cpu |
500 // maybe upload color via attribute | |
501 if (this->color() != that->color()) { | |
502 return false; | |
503 } | |
504 | |
505 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { | 509 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { |
506 return false; | 510 return false; |
507 } | 511 } |
508 | 512 |
509 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | 513 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; |
510 this->joinBounds(that->bounds()); | 514 this->joinBounds(that->bounds()); |
511 return true; | 515 return true; |
512 } | 516 } |
513 | 517 |
514 struct BatchTracker { | 518 struct BatchTracker { |
515 GrColor fColor; | |
516 SkMatrix fViewMatrix; | 519 SkMatrix fViewMatrix; |
517 bool fUsesLocalCoords; | 520 bool fUsesLocalCoords; |
518 bool fColorIgnored; | 521 bool fColorIgnored; |
519 bool fCoverageIgnored; | 522 bool fCoverageIgnored; |
520 }; | 523 }; |
521 | 524 |
522 BatchTracker fBatch; | 525 BatchTracker fBatch; |
523 SkSTArray<1, Geometry, true> fGeoData; | 526 SkSTArray<1, Geometry, true> fGeoData; |
524 GrBatchAtlas* fAtlas; | 527 GrBatchAtlas* fAtlas; |
525 PathCache* fPathCache; | 528 PathCache* fPathCache; |
(...skipping 18 matching lines...) Expand all Loading... |
544 return false; | 547 return false; |
545 } | 548 } |
546 } | 549 } |
547 | 550 |
548 AADistanceFieldPathBatch::Geometry geometry(*args.fStroke); | 551 AADistanceFieldPathBatch::Geometry geometry(*args.fStroke); |
549 if (SkStrokeRec::kFill_Style == args.fStroke->getStyle()) { | 552 if (SkStrokeRec::kFill_Style == args.fStroke->getStyle()) { |
550 geometry.fPath = *args.fPath; | 553 geometry.fPath = *args.fPath; |
551 } else { | 554 } else { |
552 args.fStroke->applyToPath(&geometry.fPath, *args.fPath); | 555 args.fStroke->applyToPath(&geometry.fPath, *args.fPath); |
553 } | 556 } |
| 557 geometry.fColor = args.fColor; |
554 geometry.fAntiAlias = args.fAntiAlias; | 558 geometry.fAntiAlias = args.fAntiAlias; |
555 // Note: this is the generation ID of the _original_ path. When a new path i
s | 559 // Note: this is the generation ID of the _original_ path. When a new path i
s |
556 // generated due to stroking it is important that the original path's id is
used | 560 // generated due to stroking it is important that the original path's id is
used |
557 // for caching. | 561 // for caching. |
558 geometry.fGenID = args.fPath->getGenerationID(); | 562 geometry.fGenID = args.fPath->getGenerationID(); |
559 | 563 |
560 SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry, a
rgs.fColor, | 564 SkAutoTUnref<GrDrawBatch> batch(AADistanceFieldPathBatch::Create(geometry, |
561 *args.fView
Matrix, fAtlas, | 565 *args.fView
Matrix, fAtlas, |
562 &fPathCache
, &fPathList)); | 566 &fPathCache
, &fPathList)); |
563 args.fTarget->drawBatch(*args.fPipelineBuilder, batch); | 567 args.fTarget->drawBatch(*args.fPipelineBuilder, batch); |
564 | 568 |
565 return true; | 569 return true; |
566 } | 570 } |
567 | 571 |
568 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 572 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
569 | 573 |
570 #ifdef GR_TEST_UTILS | 574 #ifdef GR_TEST_UTILS |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
622 ATLAS_TEXTURE_WIDTH, ATLAS_
TEXTURE_HEIGHT, | 626 ATLAS_TEXTURE_WIDTH, ATLAS_
TEXTURE_HEIGHT, |
623 NUM_PLOTS_X, NUM_PLOTS_Y, | 627 NUM_PLOTS_X, NUM_PLOTS_Y, |
624 &PathTestStruct::HandleEvic
tion, | 628 &PathTestStruct::HandleEvic
tion, |
625 (void*)&gTestStruct); | 629 (void*)&gTestStruct); |
626 } | 630 } |
627 | 631 |
628 SkMatrix viewMatrix = GrTest::TestMatrix(random); | 632 SkMatrix viewMatrix = GrTest::TestMatrix(random); |
629 GrColor color = GrRandomColor(random); | 633 GrColor color = GrRandomColor(random); |
630 | 634 |
631 AADistanceFieldPathBatch::Geometry geometry(GrTest::TestStrokeRec(random)); | 635 AADistanceFieldPathBatch::Geometry geometry(GrTest::TestStrokeRec(random)); |
| 636 geometry.fColor = color; |
632 geometry.fPath = GrTest::TestPath(random); | 637 geometry.fPath = GrTest::TestPath(random); |
633 geometry.fAntiAlias = random->nextBool(); | 638 geometry.fAntiAlias = random->nextBool(); |
634 geometry.fGenID = random->nextU(); | 639 geometry.fGenID = random->nextU(); |
635 | 640 |
636 return AADistanceFieldPathBatch::Create(geometry, color, viewMatrix, | 641 return AADistanceFieldPathBatch::Create(geometry, viewMatrix, |
637 gTestStruct.fAtlas, | 642 gTestStruct.fAtlas, |
638 &gTestStruct.fPathCache, | 643 &gTestStruct.fPathCache, |
639 &gTestStruct.fPathList); | 644 &gTestStruct.fPathList); |
640 } | 645 } |
641 | 646 |
642 #endif | 647 #endif |
OLD | NEW |