Index: src/gpu/batches/GrNonAAFillRectBatch.cpp |
diff --git a/src/gpu/batches/GrNonAAFillRectBatch.cpp b/src/gpu/batches/GrNonAAFillRectBatch.cpp |
index 3b4c5da7328320e21151664c4d4176becd8c16be..186c935c703fc905dc8f92bbbce21968a041fd7d 100644 |
--- a/src/gpu/batches/GrNonAAFillRectBatch.cpp |
+++ b/src/gpu/batches/GrNonAAFillRectBatch.cpp |
@@ -12,36 +12,11 @@ |
#include "GrDefaultGeoProcFactory.h" |
#include "GrPrimitiveProcessor.h" |
#include "GrResourceProvider.h" |
-#include "GrTInstanceBatch.h" |
#include "GrQuad.h" |
#include "GrVertexBatch.h" |
-// Common functions |
-class NonAAFillRectBatchBase { |
-public: |
- static const int kVertsPerInstance = 4; |
- static const int kIndicesPerInstance = 6; |
- |
- static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) { |
- out->setKnownSingleComponent(0xff); |
- } |
- |
- static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) { |
- return rp->refQuadIndexBuffer(); |
- } |
- |
- template <typename Geometry> |
- static void SetBounds(const Geometry& geo, SkRect* outBounds) { |
- geo.fViewMatrix.mapRect(outBounds, geo.fRect); |
- } |
- |
- template <typename Geometry> |
- static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) { |
- SkRect bounds = geo.fRect; |
- geo.fViewMatrix.mapRect(&bounds); |
- outBounds->join(bounds); |
- } |
-}; |
+static const int kVertsPerInstance = 4; |
+static const int kIndicesPerInstance = 6; |
/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes |
we have explicit local coords and sometimes not. We *could* always provide explicit local |
@@ -90,15 +65,14 @@ static void tesselate(intptr_t vertices, |
rect.fRight, rect.fBottom, vertexStride); |
if (!viewMatrix.hasPerspective()) { |
- viewMatrix.mapPointsWithStride(positions, vertexStride, |
- NonAAFillRectBatchBase::kVertsPerInstance); |
+ viewMatrix.mapPointsWithStride(positions, vertexStride, kVertsPerInstance); |
} |
// Setup local coords |
// TODO we should only do this if local coords are being read |
if (localQuad) { |
static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor); |
- for (int i = 0; i < NonAAFillRectBatchBase::kVertsPerInstance; i++) { |
+ for (int i = 0; i < kVertsPerInstance; i++) { |
SkPoint* coords = reinterpret_cast<SkPoint*>(vertices + kLocalOffset + |
i * vertexStride); |
*coords = localQuad->point(i); |
@@ -113,8 +87,10 @@ static void tesselate(intptr_t vertices, |
} |
} |
-class NonAAFillRectBatchImp : public NonAAFillRectBatchBase { |
+class NonAAFillRectBatch : public GrVertexBatch { |
public: |
+ DEFINE_BATCH_CLASS_ID |
+ |
struct Geometry { |
SkMatrix fViewMatrix; |
SkRect fRect; |
@@ -122,6 +98,47 @@ public: |
GrColor fColor; |
}; |
+ static NonAAFillRectBatch* Create() { return new NonAAFillRectBatch; } |
+ |
+ const char* name() const override { return Name(); } |
+ |
+ SkString dumpInfo() const override { |
+ SkString str; |
+ str.appendf("# batched: %d\n", fGeoData.count()); |
+ for (int i = 0; i < fGeoData.count(); ++i) { |
+ str.append(DumpInfo(fGeoData[i], i)); |
+ } |
+ str.append(INHERITED::dumpInfo()); |
+ return str; |
+ } |
+ |
+ void computePipelineOptimizations(GrInitInvariantOutput* color, |
+ GrInitInvariantOutput* coverage, |
+ GrBatchToXPOverrides* overrides) const override { |
+ // When this is called on a batch, there is only one geometry bundle |
+ color->setKnownFourComponents(fGeoData[0].fColor); |
+ InitInvariantOutputCoverage(coverage); |
+ } |
+ |
+ void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
+ overrides.getOverrideColorIfSet(&fGeoData[0].fColor); |
+ fOverrides = overrides; |
+ } |
+ |
+ SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
+ |
+ // After seeding, the client should call init() so the Batch can initialize itself |
+ void init() { |
+ const Geometry& geo = fGeoData[0]; |
+ SetBounds(geo, &fBounds); |
+ } |
+ |
+ void updateBoundsAfterAppend() { |
+ const Geometry& geo = fGeoData.back(); |
+ UpdateBoundsAfterAppend(geo, &fBounds); |
+ } |
+ |
+private: |
static const char* Name() { return "NonAAFillRectBatch"; } |
static SkString DumpInfo(const Geometry& geo, int index) { |
@@ -152,11 +169,90 @@ public: |
const GrXPOverridesForBatch& overrides) { |
tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, &geo.fLocalQuad); |
} |
+ |
+ static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) { |
+ out->setKnownSingleComponent(0xff); |
+ } |
+ |
+ static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) { |
+ return rp->refQuadIndexBuffer(); |
+ } |
+ |
+ static void SetBounds(const Geometry& geo, SkRect* outBounds) { |
+ geo.fViewMatrix.mapRect(outBounds, geo.fRect); |
+ } |
+ |
+ static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) { |
+ SkRect bounds = geo.fRect; |
+ geo.fViewMatrix.mapRect(&bounds); |
+ outBounds->join(bounds); |
+ } |
+ |
+ NonAAFillRectBatch() : INHERITED(ClassID()) {} |
+ |
+ void onPrepareDraws(Target* target) const override { |
+ sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides)); |
+ if (!gp) { |
+ SkDebugf("Couldn't create GrGeometryProcessor\n"); |
+ return; |
+ } |
+ |
+ size_t vertexStride = gp->getVertexStride(); |
+ int instanceCount = fGeoData.count(); |
+ |
+ SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider())); |
+ InstancedHelper helper; |
+ void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride, |
+ indexBuffer, kVertsPerInstance, |
+ 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 * kVertsPerInstance * vertexStride; |
+ Tesselate(verts, vertexStride, fGeoData[i], fOverrides); |
+ } |
+ helper.recordDraw(target, gp.get()); |
+ } |
+ |
+ const Geometry& seedGeometry() const { return fGeoData[0]; } |
+ |
+ bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
+ NonAAFillRectBatch* that = t->cast<NonAAFillRectBatch>(); |
+ if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), |
+ that->bounds(), caps)) { |
+ return false; |
+ } |
+ |
+ if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) { |
+ return false; |
+ } |
+ |
+ // In the event of two batches, one who can tweak, one who cannot, we just fall back to |
+ // not tweaking |
+ if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) { |
+ fOverrides = that->fOverrides; |
+ } |
+ |
+ fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); |
+ this->joinBounds(that->bounds()); |
+ return true; |
+ } |
+ |
+ GrXPOverridesForBatch fOverrides; |
+ SkSTArray<1, Geometry, true> fGeoData; |
+ |
+ typedef GrVertexBatch INHERITED; |
}; |
// We handle perspective in the local matrix or viewmatrix with special batches |
-class NonAAFillRectBatchPerspectiveImp : public NonAAFillRectBatchBase { |
+class NonAAFillRectPerspectiveBatch : public GrVertexBatch { |
public: |
+ DEFINE_BATCH_CLASS_ID |
+ |
struct Geometry { |
SkMatrix fViewMatrix; |
SkMatrix fLocalMatrix; |
@@ -167,7 +263,48 @@ public: |
bool fHasLocalRect; |
}; |
- static const char* Name() { return "NonAAFillRectBatchPerspective"; } |
+ static NonAAFillRectPerspectiveBatch* Create() { return new NonAAFillRectPerspectiveBatch; } |
+ |
+ const char* name() const override { return Name(); } |
+ |
+ SkString dumpInfo() const override { |
+ SkString str; |
+ str.appendf("# batched: %d\n", fGeoData.count()); |
+ for (int i = 0; i < fGeoData.count(); ++i) { |
+ str.append(DumpInfo(fGeoData[i], i)); |
+ } |
+ str.append(INHERITED::dumpInfo()); |
+ return str; |
+ } |
+ |
+ void computePipelineOptimizations(GrInitInvariantOutput* color, |
+ GrInitInvariantOutput* coverage, |
+ GrBatchToXPOverrides* overrides) const override { |
+ // When this is called on a batch, there is only one geometry bundle |
+ color->setKnownFourComponents(fGeoData[0].fColor); |
+ InitInvariantOutputCoverage(coverage); |
+ } |
+ |
+ void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
+ overrides.getOverrideColorIfSet(&fGeoData[0].fColor); |
+ fOverrides = overrides; |
+ } |
+ |
+ SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
+ |
+ // After seeding, the client should call init() so the Batch can initialize itself |
+ void init() { |
+ const Geometry& geo = fGeoData[0]; |
+ SetBounds(geo, &fBounds); |
+ } |
+ |
+ void updateBoundsAfterAppend() { |
+ const Geometry& geo = fGeoData.back(); |
+ UpdateBoundsAfterAppend(geo, &fBounds); |
+ } |
+ |
+private: |
+ static const char* Name() { return "NonAAFillRectPerspectiveBatch"; } |
static SkString DumpInfo(const Geometry& geo, int index) { |
SkString str; |
@@ -208,16 +345,90 @@ public: |
tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, nullptr); |
} |
} |
-}; |
-typedef GrTInstanceBatch<NonAAFillRectBatchImp> NonAAFillRectBatchSimple; |
-typedef GrTInstanceBatch<NonAAFillRectBatchPerspectiveImp> NonAAFillRectBatchPerspective; |
+ static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) { |
+ out->setKnownSingleComponent(0xff); |
+ } |
+ |
+ static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) { |
+ return rp->refQuadIndexBuffer(); |
+ } |
+ |
+ static void SetBounds(const Geometry& geo, SkRect* outBounds) { |
+ geo.fViewMatrix.mapRect(outBounds, geo.fRect); |
+ } |
+ |
+ static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) { |
+ SkRect bounds = geo.fRect; |
+ geo.fViewMatrix.mapRect(&bounds); |
+ outBounds->join(bounds); |
+ } |
+ |
+ NonAAFillRectPerspectiveBatch() : INHERITED(ClassID()) {} |
+ |
+ void onPrepareDraws(Target* target) const override { |
+ sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides)); |
+ if (!gp) { |
+ SkDebugf("Couldn't create GrGeometryProcessor\n"); |
+ return; |
+ } |
+ |
+ size_t vertexStride = gp->getVertexStride(); |
+ int instanceCount = fGeoData.count(); |
+ |
+ SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider())); |
+ InstancedHelper helper; |
+ void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride, |
+ indexBuffer, kVertsPerInstance, |
+ 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 * kVertsPerInstance * vertexStride; |
+ Tesselate(verts, vertexStride, fGeoData[i], fOverrides); |
+ } |
+ helper.recordDraw(target, gp.get()); |
+ } |
+ |
+ const Geometry& seedGeometry() const { return fGeoData[0]; } |
+ |
+ bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
+ NonAAFillRectPerspectiveBatch* that = t->cast<NonAAFillRectPerspectiveBatch>(); |
+ if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(), |
+ that->bounds(), caps)) { |
+ return false; |
+ } |
+ |
+ if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) { |
+ return false; |
+ } |
+ |
+ // In the event of two batches, one who can tweak, one who cannot, we just fall back to |
+ // not tweaking |
+ if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) { |
+ fOverrides = that->fOverrides; |
+ } |
+ |
+ fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()); |
+ this->joinBounds(that->bounds()); |
+ return true; |
+ } |
+ |
+ GrXPOverridesForBatch fOverrides; |
+ SkSTArray<1, Geometry, true> fGeoData; |
+ |
+ typedef GrVertexBatch INHERITED; |
+}; |
-inline static void append_to_batch(NonAAFillRectBatchSimple* batch, GrColor color, |
+inline static void append_to_batch(NonAAFillRectBatch* batch, GrColor color, |
const SkMatrix& viewMatrix, const SkRect& rect, |
const SkRect* localRect, const SkMatrix* localMatrix) { |
SkASSERT(!viewMatrix.hasPerspective() && (!localMatrix || !localMatrix->hasPerspective())); |
- NonAAFillRectBatchSimple::Geometry& geo = batch->geoData()->push_back(); |
+ NonAAFillRectBatch::Geometry& geo = batch->geoData()->push_back(); |
geo.fColor = color; |
geo.fViewMatrix = viewMatrix; |
@@ -234,11 +445,11 @@ inline static void append_to_batch(NonAAFillRectBatchSimple* batch, GrColor colo |
} |
} |
-inline static void append_to_batch(NonAAFillRectBatchPerspective* batch, GrColor color, |
+inline static void append_to_batch(NonAAFillRectPerspectiveBatch* batch, GrColor color, |
const SkMatrix& viewMatrix, const SkRect& rect, |
const SkRect* localRect, const SkMatrix* localMatrix) { |
SkASSERT(viewMatrix.hasPerspective() || (localMatrix && localMatrix->hasPerspective())); |
- NonAAFillRectBatchPerspective::Geometry& geo = batch->geoData()->push_back(); |
+ NonAAFillRectPerspectiveBatch::Geometry& geo = batch->geoData()->push_back(); |
geo.fColor = color; |
geo.fViewMatrix = viewMatrix; |
@@ -261,7 +472,7 @@ GrDrawBatch* Create(GrColor color, |
const SkRect& rect, |
const SkRect* localRect, |
const SkMatrix* localMatrix) { |
- NonAAFillRectBatchSimple* batch = NonAAFillRectBatchSimple::Create(); |
+ NonAAFillRectBatch* batch = NonAAFillRectBatch::Create(); |
append_to_batch(batch, color, viewMatrix, rect, localRect, localMatrix); |
batch->init(); |
return batch; |
@@ -272,7 +483,7 @@ GrDrawBatch* CreateWithPerspective(GrColor color, |
const SkRect& rect, |
const SkRect* localRect, |
const SkMatrix* localMatrix) { |
- NonAAFillRectBatchPerspective* batch = NonAAFillRectBatchPerspective::Create(); |
+ NonAAFillRectPerspectiveBatch* batch = NonAAFillRectPerspectiveBatch::Create(); |
append_to_batch(batch, color, viewMatrix, rect, localRect, localMatrix); |
batch->init(); |
return batch; |
@@ -287,17 +498,17 @@ bool Append(GrBatch* origBatch, |
bool usePerspective = viewMatrix.hasPerspective() || |
(localMatrix && localMatrix->hasPerspective()); |
- if (usePerspective && origBatch->classID() != NonAAFillRectBatchPerspective::ClassID()) { |
+ if (usePerspective && origBatch->classID() != NonAAFillRectPerspectiveBatch::ClassID()) { |
return false; |
} |
if (!usePerspective) { |
- NonAAFillRectBatchSimple* batch = origBatch->cast<NonAAFillRectBatchSimple>(); |
+ NonAAFillRectBatch* batch = origBatch->cast<NonAAFillRectBatch>(); |
append_to_batch(batch, color, viewMatrix, rect, localRect, localMatrix); |
batch->updateBoundsAfterAppend(); |
} else { |
- NonAAFillRectBatchPerspective* batch = origBatch->cast<NonAAFillRectBatchPerspective>(); |
- const NonAAFillRectBatchPerspective::Geometry& geo = batch->geoData()->back(); |
+ NonAAFillRectPerspectiveBatch* batch = origBatch->cast<NonAAFillRectPerspectiveBatch>(); |
+ const NonAAFillRectPerspectiveBatch::Geometry& geo = batch->geoData()->back(); |
if (!geo.fViewMatrix.cheapEqualTo(viewMatrix) || |
geo.fHasLocalRect != SkToBool(localRect) || |