| 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 |