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 "GrAAFillRectBatch.h" | 8 #include "GrAAFillRectBatch.h" |
9 | 9 |
10 #include "GrBatchFlushState.h" | |
11 #include "GrColor.h" | 10 #include "GrColor.h" |
12 #include "GrDefaultGeoProcFactory.h" | 11 #include "GrDefaultGeoProcFactory.h" |
13 #include "GrResourceKey.h" | 12 #include "GrResourceKey.h" |
14 #include "GrResourceProvider.h" | 13 #include "GrResourceProvider.h" |
| 14 #include "GrTInstanceBatch.h" |
15 #include "GrTypes.h" | 15 #include "GrTypes.h" |
16 #include "GrVertexBatch.h" | |
17 #include "SkMatrix.h" | 16 #include "SkMatrix.h" |
18 #include "SkRect.h" | 17 #include "SkRect.h" |
19 | 18 |
20 GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); | 19 GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey); |
21 | 20 |
22 static void set_inset_fan(SkPoint* pts, size_t stride, | 21 static void set_inset_fan(SkPoint* pts, size_t stride, |
23 const SkRect& r, SkScalar dx, SkScalar dy) { | 22 const SkRect& r, SkScalar dx, SkScalar dy) { |
24 pts->setRectFan(r.fLeft + dx, r.fTop + dy, | 23 pts->setRectFan(r.fLeft + dx, r.fTop + dy, |
25 r.fRight - dx, r.fBottom - dy, stride); | 24 r.fRight - dx, r.fBottom - dy, stride); |
26 } | 25 } |
(...skipping 11 matching lines...) Expand all Loading... |
38 2, 3, 7, 7, 6, 2, | 37 2, 3, 7, 7, 6, 2, |
39 3, 0, 4, 4, 7, 3, | 38 3, 0, 4, 4, 7, 3, |
40 4, 5, 6, 6, 7, 4, | 39 4, 5, 6, 6, 7, 4, |
41 }; | 40 }; |
42 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFillAARectIdx) == kIndicesPerAAFillRect); | 41 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFillAARectIdx) == kIndicesPerAAFillRect); |
43 return resourceProvider->findOrCreateInstancedIndexBuffer(gFillAARectIdx, | 42 return resourceProvider->findOrCreateInstancedIndexBuffer(gFillAARectIdx, |
44 kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect
, | 43 kIndicesPerAAFillRect, kNumAAFillRectsInIndexBuffer, kVertsPerAAFillRect
, |
45 gAAFillRectIndexBufferKey); | 44 gAAFillRectIndexBufferKey); |
46 } | 45 } |
47 | 46 |
48 /* | |
49 * AAFillRectBatch is templated to optionally allow the insertion of an addition
al | |
50 * attribute for explicit local coordinates. | |
51 * To use this template, an implementation must define the following static func
tions: | |
52 * A Geometry struct | |
53 * | |
54 * bool CanCombine(const Geometry& mine, const Geometry& theirs, | |
55 * const GrPipelineOptimizations&) | |
56 * | |
57 * const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry, | |
58 * const GrPipelineOptimizations& opts) | |
59 * | |
60 * Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo, | |
61 * const GrPipelineOptimizations& opts) | |
62 */ | |
63 template <typename Base> | |
64 class AAFillRectBatch : public GrVertexBatch { | |
65 public: | |
66 typedef typename Base::Geometry Geometry; | |
67 | |
68 static AAFillRectBatch* Create() { | |
69 return SkNEW(AAFillRectBatch); | |
70 } | |
71 | |
72 const char* name() const override { return "AAFillRectBatch"; } | |
73 | |
74 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | |
75 // When this is called on a batch, there is only one geometry bundle | |
76 out->setKnownFourComponents(fGeoData[0].fColor); | |
77 } | |
78 | |
79 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { | |
80 out->setUnknownSingleComponent(); | |
81 } | |
82 | |
83 void initBatchTracker(const GrPipelineOptimizations& opt) override { | |
84 opt.getOverrideColorIfSet(&fGeoData[0].fColor); | |
85 fOpts = opt; | |
86 } | |
87 | |
88 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } | |
89 | |
90 // to avoid even the initial copy of the struct, we have a getter for the fi
rst item which | |
91 // is used to seed the batch with its initial geometry. After seeding, the
client should call | |
92 // init() so the Batch can initialize itself | |
93 Geometry* geometry() { return &fGeoData[0]; } | |
94 void init() { | |
95 const Geometry& geo = fGeoData[0]; | |
96 this->setBounds(geo.fDevRect); | |
97 } | |
98 | |
99 private: | |
100 AAFillRectBatch() { | |
101 this->initClassID<AAFillRectBatch<Base>>(); | |
102 | |
103 // Push back an initial geometry | |
104 fGeoData.push_back(); | |
105 } | |
106 | |
107 void onPrepareDraws(Target* target) override { | |
108 SkAutoTUnref<const GrGeometryProcessor> gp(Base::CreateGP(this->seedGeom
etry(), fOpts)); | |
109 if (!gp) { | |
110 SkDebugf("Couldn't create GrGeometryProcessor\n"); | |
111 return; | |
112 } | |
113 | |
114 target->initDraw(gp, this->pipeline()); | |
115 | |
116 size_t vertexStride = gp->getVertexStride(); | |
117 int instanceCount = fGeoData.count(); | |
118 | |
119 SkAutoTUnref<const GrIndexBuffer> indexBuffer(get_index_buffer(target->r
esourceProvider())); | |
120 InstancedHelper helper; | |
121 void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexS
tride, | |
122 indexBuffer, kVertsPerAAFillRect, kIndicesP
erAAFillRect, | |
123 instanceCount); | |
124 if (!vertices || !indexBuffer) { | |
125 SkDebugf("Could not allocate vertices\n"); | |
126 return; | |
127 } | |
128 | |
129 for (int i = 0; i < instanceCount; i++) { | |
130 intptr_t verts = reinterpret_cast<intptr_t>(vertices) + | |
131 i * kVertsPerAAFillRect * vertexStride; | |
132 Base::Tesselate(verts, vertexStride, fGeoData[i], fOpts); | |
133 } | |
134 helper.recordDraw(target); | |
135 } | |
136 | |
137 const Geometry& seedGeometry() const { return fGeoData[0]; } | |
138 | |
139 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | |
140 AAFillRectBatch* that = t->cast<AAFillRectBatch>(); | |
141 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | |
142 that->bounds(), caps)) { | |
143 return false; | |
144 } | |
145 | |
146 if (!Base::CanCombine(this->seedGeometry(), that->seedGeometry(), fOpts)
) { | |
147 return false; | |
148 } | |
149 | |
150 // In the event of two batches, one who can tweak, one who cannot, we ju
st fall back to | |
151 // not tweaking | |
152 if (fOpts.canTweakAlphaForCoverage() && !that->fOpts.canTweakAlphaForCov
erage()) { | |
153 fOpts = that->fOpts; | |
154 } | |
155 | |
156 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin())
; | |
157 this->joinBounds(that->bounds()); | |
158 return true; | |
159 } | |
160 | |
161 GrPipelineOptimizations fOpts; | |
162 SkSTArray<1, Geometry, true> fGeoData; | |
163 }; | |
164 | |
165 static const GrGeometryProcessor* create_fill_rect_gp( | 47 static const GrGeometryProcessor* create_fill_rect_gp( |
166 const SkMatrix& viewMatrix, | 48 const SkMatrix& viewMatrix, |
167 const GrPipelineOptimizations& opts, | 49 const GrPipelineOptimizations& opts, |
168 GrDefaultGeoProcFactory::LocalCoords::Typ
e localCoordsType) { | 50 GrDefaultGeoProcFactory::LocalCoords::Typ
e localCoordsType) { |
169 using namespace GrDefaultGeoProcFactory; | 51 using namespace GrDefaultGeoProcFactory; |
170 | 52 |
171 Color color(Color::kAttribute_Type); | 53 Color color(Color::kAttribute_Type); |
172 Coverage::Type coverageType; | 54 Coverage::Type coverageType; |
173 // TODO remove coverage if coverage is ignored | 55 // TODO remove coverage if coverage is ignored |
174 /*if (coverageIgnored) { | 56 /*if (coverageIgnored) { |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 if (tweakAlphaForCoverage) { | 174 if (tweakAlphaForCoverage) { |
293 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; | 175 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = scaledColor; |
294 } else { | 176 } else { |
295 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; | 177 *reinterpret_cast<GrColor*>(verts + i * vertexStride) = color; |
296 *reinterpret_cast<float*>(verts + i * vertexStride + | 178 *reinterpret_cast<float*>(verts + i * vertexStride + |
297 coverageOffset) = innerCoverage; | 179 coverageOffset) = innerCoverage; |
298 } | 180 } |
299 } | 181 } |
300 } | 182 } |
301 | 183 |
302 class AAFillRectBatchNoLocalMatrixImp { | 184 // Common functions |
| 185 class AAFillRectBatchBase { |
| 186 public: |
| 187 static const int kVertsPerInstance = kVertsPerAAFillRect; |
| 188 static const int kIndicesPerInstance = kIndicesPerAAFillRect; |
| 189 |
| 190 inline static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* rp) { |
| 191 return get_index_buffer(rp); |
| 192 } |
| 193 }; |
| 194 |
| 195 class AAFillRectBatchNoLocalMatrixImp : public AAFillRectBatchBase { |
303 public: | 196 public: |
304 struct Geometry { | 197 struct Geometry { |
305 SkMatrix fViewMatrix; | 198 SkMatrix fViewMatrix; |
306 SkRect fRect; | 199 SkRect fRect; |
307 SkRect fDevRect; | 200 SkRect fDevRect; |
308 GrColor fColor; | 201 GrColor fColor; |
309 }; | 202 }; |
310 | 203 |
| 204 inline static const char* Name() { return "AAFillRectBatchNoLocalMatrix"; } |
| 205 |
311 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs, | 206 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs, |
312 const GrPipelineOptimizations& opts) { | 207 const GrPipelineOptimizations& opts) { |
313 // We apply the viewmatrix to the rect points on the cpu. However, if t
he pipeline uses | 208 // We apply the viewmatrix to the rect points on the cpu. However, if t
he pipeline uses |
314 // local coords then we won't be able to batch. We could actually uploa
d the viewmatrix | 209 // local coords then we won't be able to batch. We could actually uploa
d the viewmatrix |
315 // using vertex attributes in these cases, but haven't investigated that | 210 // using vertex attributes in these cases, but haven't investigated that |
316 return !opts.readsLocalCoords() || mine.fViewMatrix.cheapEqualTo(theirs.
fViewMatrix); | 211 return !opts.readsLocalCoords() || mine.fViewMatrix.cheapEqualTo(theirs.
fViewMatrix); |
317 } | 212 } |
318 | 213 |
319 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo, | 214 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo, |
320 const GrPipelineOptimizati
ons& opts) { | 215 const GrPipelineOptimizati
ons& opts) { |
321 const GrGeometryProcessor* gp = | 216 const GrGeometryProcessor* gp = |
322 create_fill_rect_gp(geo.fViewMatrix, opts, | 217 create_fill_rect_gp(geo.fViewMatrix, opts, |
323 GrDefaultGeoProcFactory::LocalCoords::kUsePo
sition_Type); | 218 GrDefaultGeoProcFactory::LocalCoords::kUsePo
sition_Type); |
324 | 219 |
325 SkASSERT(opts.canTweakAlphaForCoverage() ? | 220 SkASSERT(opts.canTweakAlphaForCoverage() ? |
326 gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::Positi
onColorAttr) : | 221 gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::Positi
onColorAttr) : |
327 gp->getVertexStride() == | 222 gp->getVertexStride() == |
328 sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAt
tr)); | 223 sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAt
tr)); |
329 return gp; | 224 return gp; |
330 } | 225 } |
331 | 226 |
332 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G
eometry& geo, | 227 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G
eometry& geo, |
333 const GrPipelineOptimizations& opts) { | 228 const GrPipelineOptimizations& opts) { |
334 generate_aa_fill_rect_geometry(vertices, vertexStride, | 229 generate_aa_fill_rect_geometry(vertices, vertexStride, |
335 geo.fColor, geo.fViewMatrix, geo.fRect, g
eo.fDevRect, opts, | 230 geo.fColor, geo.fViewMatrix, geo.fRect, g
eo.fDevRect, opts, |
336 NULL); | 231 NULL); |
337 } | 232 } |
338 }; | 233 }; |
339 | 234 |
340 class AAFillRectBatchLocalMatrixImp { | 235 class AAFillRectBatchLocalMatrixImp : public AAFillRectBatchBase { |
341 public: | 236 public: |
342 struct Geometry { | 237 struct Geometry { |
343 SkMatrix fViewMatrix; | 238 SkMatrix fViewMatrix; |
344 SkMatrix fLocalMatrix; | 239 SkMatrix fLocalMatrix; |
345 SkRect fRect; | 240 SkRect fRect; |
346 SkRect fDevRect; | 241 SkRect fDevRect; |
347 GrColor fColor; | 242 GrColor fColor; |
348 }; | 243 }; |
349 | 244 |
| 245 inline static const char* Name() { return "AAFillRectBatchLocalMatrix"; } |
| 246 |
350 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs, | 247 inline static bool CanCombine(const Geometry& mine, const Geometry& theirs, |
351 const GrPipelineOptimizations&) { | 248 const GrPipelineOptimizations&) { |
352 return true; | 249 return true; |
353 } | 250 } |
354 | 251 |
355 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo, | 252 inline static const GrGeometryProcessor* CreateGP(const Geometry& geo, |
356 const GrPipelineOptimizati
ons& opts) { | 253 const GrPipelineOptimizati
ons& opts) { |
357 const GrGeometryProcessor* gp = | 254 const GrGeometryProcessor* gp = |
358 create_fill_rect_gp(geo.fViewMatrix, opts, | 255 create_fill_rect_gp(geo.fViewMatrix, opts, |
359 GrDefaultGeoProcFactory::LocalCoords::kHasEx
plicit_Type); | 256 GrDefaultGeoProcFactory::LocalCoords::kHasEx
plicit_Type); |
360 | 257 |
361 SkASSERT(opts.canTweakAlphaForCoverage() ? | 258 SkASSERT(opts.canTweakAlphaForCoverage() ? |
362 gp->getVertexStride() == | 259 gp->getVertexStride() == |
363 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoord
Attr) : | 260 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoord
Attr) : |
364 gp->getVertexStride() == | 261 gp->getVertexStride() == |
365 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoord
Coverage)); | 262 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoord
Coverage)); |
366 return gp; | 263 return gp; |
367 } | 264 } |
368 | 265 |
369 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G
eometry& geo, | 266 inline static void Tesselate(intptr_t vertices, size_t vertexStride, const G
eometry& geo, |
370 const GrPipelineOptimizations& opts) { | 267 const GrPipelineOptimizations& opts) { |
371 generate_aa_fill_rect_geometry(vertices, vertexStride, | 268 generate_aa_fill_rect_geometry(vertices, vertexStride, |
372 geo.fColor, geo.fViewMatrix, geo.fRect, g
eo.fDevRect, opts, | 269 geo.fColor, geo.fViewMatrix, geo.fRect, g
eo.fDevRect, opts, |
373 &geo.fLocalMatrix); | 270 &geo.fLocalMatrix); |
374 } | 271 } |
375 }; | 272 }; |
376 | 273 |
377 typedef AAFillRectBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalM
atrix; | 274 typedef GrTInstanceBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocal
Matrix; |
378 typedef AAFillRectBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatri
x; | 275 typedef GrTInstanceBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatr
ix; |
379 | 276 |
380 namespace GrAAFillRectBatch { | 277 namespace GrAAFillRectBatch { |
381 | 278 |
382 GrDrawBatch* Create(GrColor color, | 279 GrDrawBatch* Create(GrColor color, |
383 const SkMatrix& viewMatrix, | 280 const SkMatrix& viewMatrix, |
384 const SkRect& rect, | 281 const SkRect& rect, |
385 const SkRect& devRect) { | 282 const SkRect& devRect) { |
386 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create()
; | 283 AAFillRectBatchNoLocalMatrix* batch = AAFillRectBatchNoLocalMatrix::Create()
; |
387 AAFillRectBatchNoLocalMatrix::Geometry& geo = *batch->geometry(); | 284 AAFillRectBatchNoLocalMatrix::Geometry& geo = *batch->geometry(); |
388 geo.fColor = color; | 285 geo.fColor = color; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 DRAW_BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) { | 325 DRAW_BATCH_TEST_DEFINE(AAFillRectBatchLocalMatrix) { |
429 GrColor color = GrRandomColor(random); | 326 GrColor color = GrRandomColor(random); |
430 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); | 327 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); |
431 SkMatrix localMatrix = GrTest::TestMatrix(random); | 328 SkMatrix localMatrix = GrTest::TestMatrix(random); |
432 SkRect rect = GrTest::TestRect(random); | 329 SkRect rect = GrTest::TestRect(random); |
433 SkRect devRect = GrTest::TestRect(random); | 330 SkRect devRect = GrTest::TestRect(random); |
434 return GrAAFillRectBatch::Create(color, viewMatrix, localMatrix, rect, devRe
ct); | 331 return GrAAFillRectBatch::Create(color, viewMatrix, localMatrix, rect, devRe
ct); |
435 } | 332 } |
436 | 333 |
437 #endif | 334 #endif |
OLD | NEW |