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

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

Issue 1359453002: Fix for degenerate stroke rect (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: handle degenerate stroke rects 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
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698