diff options
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/batches/GrAAFillRectBatch.cpp | 143 | ||||
-rw-r--r-- | src/gpu/batches/GrTInstanceBatch.h | 139 |
2 files changed, 159 insertions, 123 deletions
diff --git a/src/gpu/batches/GrAAFillRectBatch.cpp b/src/gpu/batches/GrAAFillRectBatch.cpp index c6eb5ab9ed..8760896604 100644 --- a/src/gpu/batches/GrAAFillRectBatch.cpp +++ b/src/gpu/batches/GrAAFillRectBatch.cpp @@ -7,13 +7,12 @@ #include "GrAAFillRectBatch.h" -#include "GrBatchFlushState.h" #include "GrColor.h" #include "GrDefaultGeoProcFactory.h" #include "GrResourceKey.h" #include "GrResourceProvider.h" +#include "GrTInstanceBatch.h" #include "GrTypes.h" -#include "GrVertexBatch.h" #include "SkMatrix.h" #include "SkRect.h" @@ -45,123 +44,6 @@ const GrIndexBuffer* get_index_buffer(GrResourceProvider* resourceProvider) { gAAFillRectIndexBufferKey); } -/* - * AAFillRectBatch is templated to optionally allow the insertion of an additional - * attribute for explicit local coordinates. - * To use this template, an implementation must define the following static functions: - * A Geometry struct - * - * bool CanCombine(const Geometry& mine, const Geometry& theirs, - * const GrPipelineOptimizations&) - * - * const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry, - * const GrPipelineOptimizations& opts) - * - * Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo, - * const GrPipelineOptimizations& opts) - */ -template <typename Base> -class AAFillRectBatch : public GrVertexBatch { -public: - typedef typename Base::Geometry Geometry; - - static AAFillRectBatch* Create() { - return SkNEW(AAFillRectBatch); - } - - const char* name() const override { return "AAFillRectBatch"; } - - void getInvariantOutputColor(GrInitInvariantOutput* out) const override { - // When this is called on a batch, there is only one geometry bundle - out->setKnownFourComponents(fGeoData[0].fColor); - } - - void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { - out->setUnknownSingleComponent(); - } - - void initBatchTracker(const GrPipelineOptimizations& opt) override { - opt.getOverrideColorIfSet(&fGeoData[0].fColor); - fOpts = opt; - } - - SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } - - // to avoid even the initial copy of the struct, we have a getter for the first item which - // is used to seed the batch with its initial geometry. After seeding, the client should call - // init() so the Batch can initialize itself - Geometry* geometry() { return &fGeoData[0]; } - void init() { - const Geometry& geo = fGeoData[0]; - this->setBounds(geo.fDevRect); - } - -private: - AAFillRectBatch() { - this->initClassID<AAFillRectBatch<Base>>(); - - // Push back an initial geometry - fGeoData.push_back(); - } - - void onPrepareDraws(Target* target) override { - SkAutoTUnref<const GrGeometryProcessor> gp(Base::CreateGP(this->seedGeometry(), fOpts)); - if (!gp) { - SkDebugf("Couldn't create GrGeometryProcessor\n"); - return; - } - - target->initDraw(gp, this->pipeline()); - - size_t vertexStride = gp->getVertexStride(); - int instanceCount = fGeoData.count(); - - SkAutoTUnref<const GrIndexBuffer> indexBuffer(get_index_buffer(target->resourceProvider())); - InstancedHelper helper; - void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride, - indexBuffer, kVertsPerAAFillRect, kIndicesPerAAFillRect, - instanceCount); - if (!vertices || !indexBuffer) { - SkDebugf("Could not allocate vertices\n"); - return; - } - - for (int i = 0; i < instanceCount; i++) { - intptr_t verts = reinterpret_cast<intptr_t>(vertices) + - i * kVertsPerAAFillRect * vertexStride; - Base::Tesselate(verts, vertexStride, fGeoData[i], fOpts); - } - helper.recordDraw(target); - } - - const Geometry& seedGeometry() const { return fGeoData[0]; } - - bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { - AAFillRectBatch* that = t->cast<AAFillRectBatch>(); - if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), - that->bounds(), caps)) { - return false; - } - - if (!Base::CanCombine(this->seedGeometry(), that->seedGeometry(), fOpts)) { - return false; - } - - // In the event of two batches, one who can tweak, one who cannot, we just fall back to - // not tweaking - if (fOpts.canTweakAlphaForCoverage() && !that->fOpts.canTweakAlphaForCoverage()) { - fOpts = that->fOpts; - } - - fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); - this->joinBounds(that->bounds()); - return true; - } - - GrPipelineOptimizations fOpts; - SkSTArray<1, Geometry, true> fGeoData; -}; - static const GrGeometryProcessor* create_fill_rect_gp( const SkMatrix& viewMatrix, const GrPipelineOptimizations& opts, @@ -299,7 +181,18 @@ static void generate_aa_fill_rect_geometry(intptr_t verts, } } -class AAFillRectBatchNoLocalMatrixImp { +// Common functions +class AAFillRectBatchBase { +public: + static const int kVertsPerInstance = kVertsPerAAFillRect; + static const int kIndicesPerInstance = kIndicesPerAAFillRect; + + inline static const GrIndexBuffer* GetIndexBuffer(GrResourceProvider* rp) { + return get_index_buffer(rp); + } +}; + +class AAFillRectBatchNoLocalMatrixImp : public AAFillRectBatchBase { public: struct Geometry { SkMatrix fViewMatrix; @@ -308,6 +201,8 @@ public: GrColor fColor; }; + inline static const char* Name() { return "AAFillRectBatchNoLocalMatrix"; } + inline static bool CanCombine(const Geometry& mine, const Geometry& theirs, const GrPipelineOptimizations& opts) { // We apply the viewmatrix to the rect points on the cpu. However, if the pipeline uses @@ -337,7 +232,7 @@ public: } }; -class AAFillRectBatchLocalMatrixImp { +class AAFillRectBatchLocalMatrixImp : public AAFillRectBatchBase { public: struct Geometry { SkMatrix fViewMatrix; @@ -347,6 +242,8 @@ public: GrColor fColor; }; + inline static const char* Name() { return "AAFillRectBatchLocalMatrix"; } + inline static bool CanCombine(const Geometry& mine, const Geometry& theirs, const GrPipelineOptimizations&) { return true; @@ -374,8 +271,8 @@ public: } }; -typedef AAFillRectBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalMatrix; -typedef AAFillRectBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatrix; +typedef GrTInstanceBatch<AAFillRectBatchNoLocalMatrixImp> AAFillRectBatchNoLocalMatrix; +typedef GrTInstanceBatch<AAFillRectBatchLocalMatrixImp> AAFillRectBatchLocalMatrix; namespace GrAAFillRectBatch { diff --git a/src/gpu/batches/GrTInstanceBatch.h b/src/gpu/batches/GrTInstanceBatch.h new file mode 100644 index 0000000000..420f873d26 --- /dev/null +++ b/src/gpu/batches/GrTInstanceBatch.h @@ -0,0 +1,139 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrTInstanceBatch_DEFINED +#define GrTInstanceBatch_DEFINED + +#include "GrVertexBatch.h" + +#include "GrBatchFlushState.h" + +/** + * GrTInstanceBatch is an optional template to help with writing batches + * To use this template, The 'Impl' must define the following statics: + * A Geometry struct + * + * static const int kVertsPerInstance + * static const int kIndicesPerInstance + * + * const char* Name() + * + * bool CanCombine(const Geometry& mine, const Geometry& theirs, + * const GrPipelineOptimizations&) + * + * const GrGeometryProcessor* CreateGP(const Geometry& seedGeometry, + * const GrPipelineOptimizations& opts) + * + * const GrIndexBuffer* GetIndexBuffer(GrResourceProvider*) + * + * Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo, + * const GrPipelineOptimizations& opts) + */ +template <typename Impl> +class GrTInstanceBatch : public GrVertexBatch { +public: + typedef typename Impl::Geometry Geometry; + + static GrTInstanceBatch* Create() { + return SkNEW(GrTInstanceBatch); + } + + const char* name() const override { return Impl::Name(); } + + void getInvariantOutputColor(GrInitInvariantOutput* out) const override { + // When this is called on a batch, there is only one geometry bundle + out->setKnownFourComponents(fGeoData[0].fColor); + } + + void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { + out->setUnknownSingleComponent(); + } + + void initBatchTracker(const GrPipelineOptimizations& opt) override { + opt.getOverrideColorIfSet(&fGeoData[0].fColor); + fOpts = opt; + } + + SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } + + // to avoid even the initial copy of the struct, we have a getter for the first item which + // is used to seed the batch with its initial geometry. After seeding, the client should call + // init() so the Batch can initialize itself + Geometry* geometry() { return &fGeoData[0]; } + void init() { + const Geometry& geo = fGeoData[0]; + this->setBounds(geo.fDevRect); + } + +private: + GrTInstanceBatch() { + this->initClassID<GrTInstanceBatch<Impl>>(); + + // Push back an initial geometry + fGeoData.push_back(); + } + + void onPrepareDraws(Target* target) override { + SkAutoTUnref<const GrGeometryProcessor> gp(Impl::CreateGP(this->seedGeometry(), fOpts)); + if (!gp) { + SkDebugf("Couldn't create GrGeometryProcessor\n"); + return; + } + + target->initDraw(gp, this->pipeline()); + + size_t vertexStride = gp->getVertexStride(); + int instanceCount = fGeoData.count(); + + SkAutoTUnref<const GrIndexBuffer> indexBuffer( + Impl::GetIndexBuffer(target->resourceProvider())); + InstancedHelper helper; + void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride, + indexBuffer, Impl::kVertsPerInstance, + Impl::kIndicesPerInstance, instanceCount); + if (!vertices || !indexBuffer) { + SkDebugf("Could not allocate vertices\n"); + return; + } + + for (int i = 0; i < instanceCount; i++) { + intptr_t verts = reinterpret_cast<intptr_t>(vertices) + + i * Impl::kVertsPerInstance * vertexStride; + Impl::Tesselate(verts, vertexStride, fGeoData[i], fOpts); + } + helper.recordDraw(target); + } + + const Geometry& seedGeometry() const { return fGeoData[0]; } + + bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { + GrTInstanceBatch* that = t->cast<GrTInstanceBatch>(); + if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), + that->bounds(), caps)) { + return false; + } + + if (!Impl::CanCombine(this->seedGeometry(), that->seedGeometry(), fOpts)) { + return false; + } + + // In the event of two batches, one who can tweak, one who cannot, we just fall back to + // not tweaking + if (fOpts.canTweakAlphaForCoverage() && !that->fOpts.canTweakAlphaForCoverage()) { + fOpts = that->fOpts; + } + + fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); + this->joinBounds(that->bounds()); + return true; + } + + GrPipelineOptimizations fOpts; + SkSTArray<1, Geometry, true> fGeoData; +}; + +#endif |