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 25 matching lines...) Expand all Loading... |
36 coverageType = Coverage::kSolid_Type; | 36 coverageType = Coverage::kSolid_Type; |
37 } else { | 37 } else { |
38 coverageType = Coverage::kAttribute_Type; | 38 coverageType = Coverage::kAttribute_Type; |
39 } | 39 } |
40 Coverage coverage(coverageType); | 40 Coverage coverage(coverageType); |
41 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type : | 41 LocalCoords localCoords(usesLocalCoords ? LocalCoords::kUsePosition_Type : |
42 LocalCoords::kUnused_Type); | 42 LocalCoords::kUnused_Type); |
43 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix); | 43 return CreateForDeviceSpace(color, coverage, localCoords, viewMatrix); |
44 } | 44 } |
45 | 45 |
46 void GrAAStrokeRectBatch::initBatchTracker(const GrPipelineOptimizations& opt) { | 46 class AAStrokeRectBatch : public GrVertexBatch { |
| 47 public: |
| 48 DEFINE_BATCH_CLASS_ID |
| 49 |
| 50 // TODO support AA rotated stroke rects by copying around view matrices |
| 51 struct Geometry { |
| 52 SkRect fDevOutside; |
| 53 SkRect fDevOutsideAssist; |
| 54 SkRect fDevInside; |
| 55 GrColor fColor; |
| 56 bool fMiterStroke; |
| 57 }; |
| 58 |
| 59 static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const
SkRect& devOutside, |
| 60 const SkRect& devOutsideAssist, const SkRect& dev
Inside, |
| 61 bool miterStroke) { |
| 62 return new AAStrokeRectBatch(color, viewMatrix, devOutside, devOutsideAs
sist, devInside, |
| 63 miterStroke); |
| 64 } |
| 65 |
| 66 const char* name() const override { return "AAStrokeRect"; } |
| 67 |
| 68 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
| 69 // When this is called on a batch, there is only one geometry bundle |
| 70 out->setKnownFourComponents(fGeoData[0].fColor); |
| 71 } |
| 72 |
| 73 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
| 74 out->setUnknownSingleComponent(); |
| 75 } |
| 76 |
| 77 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
| 78 |
| 79 private: |
| 80 void onPrepareDraws(Target*) override; |
| 81 void initBatchTracker(const GrPipelineOptimizations&) override; |
| 82 |
| 83 AAStrokeRectBatch(GrColor color, const SkMatrix& viewMatrix, const SkRect& d
evOutside, |
| 84 const SkRect& devOutsideAssist, const SkRect& devInside, b
ool miterStroke) |
| 85 : INHERITED(ClassID()) { |
| 86 fBatch.fViewMatrix = viewMatrix; |
| 87 Geometry& geometry = fGeoData.push_back(); |
| 88 geometry.fColor = color; |
| 89 geometry.fDevOutside = devOutside; |
| 90 geometry.fDevOutsideAssist = devOutsideAssist; |
| 91 geometry.fDevInside = devInside; |
| 92 geometry.fMiterStroke = miterStroke; |
| 93 |
| 94 // If we have miterstroke then we inset devOutside and outset devOutside
Assist, so we need |
| 95 // the join for proper bounds |
| 96 fBounds = geometry.fDevOutside; |
| 97 fBounds.join(geometry.fDevOutsideAssist); |
| 98 } |
| 99 |
| 100 |
| 101 static const int kMiterIndexCnt = 3 * 24; |
| 102 static const int kMiterVertexCnt = 16; |
| 103 static const int kNumMiterRectsInIndexBuffer = 256; |
| 104 |
| 105 static const int kBevelIndexCnt = 48 + 36 + 24; |
| 106 static const int kBevelVertexCnt = 24; |
| 107 static const int kNumBevelRectsInIndexBuffer = 256; |
| 108 |
| 109 static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* resourceProvi
der, |
| 110 bool miterStroke); |
| 111 |
| 112 GrColor color() const { return fBatch.fColor; } |
| 113 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
| 114 bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCover
age; } |
| 115 bool colorIgnored() const { return fBatch.fColorIgnored; } |
| 116 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } |
| 117 bool miterStroke() const { return fBatch.fMiterStroke; } |
| 118 bool coverageIgnored() const { return fBatch.fCoverageIgnored; } |
| 119 |
| 120 bool onCombineIfPossible(GrBatch* t, const GrCaps&) override; |
| 121 |
| 122 void generateAAStrokeRectGeometry(void* vertices, |
| 123 size_t offset, |
| 124 size_t vertexStride, |
| 125 int outerVertexNum, |
| 126 int innerVertexNum, |
| 127 GrColor color, |
| 128 const SkRect& devOutside, |
| 129 const SkRect& devOutsideAssist, |
| 130 const SkRect& devInside, |
| 131 bool miterStroke, |
| 132 bool tweakAlphaForCoverage) const; |
| 133 |
| 134 struct BatchTracker { |
| 135 SkMatrix fViewMatrix; |
| 136 GrColor fColor; |
| 137 bool fUsesLocalCoords; |
| 138 bool fColorIgnored; |
| 139 bool fCoverageIgnored; |
| 140 bool fMiterStroke; |
| 141 bool fCanTweakAlphaForCoverage; |
| 142 }; |
| 143 |
| 144 BatchTracker fBatch; |
| 145 SkSTArray<1, Geometry, true> fGeoData; |
| 146 |
| 147 typedef GrVertexBatch INHERITED; |
| 148 }; |
| 149 |
| 150 void AAStrokeRectBatch::initBatchTracker(const GrPipelineOptimizations& opt) { |
47 // Handle any color overrides | 151 // Handle any color overrides |
48 if (!opt.readsColor()) { | 152 if (!opt.readsColor()) { |
49 fGeoData[0].fColor = GrColor_ILLEGAL; | 153 fGeoData[0].fColor = GrColor_ILLEGAL; |
50 } | 154 } |
51 opt.getOverrideColorIfSet(&fGeoData[0].fColor); | 155 opt.getOverrideColorIfSet(&fGeoData[0].fColor); |
52 | 156 |
53 // setup batch properties | 157 // setup batch properties |
54 fBatch.fColorIgnored = !opt.readsColor(); | 158 fBatch.fColorIgnored = !opt.readsColor(); |
55 fBatch.fColor = fGeoData[0].fColor; | 159 fBatch.fColor = fGeoData[0].fColor; |
56 fBatch.fUsesLocalCoords = opt.readsLocalCoords(); | 160 fBatch.fUsesLocalCoords = opt.readsLocalCoords(); |
57 fBatch.fCoverageIgnored = !opt.readsCoverage(); | 161 fBatch.fCoverageIgnored = !opt.readsCoverage(); |
58 fBatch.fMiterStroke = fGeoData[0].fMiterStroke; | 162 fBatch.fMiterStroke = fGeoData[0].fMiterStroke; |
59 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage(); | 163 fBatch.fCanTweakAlphaForCoverage = opt.canTweakAlphaForCoverage(); |
60 } | 164 } |
61 | 165 |
62 void GrAAStrokeRectBatch::onPrepareDraws(Target* target) { | 166 void AAStrokeRectBatch::onPrepareDraws(Target* target) { |
63 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); | 167 bool canTweakAlphaForCoverage = this->canTweakAlphaForCoverage(); |
64 | 168 |
65 SkAutoTUnref<const GrGeometryProcessor> gp(create_stroke_rect_gp(canTweakAlp
haForCoverage, | 169 SkAutoTUnref<const GrGeometryProcessor> gp(create_stroke_rect_gp(canTweakAlp
haForCoverage, |
66 this->viewM
atrix(), | 170 this->viewM
atrix(), |
67 this->usesL
ocalCoords(), | 171 this->usesL
ocalCoords(), |
68 this->cover
ageIgnored())); | 172 this->cover
ageIgnored())); |
69 if (!gp) { | 173 if (!gp) { |
70 SkDebugf("Couldn't create GrGeometryProcessor\n"); | 174 SkDebugf("Couldn't create GrGeometryProcessor\n"); |
71 return; | 175 return; |
72 } | 176 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 args.fColor, | 209 args.fColor, |
106 args.fDevOutside, | 210 args.fDevOutside, |
107 args.fDevOutsideAssist, | 211 args.fDevOutsideAssist, |
108 args.fDevInside, | 212 args.fDevInside, |
109 args.fMiterStroke, | 213 args.fMiterStroke, |
110 canTweakAlphaForCoverage); | 214 canTweakAlphaForCoverage); |
111 } | 215 } |
112 helper.recordDraw(target); | 216 helper.recordDraw(target); |
113 } | 217 } |
114 | 218 |
115 const GrIndexBuffer* GrAAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* res
ourceProvider, | 219 const GrIndexBuffer* AAStrokeRectBatch::GetIndexBuffer(GrResourceProvider* resou
rceProvider, |
116 bool miterStroke) { | 220 bool miterStroke) { |
117 | 221 |
118 if (miterStroke) { | 222 if (miterStroke) { |
119 static const uint16_t gMiterIndices[] = { | 223 static const uint16_t gMiterIndices[] = { |
120 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0, | 224 0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0, |
121 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0, | 225 1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0, |
122 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0, | 226 2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0, |
123 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0, | 227 3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0, |
124 | 228 |
125 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4, | 229 0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4, |
126 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4, | 230 1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 }; | 300 }; |
197 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gBevelIndices) == kBevelIndexCnt); | 301 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gBevelIndices) == kBevelIndexCnt); |
198 | 302 |
199 GR_DEFINE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey); | 303 GR_DEFINE_STATIC_UNIQUE_KEY(gBevelIndexBufferKey); |
200 return resourceProvider->findOrCreateInstancedIndexBuffer(gBevelIndices, | 304 return resourceProvider->findOrCreateInstancedIndexBuffer(gBevelIndices, |
201 kBevelIndexCnt, kNumBevelRectsInIndexBuffer, kBevelVertexCnt, | 305 kBevelIndexCnt, kNumBevelRectsInIndexBuffer, kBevelVertexCnt, |
202 gBevelIndexBufferKey); | 306 gBevelIndexBufferKey); |
203 } | 307 } |
204 } | 308 } |
205 | 309 |
206 bool GrAAStrokeRectBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) { | 310 bool AAStrokeRectBatch::onCombineIfPossible(GrBatch* t, const GrCaps& caps) { |
207 GrAAStrokeRectBatch* that = t->cast<GrAAStrokeRectBatch>(); | 311 AAStrokeRectBatch* that = t->cast<AAStrokeRectBatch>(); |
208 | 312 |
209 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeli
ne(), | 313 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeli
ne(), |
210 that->bounds(), caps)) { | 314 that->bounds(), caps)) { |
211 return false; | 315 return false; |
212 } | 316 } |
213 | 317 |
214 // TODO batch across miterstroke changes | 318 // TODO batch across miterstroke changes |
215 if (this->miterStroke() != that->miterStroke()) { | 319 if (this->miterStroke() != that->miterStroke()) { |
216 return false; | 320 return false; |
217 } | 321 } |
(...skipping 12 matching lines...) Expand all Loading... |
230 } | 334 } |
231 | 335 |
232 if (this->color() != that->color()) { | 336 if (this->color() != that->color()) { |
233 fBatch.fColor = GrColor_ILLEGAL; | 337 fBatch.fColor = GrColor_ILLEGAL; |
234 } | 338 } |
235 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); | 339 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); |
236 this->joinBounds(that->bounds()); | 340 this->joinBounds(that->bounds()); |
237 return true; | 341 return true; |
238 } | 342 } |
239 | 343 |
240 void GrAAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices, | 344 void AAStrokeRectBatch::generateAAStrokeRectGeometry(void* vertices, |
241 size_t offset, | 345 size_t offset, |
242 size_t vertexStride, | 346 size_t vertexStride, |
243 int outerVertexNum, | 347 int outerVertexNum, |
244 int innerVertexNum, | 348 int innerVertexNum, |
245 GrColor color, | 349 GrColor color, |
246 const SkRect& devOutside, | 350 const SkRect& devOutside, |
247 const SkRect& devOutsideA
ssist, | 351 const SkRect& devOutsideAss
ist, |
248 const SkRect& devInside, | 352 const SkRect& devInside, |
249 bool miterStroke, | 353 bool miterStroke, |
250 bool tweakAlphaForCoverag
e) const { | 354 bool tweakAlphaForCoverage)
const { |
251 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; | 355 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + offset; |
252 | 356 |
253 // We create vertices for four nested rectangles. There are two ramps from 0
to full | 357 // We create vertices for four nested rectangles. There are two ramps from 0
to full |
254 // coverage, one on the exterior of the stroke and the other on the interior
. | 358 // coverage, one on the exterior of the stroke and the other on the interior
. |
255 // The following pointers refer to the four rects, from outermost to innermo
st. | 359 // The following pointers refer to the four rects, from outermost to innermo
st. |
256 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); | 360 SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts); |
257 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * verte
xStride); | 361 SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + outerVertexNum * verte
xStride); |
258 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * v
ertexStride); | 362 SkPoint* fan2Pos = reinterpret_cast<SkPoint*>(verts + 2 * outerVertexNum * v
ertexStride); |
259 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + | 363 SkPoint* fan3Pos = reinterpret_cast<SkPoint*>(verts + |
260 (2 * outerVertexNum + innerVer
texNum) * | 364 (2 * outerVertexNum + innerVer
texNum) * |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 for (int i = 0; i < innerVertexNum; ++i) { | 447 for (int i = 0; i < innerVertexNum; ++i) { |
344 if (tweakAlphaForCoverage) { | 448 if (tweakAlphaForCoverage) { |
345 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; | 449 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = 0; |
346 } else { | 450 } else { |
347 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 451 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; |
348 *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(GrColo
r)) = 0; | 452 *reinterpret_cast<GrColor*>(verts + i * vertexStride + sizeof(GrColo
r)) = 0; |
349 } | 453 } |
350 } | 454 } |
351 } | 455 } |
352 | 456 |
| 457 namespace GrAAStrokeRectBatch { |
| 458 |
| 459 GrDrawBatch* Create(GrColor color, |
| 460 const SkMatrix& viewMatrix, |
| 461 const SkRect& devOutside, |
| 462 const SkRect& devOutsideAssist, |
| 463 const SkRect& devInside, |
| 464 bool miterStroke) { |
| 465 return AAStrokeRectBatch::Create(color, viewMatrix, devOutside, devOutsideAs
sist, devInside, |
| 466 miterStroke); |
| 467 } |
| 468 |
| 469 }; |
| 470 |
353 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 471 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
354 | 472 |
355 #ifdef GR_TEST_UTILS | 473 #ifdef GR_TEST_UTILS |
356 | 474 |
357 #include "GrBatchTest.h" | 475 #include "GrBatchTest.h" |
358 | 476 |
359 DRAW_BATCH_TEST_DEFINE(AAStrokeRectBatch) { | 477 DRAW_BATCH_TEST_DEFINE(AAStrokeRectBatch) { |
360 bool miterStroke = random->nextBool(); | 478 bool miterStroke = random->nextBool(); |
361 | 479 |
362 // Create mock stroke rect | 480 // Create mock stroke rect |
363 SkRect outside = GrTest::TestRect(random); | 481 SkRect outside = GrTest::TestRect(random); |
364 SkScalar minDim = SkMinScalar(outside.width(), outside.height()); | 482 SkScalar minDim = SkMinScalar(outside.width(), outside.height()); |
365 SkScalar strokeWidth = minDim * 0.1f; | 483 SkScalar strokeWidth = minDim * 0.1f; |
366 SkRect outsideAssist = outside; | 484 SkRect outsideAssist = outside; |
367 outsideAssist.outset(strokeWidth, strokeWidth); | 485 outsideAssist.outset(strokeWidth, strokeWidth); |
368 SkRect inside = outside; | 486 SkRect inside = outside; |
369 inside.inset(strokeWidth, strokeWidth); | 487 inside.inset(strokeWidth, strokeWidth); |
370 | 488 |
371 GrAAStrokeRectBatch::Geometry geo; | 489 GrColor color = GrRandomColor(random); |
372 geo.fColor = GrRandomColor(random); | |
373 geo.fDevOutside = outside; | |
374 geo.fDevOutsideAssist = outsideAssist; | |
375 geo.fDevInside = inside; | |
376 geo.fMiterStroke = miterStroke; | |
377 | 490 |
378 return GrAAStrokeRectBatch::Create(geo, GrTest::TestMatrix(random)); | 491 return GrAAStrokeRectBatch::Create(color, GrTest::TestMatrix(random), outsid
e, outsideAssist, |
| 492 inside, miterStroke); |
379 } | 493 } |
380 | 494 |
381 #endif | 495 #endif |
OLD | NEW |