OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "GrAAStrokeRectBatch.h" | 8 #include "GrAAStrokeRectBatch.h" |
9 | 9 |
10 #include "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 public: | 47 public: |
48 DEFINE_BATCH_CLASS_ID | 48 DEFINE_BATCH_CLASS_ID |
49 | 49 |
50 // TODO support AA rotated stroke rects by copying around view matrices | 50 // TODO support AA rotated stroke rects by copying around view matrices |
51 struct Geometry { | 51 struct Geometry { |
52 SkRect fDevOutside; | 52 SkRect fDevOutside; |
53 SkRect fDevOutsideAssist; | 53 SkRect fDevOutsideAssist; |
54 SkRect fDevInside; | 54 SkRect fDevInside; |
55 GrColor fColor; | 55 GrColor fColor; |
56 bool fMiterStroke; | 56 bool fMiterStroke; |
57 bool fDegenerate; | |
57 }; | 58 }; |
58 | 59 |
59 static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& devOutside, | 60 static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const SkRect& devOutside, |
60 const SkRect& devOutsideAssist, const SkRect& dev Inside, | 61 const SkRect& devOutsideAssist, const SkRect& dev Inside, |
61 bool miterStroke) { | 62 bool miterStroke, bool degenerate) { |
62 return new AAStrokeRectBatch(color, viewMatrix, devOutside, devOutsideAs sist, devInside, | 63 return new AAStrokeRectBatch(color, viewMatrix, devOutside, devOutsideAs sist, devInside, |
63 miterStroke); | 64 miterStroke, degenerate); |
64 } | 65 } |
65 | 66 |
66 const char* name() const override { return "AAStrokeRect"; } | 67 const char* name() const override { return "AAStrokeRect"; } |
67 | 68 |
68 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | 69 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
69 // When this is called on a batch, there is only one geometry bundle | 70 // When this is called on a batch, there is only one geometry bundle |
70 out->setKnownFourComponents(fGeoData[0].fColor); | 71 out->setKnownFourComponents(fGeoData[0].fColor); |
71 } | 72 } |
72 | 73 |
73 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { | 74 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
74 out->setUnknownSingleComponent(); | 75 out->setUnknownSingleComponent(); |
75 } | 76 } |
76 | 77 |
77 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | 78 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
78 | 79 |
79 private: | 80 private: |
80 void onPrepareDraws(Target*) override; | 81 void onPrepareDraws(Target*) override; |
81 void initBatchTracker(const GrPipelineOptimizations&) override; | 82 void initBatchTracker(const GrPipelineOptimizations&) override; |
82 | 83 |
83 AAStrokeRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& d evOutside, | 84 AAStrokeRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& d evOutside, |
84 const SkRect& devOutsideAssist, const SkRect& devInside, b ool miterStroke) | 85 const SkRect& devOutsideAssist, const SkRect& devInside, b ool miterStroke, |
86 bool degenerate) | |
85 : INHERITED(ClassID()) { | 87 : INHERITED(ClassID()) { |
86 fBatch.fViewMatrix = viewMatrix; | 88 fBatch.fViewMatrix = viewMatrix; |
87 Geometry& geometry = fGeoData.push_back(); | 89 Geometry& geometry = fGeoData.push_back(); |
88 geometry.fColor = color; | 90 geometry.fColor = color; |
89 geometry.fDevOutside = devOutside; | 91 geometry.fDevOutside = devOutside; |
90 geometry.fDevOutsideAssist = devOutsideAssist; | 92 geometry.fDevOutsideAssist = devOutsideAssist; |
91 geometry.fDevInside = devInside; | 93 geometry.fDevInside = devInside; |
92 geometry.fMiterStroke = miterStroke; | 94 geometry.fMiterStroke = miterStroke; |
95 geometry.fDegenerate = degenerate; | |
93 | 96 |
94 // If we have miterstroke then we inset devOutside and outset devOutside Assist, so we need | 97 // If we have miterstroke then we inset devOutside and outset devOutside Assist, so we need |
95 // the join for proper bounds | 98 // the join for proper bounds |
96 fBounds = geometry.fDevOutside; | 99 fBounds = geometry.fDevOutside; |
97 fBounds.join(geometry.fDevOutsideAssist); | 100 fBounds.join(geometry.fDevOutsideAssist); |
98 } | 101 } |
99 | 102 |
100 | 103 |
101 static const int kMiterIndexCnt = 3 * 24; | 104 static const int kMiterIndexCnt = 3 * 24; |
102 static const int kMiterVertexCnt = 16; | 105 static const int kMiterVertexCnt = 16; |
(...skipping 19 matching lines...) Expand all Loading... | |
122 void generateAAStrokeRectGeometry(void* vertices, | 125 void generateAAStrokeRectGeometry(void* vertices, |
123 size_t offset, | 126 size_t offset, |
124 size_t vertexStride, | 127 size_t vertexStride, |
125 int outerVertexNum, | 128 int outerVertexNum, |
126 int innerVertexNum, | 129 int innerVertexNum, |
127 GrColor color, | 130 GrColor color, |
128 const SkRect& devOutside, | 131 const SkRect& devOutside, |
129 const SkRect& devOutsideAssist, | 132 const SkRect& devOutsideAssist, |
130 const SkRect& devInside, | 133 const SkRect& devInside, |
131 bool miterStroke, | 134 bool miterStroke, |
135 bool degenerate, | |
132 bool tweakAlphaForCoverage) const; | 136 bool tweakAlphaForCoverage) const; |
133 | 137 |
134 struct BatchTracker { | 138 struct BatchTracker { |
135 SkMatrix fViewMatrix; | 139 SkMatrix fViewMatrix; |
136 GrColor fColor; | 140 GrColor fColor; |
137 bool fUsesLocalCoords; | 141 bool fUsesLocalCoords; |
138 bool fColorIgnored; | 142 bool fColorIgnored; |
139 bool fCoverageIgnored; | 143 bool fCoverageIgnored; |
140 bool fMiterStroke; | 144 bool fMiterStroke; |
141 bool fCanTweakAlphaForCoverage; | 145 bool fCanTweakAlphaForCoverage; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 this->generateAAStrokeRectGeometry(vertices, | 208 this->generateAAStrokeRectGeometry(vertices, |
205 i * verticesPerInstance * vertexStrid e, | 209 i * verticesPerInstance * vertexStrid e, |
206 vertexStride, | 210 vertexStride, |
207 outerVertexNum, | 211 outerVertexNum, |
208 innerVertexNum, | 212 innerVertexNum, |
209 args.fColor, | 213 args.fColor, |
210 args.fDevOutside, | 214 args.fDevOutside, |
211 args.fDevOutsideAssist, | 215 args.fDevOutsideAssist, |
212 args.fDevInside, | 216 args.fDevInside, |
213 args.fMiterStroke, | 217 args.fMiterStroke, |
218 args.fDegenerate, | |
214 canTweakAlphaForCoverage); | 219 canTweakAlphaForCoverage); |
215 } | 220 } |
216 helper.recordDraw(target); | 221 helper.recordDraw(target); |
217 } | 222 } |
218 | 223 |
219 const GrIndexBuffer* AAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* resou rceProvider, | 224 const GrIndexBuffer* AAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* resou rceProvider, |
220 bool miterStroke) { | 225 bool miterStroke) { |
221 | 226 |
222 if (miterStroke) { | 227 if (miterStroke) { |
223 static const uint16_t gMiterIndices[] = { | 228 static const uint16_t gMiterIndices[] = { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
344 void AAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices, | 349 void AAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices, |
345 size_t offset, | 350 size_t offset, |
346 size_t vertexStride, | 351 size_t vertexStride, |
347 int outerVertexNum, | 352 int outerVertexNum, |
348 int innerVertexNum, | 353 int innerVertexNum, |
349 GrColor color, | 354 GrColor color, |
350 const SkRect& devOutside, | 355 const SkRect& devOutside, |
351 const SkRect& devOutsideAss ist, | 356 const SkRect& devOutsideAss ist, |
352 const SkRect& devInside, | 357 const SkRect& devInside, |
353 bool miterStroke, | 358 bool miterStroke, |
359 bool degenerate, | |
354 bool tweakAlphaForCoverage) const { | 360 bool tweakAlphaForCoverage) const { |
355 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; | 361 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; |
356 | 362 |
357 // We create vertices for four nested rectangles. There are two ramps from 0 to full | 363 // We create vertices for four nested rectangles. There are two ramps from 0 to full |
358 // coverage, one on the exterior of the stroke and the other on the interior . | 364 // coverage, one on the exterior of the stroke and the other on the interior . |
359 // The following pointers refer to the four rects, from outermost to innermo st. | 365 // The following pointers refer to the four rects, from outermost to innermo st. |
360 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); | 366 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); |
361 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * verte xStride); | 367 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * verte xStride); |
362 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * v ertexStride); | 368 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * v ertexStride); |
363 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + | 369 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + |
(...skipping 15 matching lines...) Expand all Loading... | |
379 SkASSERT(inset >= 0); | 385 SkASSERT(inset >= 0); |
380 #else | 386 #else |
381 SkScalar inset = SK_ScalarHalf; | 387 SkScalar inset = SK_ScalarHalf; |
382 #endif | 388 #endif |
383 | 389 |
384 if (miterStroke) { | 390 if (miterStroke) { |
385 // outermost | 391 // outermost |
386 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK_Sca larHalf); | 392 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK_Sca larHalf); |
387 // inner two | 393 // inner two |
388 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset); | 394 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset); |
389 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset); | 395 if (!degenerate) { |
390 // innermost | 396 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset); |
391 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK_Sca larHalf); | 397 // innermost |
398 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf); | |
399 } else { | |
robertphillips
2015/09/21 17:12:44
// When the interior rect has become degenerate ..
joshualitt
2015/09/21 19:51:25
Acknowledged.
| |
400 fan2Pos->setRectFan(devInside.fLeft, devInside.fTop, | |
401 devInside.fRight, devInside.fBottom, vertexStrid e); | |
402 fan3Pos->setRectFan(devInside.fLeft, devInside.fTop, | |
403 devInside.fRight, devInside.fBottom, vertexStrid e); | |
404 } | |
392 } else { | 405 } else { |
393 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vertexSt ride); | 406 SkPoint* fan0AssistPos = reinterpret_cast<SkPoint*>(verts + 4 * vertexSt ride); |
394 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + | 407 SkPoint* fan1AssistPos = reinterpret_cast<SkPoint*>(verts + |
395 (outerVertexNum + 4) * | 408 (outerVertexNum + 4) * |
396 vertexStride); | 409 vertexStride); |
397 // outermost | 410 // outermost |
398 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK_Sca larHalf); | 411 set_inset_fan(fan0Pos, vertexStride, devOutside, -SK_ScalarHalf, -SK_Sca larHalf); |
399 set_inset_fan(fan0AssistPos, vertexStride, devOutsideAssist, -SK_ScalarH alf, | 412 set_inset_fan(fan0AssistPos, vertexStride, devOutsideAssist, -SK_ScalarH alf, |
400 -SK_ScalarHalf); | 413 -SK_ScalarHalf); |
401 // outer one of the inner two | 414 // outer one of the inner two |
402 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset); | 415 set_inset_fan(fan1Pos, vertexStride, devOutside, inset, inset); |
403 set_inset_fan(fan1AssistPos, vertexStride, devOutsideAssist, inset, in set); | 416 set_inset_fan(fan1AssistPos, vertexStride, devOutsideAssist, inset, in set); |
404 // inner one of the inner two | 417 if (!degenerate) { |
405 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset); | 418 // inner one of the inner two |
406 // innermost | 419 set_inset_fan(fan2Pos, vertexStride, devInside, -inset, -inset); |
407 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK_Sca larHalf); | 420 // innermost |
421 set_inset_fan(fan3Pos, vertexStride, devInside, SK_ScalarHalf, SK _ScalarHalf); | |
422 } else { | |
robertphillips
2015/09/21 17:12:44
// When the interior rect has become degenerate ..
joshualitt
2015/09/21 19:51:25
Acknowledged.
| |
423 fan2Pos->setRectFan(devInside.fLeft, devInside.fTop, | |
424 devInside.fRight, devInside.fBottom, vertexStrid e); | |
425 fan3Pos->setRectFan(devInside.fLeft, devInside.fTop, | |
426 devInside.fRight, devInside.fBottom, vertexStrid e); | |
427 } | |
408 } | 428 } |
409 | 429 |
410 // Make verts point to vertex color and then set all the color and coverage vertex attrs | 430 // Make verts point to vertex color and then set all the color and coverage vertex attrs |
411 // values. The outermost rect has 0 coverage | 431 // values. The outermost rect has 0 coverage |
412 verts += sizeof(SkPoint); | 432 verts += sizeof(SkPoint); |
413 for (int i = 0; i < outerVertexNum; ++i) { | 433 for (int i = 0; i < outerVertexNum; ++i) { |
414 if (tweakAlphaForCoverage) { | 434 if (tweakAlphaForCoverage) { |
415 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; | 435 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; |
416 } else { | 436 } else { |
417 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 437 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; |
418 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) = 0; | 438 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) = 0; |
419 } | 439 } |
420 } | 440 } |
421 | 441 |
422 // scale is the coverage for the the inner two rects. | 442 // scale is the coverage for the the inner two rects. |
423 int scale; | 443 int scale; |
robertphillips
2015/09/21 17:12:44
This hardens the inner/outer fan too
joshualitt
2015/09/21 19:51:25
Acknowledged.
| |
424 if (inset < SK_ScalarHalf) { | 444 if (inset < SK_ScalarHalf && !degenerate) { |
425 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); | 445 scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf)); |
426 SkASSERT(scale >= 0 && scale <= 255); | 446 SkASSERT(scale >= 0 && scale <= 255); |
427 } else { | 447 } else { |
428 scale = 0xff; | 448 scale = 0xff; |
429 } | 449 } |
430 | 450 |
431 float innerCoverage = GrNormalizeByteToFloat(scale); | 451 float innerCoverage = GrNormalizeByteToFloat(scale); |
432 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); | 452 GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale); |
433 | 453 |
434 verts += outerVertexNum * vertexStride; | 454 verts += outerVertexNum * vertexStride; |
435 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) { | 455 for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) { |
436 if (tweakAlphaForCoverage) { | 456 if (tweakAlphaForCoverage) { |
437 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; | 457 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; |
438 } else { | 458 } else { |
439 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 459 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; |
440 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) = | 460 *reinterpret_cast<float*>(verts + i * vertexStride + sizeof(GrColor) ) = |
441 innerCoverage; | 461 innerCoverage; |
442 } | 462 } |
443 } | 463 } |
444 | 464 |
445 // The innermost rect has 0 coverage | 465 // The innermost rect has 0 coverage, unless we are degenerate |
446 verts += (outerVertexNum + innerVertexNum) * vertexStride; | 466 verts += (outerVertexNum + innerVertexNum) * vertexStride; |
467 scale = 0; | |
468 if (degenerate) { | |
469 scale = 0xff; | |
470 } | |
447 for (int i = 0; i < innerVertexNum; ++i) { | 471 for (int i = 0; i < innerVertexNum; ++i) { |
448 if (tweakAlphaForCoverage) { | 472 if (tweakAlphaForCoverage) { |
449 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; | 473 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scale; |
450 } else { | 474 } else { |
451 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 475 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; |
452 *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(GrColo r)) = 0; | 476 *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(GrColo r)) = scale; |
453 } | 477 } |
454 } | 478 } |
455 } | 479 } |
456 | 480 |
457 namespace GrAAStrokeRectBatch { | 481 namespace GrAAStrokeRectBatch { |
458 | 482 |
459 GrDrawBatch* Create(GrColor color, | 483 GrDrawBatch* Create(GrColor color, |
460 const SkMatrix& viewMatrix, | 484 const SkMatrix& viewMatrix, |
461 const SkRect& devOutside, | 485 const SkRect& devOutside, |
462 const SkRect& devOutsideAssist, | 486 const SkRect& devOutsideAssist, |
463 const SkRect& devInside, | 487 const SkRect& devInside, |
464 bool miterStroke) { | 488 bool miterStroke, |
489 bool degenerate) { | |
465 return AAStrokeRectBatch::Create(color, viewMatrix, devOutside, devOutsideAs sist, devInside, | 490 return AAStrokeRectBatch::Create(color, viewMatrix, devOutside, devOutsideAs sist, devInside, |
466 miterStroke); | 491 miterStroke, degenerate); |
467 } | 492 } |
468 | 493 |
469 }; | 494 }; |
470 | 495 |
471 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 496 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
472 | 497 |
473 #ifdef GR_TEST_UTILS | 498 #ifdef GR_TEST_UTILS |
474 | 499 |
475 #include "GrBatchTest.h" | 500 #include "GrBatchTest.h" |
476 | 501 |
477 DRAW_BATCH_TEST_DEFINE(AAStrokeRectBatch) { | 502 DRAW_BATCH_TEST_DEFINE(AAStrokeRectBatch) { |
478 bool miterStroke = random->nextBool(); | 503 bool miterStroke = random->nextBool(); |
504 bool degenerate = random->nextBool(); | |
479 | 505 |
480 // Create mock stroke rect | 506 // Create mock stroke rect |
481 SkRect outside = GrTest::TestRect(random); | 507 SkRect outside = GrTest::TestRect(random); |
482 SkScalar minDim = SkMinScalar(outside.width(), outside.height()); | 508 SkScalar minDim = SkMinScalar(outside.width(), outside.height()); |
483 SkScalar strokeWidth = minDim * 0.1f; | 509 SkScalar strokeWidth = minDim * 0.1f; |
484 SkRect outsideAssist = outside; | 510 SkRect outsideAssist = outside; |
485 outsideAssist.outset(strokeWidth, strokeWidth); | 511 outsideAssist.outset(strokeWidth, strokeWidth); |
486 SkRect inside = outside; | 512 SkRect inside = outside; |
487 inside.inset(strokeWidth, strokeWidth); | 513 inside.inset(strokeWidth, strokeWidth); |
488 | 514 |
489 GrColor color = GrRandomColor(random); | 515 GrColor color = GrRandomColor(random); |
490 | 516 |
491 return GrAAStrokeRectBatch::Create(color, GrTest::TestMatrix(random), outsid e, outsideAssist, | 517 return GrAAStrokeRectBatch::Create(color, GrTest::TestMatrix(random), outsid e, outsideAssist, |
492 inside, miterStroke); | 518 inside, degenerate, miterStroke); |
493 } | 519 } |
494 | 520 |
495 #endif | 521 #endif |
OLD | NEW |