Split GrCCCoverageProcessor into subclasses
Makes separate subclasses for geometry and vertex shaders.
Bug: skia:
Change-Id: Ifced79af3092090a71d03fe252fb4da76738cf08
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/204545
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
index f72ccf9..0be4c08 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp
@@ -184,23 +184,6 @@
outputAttenuation);
}
-void GrCCCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&,
- GrProcessorKeyBuilder* b) const {
- int key = (int)fPrimitiveType << 2;
- if (GSSubpass::kCorners == fGSSubpass) {
- key |= 2;
- }
- if (Impl::kVertexShader == fImpl) {
- key |= 1;
- }
-#ifdef SK_DEBUG
- uint32_t bloatBits;
- memcpy(&bloatBits, &fDebugBloat, 4);
- b->add32(bloatBits);
-#endif
- b->add32(key);
-}
-
GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createGLSLInstance(const GrShaderCaps&) const {
std::unique_ptr<Shader> shader;
switch (fPrimitiveType) {
@@ -218,33 +201,23 @@
shader = skstd::make_unique<GrCCConicShader>();
break;
}
- return Impl::kGeometryShader == fImpl ? this->createGSImpl(std::move(shader))
- : this->createVSImpl(std::move(shader));
+ return this->onCreateGLSLInstance(std::move(shader));
}
-void GrCCCoverageProcessor::Shader::emitFragmentCode(const GrCCCoverageProcessor& proc,
- GrGLSLFPFragmentBuilder* f,
- const char* skOutputColor,
- const char* skOutputCoverage) const {
+void GrCCCoverageProcessor::Shader::emitFragmentCode(
+ const GrCCCoverageProcessor& proc, GrGLSLFPFragmentBuilder* f, const char* skOutputColor,
+ const char* skOutputCoverage) const {
f->codeAppendf("half coverage = 0;");
this->onEmitFragmentCode(f, "coverage");
f->codeAppendf("%s.a = coverage;", skOutputColor);
f->codeAppendf("%s = half4(1);", skOutputCoverage);
}
-void GrCCCoverageProcessor::draw(GrOpFlushState* flushState, const GrPipeline& pipeline,
- const SkIRect scissorRects[], const GrMesh meshes[], int meshCount,
- const SkRect& drawBounds) const {
+void GrCCCoverageProcessor::draw(
+ GrOpFlushState* flushState, const GrPipeline& pipeline, const SkIRect scissorRects[],
+ const GrMesh meshes[], int meshCount, const SkRect& drawBounds) const {
GrPipeline::DynamicStateArrays dynamicStateArrays;
dynamicStateArrays.fScissorRects = scissorRects;
GrGpuRTCommandBuffer* cmdBuff = flushState->rtCommandBuffer();
cmdBuff->draw(*this, pipeline, nullptr, &dynamicStateArrays, meshes, meshCount, drawBounds);
-
- // Geometry shader backend draws primitives in two subpasses.
- if (Impl::kGeometryShader == fImpl) {
- SkASSERT(GSSubpass::kHulls == fGSSubpass);
- GrCCCoverageProcessor cornerProc(*this, GSSubpass::kCorners);
- cmdBuff->draw(cornerProc, pipeline, nullptr, &dynamicStateArrays, meshes, meshCount,
- drawBounds);
- }
}
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.h b/src/gpu/ccpr/GrCCCoverageProcessor.h
index bbf898e..9687bba 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor.h
+++ b/src/gpu/ccpr/GrCCCoverageProcessor.h
@@ -37,7 +37,7 @@
public:
enum class PrimitiveType {
kTriangles,
- kWeightedTriangles, // Triangles (from the tessellator) whose winding magnitude > 1.
+ kWeightedTriangles, // Triangles (from the tessellator) whose winding magnitude > 1.
kQuadratics,
kCubics,
kConics
@@ -68,16 +68,21 @@
void setW(const Sk2f& P0, const Sk2f& P1, const Sk2f& P2, const Sk2f& trans, float w);
};
- GrCCCoverageProcessor(GrResourceProvider* rp, PrimitiveType type)
- : INHERITED(kGrCCCoverageProcessor_ClassID)
- , fPrimitiveType(type)
- , fImpl(rp->caps()->shaderCaps()->geometryShaderSupport() ? Impl::kGeometryShader
- : Impl::kVertexShader) {
- if (Impl::kGeometryShader == fImpl) {
- this->initGS();
- } else {
- this->initVS(rp);
- }
+ virtual void reset(PrimitiveType, GrResourceProvider*) = 0;
+
+ PrimitiveType primitiveType() const { return fPrimitiveType; }
+
+ // Number of bezier points for curves, or 3 for triangles.
+ int numInputPoints() const { return PrimitiveType::kCubics == fPrimitiveType ? 4 : 3; }
+
+ bool isTriangles() const {
+ return PrimitiveType::kTriangles == fPrimitiveType ||
+ PrimitiveType::kWeightedTriangles == fPrimitiveType;
+ }
+
+ int hasInputWeight() const {
+ return PrimitiveType::kWeightedTriangles == fPrimitiveType ||
+ PrimitiveType::kConics == fPrimitiveType;
}
// GrPrimitiveProcessor overrides.
@@ -87,30 +92,32 @@
return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str());
}
#endif
- void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
- GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
+ void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
+ SkDEBUGCODE(this->getDebugBloatKey(b));
+ b->add32((int)fPrimitiveType);
+ }
+ GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
#ifdef SK_DEBUG
// Increases the 1/2 pixel AA bloat by a factor of debugBloat.
void enableDebugBloat(float debugBloat) { fDebugBloat = debugBloat; }
bool debugBloatEnabled() const { return fDebugBloat > 0; }
float debugBloat() const { SkASSERT(this->debugBloatEnabled()); return fDebugBloat; }
+ void getDebugBloatKey(GrProcessorKeyBuilder* b) const {
+ uint32_t bloatBits;
+ memcpy(&bloatBits, &fDebugBloat, 4);
+ b->add32(bloatBits);
+ }
#endif
// Appends a GrMesh that will draw the provided instances. The instanceBuffer must be an array
// of either TriPointInstance or QuadPointInstance, depending on this processor's RendererPass,
// with coordinates in the desired shape's final atlas-space position.
- void appendMesh(sk_sp<GrGpuBuffer> instanceBuffer, int instanceCount, int baseInstance,
- SkTArray<GrMesh>* out) const {
- if (Impl::kGeometryShader == fImpl) {
- this->appendGSMesh(std::move(instanceBuffer), instanceCount, baseInstance, out);
- } else {
- this->appendVSMesh(std::move(instanceBuffer), instanceCount, baseInstance, out);
- }
- }
+ virtual void appendMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount,
+ int baseInstance, SkTArray<GrMesh>* out) const = 0;
- void draw(GrOpFlushState*, const GrPipeline&, const SkIRect scissorRects[], const GrMesh[],
- int meshCount, const SkRect& drawBounds) const;
+ virtual void draw(GrOpFlushState*, const GrPipeline&, const SkIRect scissorRects[],
+ const GrMesh[], int meshCount, const SkRect& drawBounds) const;
// The Shader provides code to calculate each pixel's coverage in a RenderPass. It also
// provides details about shape-specific geometry.
@@ -197,82 +204,26 @@
return Scope::kGeoToFrag == varying.scope() ? varying.gsOut() : varying.vsOut();
}
- // Our friendship with GrGLSLShaderBuilder does not propogate to subclasses.
+ // Our friendship with GrGLSLShaderBuilder does not propagate to subclasses.
inline static SkString& AccessCodeString(GrGLSLShaderBuilder* s) { return s->code(); }
};
-private:
- class GSImpl;
- class GSTriangleHullImpl;
- class GSCurveHullImpl;
- class GSCornerImpl;
- class VSImpl;
- class TriangleShader;
-
+protected:
// Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
// accidentally bleed into neighbor pixels.
static constexpr float kAABloatRadius = 0.491111f;
- // Number of bezier points for curves, or 3 for triangles.
- int numInputPoints() const { return PrimitiveType::kCubics == fPrimitiveType ? 4 : 3; }
+ GrCCCoverageProcessor(ClassID classID) : INHERITED(classID) {}
- bool isTriangles() const {
- return PrimitiveType::kTriangles == fPrimitiveType ||
- PrimitiveType::kWeightedTriangles == fPrimitiveType;
- }
+ virtual GrGLSLPrimitiveProcessor* onCreateGLSLInstance(std::unique_ptr<Shader>) const = 0;
- int hasInputWeight() const {
- return PrimitiveType::kWeightedTriangles == fPrimitiveType ||
- PrimitiveType::kConics == fPrimitiveType;
- }
+ // Our friendship with GrGLSLShaderBuilder does not propagate to subclasses.
+ inline static SkString& AccessCodeString(GrGLSLShaderBuilder* s) { return s->code(); }
- enum class Impl : bool {
- kGeometryShader,
- kVertexShader
- };
-
- // Geometry shader backend draws primitives in two subpasses.
- enum class GSSubpass : bool {
- kHulls,
- kCorners
- };
-
- GrCCCoverageProcessor(const GrCCCoverageProcessor& proc, GSSubpass subpass)
- : INHERITED(kGrCCCoverageProcessor_ClassID)
- , fPrimitiveType(proc.fPrimitiveType)
- , fImpl(Impl::kGeometryShader)
- SkDEBUGCODE(, fDebugBloat(proc.fDebugBloat))
- , fGSSubpass(subpass) {
- SkASSERT(Impl::kGeometryShader == proc.fImpl);
- this->initGS();
- }
-
- void initGS();
- void initVS(GrResourceProvider*);
-
- void appendGSMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount, int baseInstance,
- SkTArray<GrMesh>* out) const;
- void appendVSMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount, int baseInstance,
- SkTArray<GrMesh>* out) const;
-
- GrGLSLPrimitiveProcessor* createGSImpl(std::unique_ptr<Shader>) const;
- GrGLSLPrimitiveProcessor* createVSImpl(std::unique_ptr<Shader>) const;
- // The type and meaning of this attribute depends on whether we're using VSImpl or GSImpl.
- Attribute fVertexAttribute;
-
- const PrimitiveType fPrimitiveType;
- const Impl fImpl;
+ PrimitiveType fPrimitiveType;
SkDEBUGCODE(float fDebugBloat = 0);
- // Used by GSImpl.
- const GSSubpass fGSSubpass = GSSubpass::kHulls;
-
- // Used by VSImpl.
- Attribute fInstanceAttributes[2];
- sk_sp<const GrGpuBuffer> fVSVertexBuffer;
- sk_sp<const GrGpuBuffer> fVSIndexBuffer;
- int fVSNumIndicesPerInstance;
- GrPrimitiveType fVSTriangleType;
+ class TriangleShader;
typedef GrGeometryProcessor INHERITED;
};
diff --git a/src/gpu/ccpr/GrCCFiller.cpp b/src/gpu/ccpr/GrCCFiller.cpp
index 311eb95..8e26c2f 100644
--- a/src/gpu/ccpr/GrCCFiller.cpp
+++ b/src/gpu/ccpr/GrCCFiller.cpp
@@ -459,54 +459,58 @@
return true;
}
-void GrCCFiller::drawFills(GrOpFlushState* flushState, BatchID batchID,
- const SkIRect& drawBounds) const {
+void GrCCFiller::drawFills(GrOpFlushState* flushState, GrCCCoverageProcessor* proc,
+ BatchID batchID, const SkIRect& drawBounds) const {
using PrimitiveType = GrCCCoverageProcessor::PrimitiveType;
SkASSERT(fInstanceBuffer);
+ GrResourceProvider* rp = flushState->resourceProvider();
const PrimitiveTallies& batchTotalCounts = fBatches[batchID].fTotalPrimitiveCounts;
GrPipeline pipeline(GrScissorTest::kEnabled, SkBlendMode::kPlus);
if (batchTotalCounts.fTriangles) {
- this->drawPrimitives(flushState, pipeline, batchID, PrimitiveType::kTriangles,
- &PrimitiveTallies::fTriangles, drawBounds);
+ proc->reset(PrimitiveType::kTriangles, rp);
+ this->drawPrimitives(
+ flushState, *proc, pipeline, batchID, &PrimitiveTallies::fTriangles, drawBounds);
}
if (batchTotalCounts.fWeightedTriangles) {
- this->drawPrimitives(flushState, pipeline, batchID, PrimitiveType::kWeightedTriangles,
- &PrimitiveTallies::fWeightedTriangles, drawBounds);
+ proc->reset(PrimitiveType::kWeightedTriangles, rp);
+ this->drawPrimitives(
+ flushState, *proc, pipeline, batchID, &PrimitiveTallies::fWeightedTriangles,
+ drawBounds);
}
if (batchTotalCounts.fQuadratics) {
- this->drawPrimitives(flushState, pipeline, batchID, PrimitiveType::kQuadratics,
- &PrimitiveTallies::fQuadratics, drawBounds);
+ proc->reset(PrimitiveType::kQuadratics, rp);
+ this->drawPrimitives(
+ flushState, *proc, pipeline, batchID, &PrimitiveTallies::fQuadratics, drawBounds);
}
if (batchTotalCounts.fCubics) {
- this->drawPrimitives(flushState, pipeline, batchID, PrimitiveType::kCubics,
- &PrimitiveTallies::fCubics, drawBounds);
+ proc->reset(PrimitiveType::kCubics, rp);
+ this->drawPrimitives(
+ flushState, *proc, pipeline, batchID, &PrimitiveTallies::fCubics, drawBounds);
}
if (batchTotalCounts.fConics) {
- this->drawPrimitives(flushState, pipeline, batchID, PrimitiveType::kConics,
- &PrimitiveTallies::fConics, drawBounds);
+ proc->reset(PrimitiveType::kConics, rp);
+ this->drawPrimitives(
+ flushState, *proc, pipeline, batchID, &PrimitiveTallies::fConics, drawBounds);
}
}
-void GrCCFiller::drawPrimitives(GrOpFlushState* flushState, const GrPipeline& pipeline,
- BatchID batchID, GrCCCoverageProcessor::PrimitiveType primitiveType,
- int PrimitiveTallies::*instanceType,
- const SkIRect& drawBounds) const {
+void GrCCFiller::drawPrimitives(
+ GrOpFlushState* flushState, const GrCCCoverageProcessor& proc, const GrPipeline& pipeline,
+ BatchID batchID, int PrimitiveTallies::*instanceType, const SkIRect& drawBounds) const {
SkASSERT(pipeline.isScissorEnabled());
// Don't call reset(), as that also resets the reserve count.
fMeshesScratchBuffer.pop_back_n(fMeshesScratchBuffer.count());
fScissorRectScratchBuffer.pop_back_n(fScissorRectScratchBuffer.count());
- GrCCCoverageProcessor proc(flushState->resourceProvider(), primitiveType);
-
SkASSERT(batchID > 0);
SkASSERT(batchID < fBatches.count());
const Batch& previousBatch = fBatches[batchID - 1];
diff --git a/src/gpu/ccpr/GrCCFiller.h b/src/gpu/ccpr/GrCCFiller.h
index 4eec190..4d61a2e 100644
--- a/src/gpu/ccpr/GrCCFiller.h
+++ b/src/gpu/ccpr/GrCCFiller.h
@@ -45,7 +45,8 @@
bool prepareToDraw(GrOnFlushResourceProvider*);
// Called after prepareToDraw(). Draws the given batch of path fills.
- void drawFills(GrOpFlushState*, BatchID, const SkIRect& drawBounds) const;
+ void drawFills(
+ GrOpFlushState*, GrCCCoverageProcessor*, BatchID, const SkIRect& drawBounds) const;
private:
static constexpr int kNumScissorModes = 2;
@@ -95,9 +96,8 @@
SkIRect fScissor;
};
- void drawPrimitives(GrOpFlushState*, const GrPipeline&, BatchID,
- GrCCCoverageProcessor::PrimitiveType, int PrimitiveTallies::*instanceType,
- const SkIRect& drawBounds) const;
+ void drawPrimitives(GrOpFlushState*, const GrCCCoverageProcessor&, const GrPipeline&, BatchID,
+ int PrimitiveTallies::*instanceType, const SkIRect& drawBounds) const;
GrCCFillGeometry fGeometry;
SkSTArray<32, PathInfo, true> fPathInfos;
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.cpp b/src/gpu/ccpr/GrCCPerFlushResources.cpp
index 18d3ee9..5b612be 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.cpp
+++ b/src/gpu/ccpr/GrCCPerFlushResources.cpp
@@ -17,6 +17,8 @@
#include "GrSurfaceContextPriv.h"
#include "SkMakeUnique.h"
#include "ccpr/GrCCPathCache.h"
+#include "ccpr/GrGSCoverageProcessor.h"
+#include "ccpr/GrVSCoverageProcessor.h"
using FillBatchID = GrCCFiller::BatchID;
using StrokeBatchID = GrCCStroker::BatchID;
@@ -100,7 +102,7 @@
};
// Renders coverage counts to a CCPR atlas using the resources' pre-filled GrCCPathParser.
-class RenderAtlasOp : public AtlasOp {
+template<typename ProcessorType> class RenderAtlasOp : public AtlasOp {
public:
DEFINE_OP_CLASS_ID
@@ -118,8 +120,9 @@
const char* name() const override { return "RenderAtlasOp (CCPR)"; }
void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
- fResources->filler().drawFills(flushState, fFillBatchID, fDrawBounds);
- fResources->stroker().drawStrokes(flushState, fStrokeBatchID, fDrawBounds);
+ ProcessorType proc;
+ fResources->filler().drawFills(flushState, &proc, fFillBatchID, fDrawBounds);
+ fResources->stroker().drawStrokes(flushState, &proc, fStrokeBatchID, fDrawBounds);
}
private:
@@ -495,9 +498,16 @@
}
if (auto rtc = atlas->makeRenderTargetContext(onFlushRP, std::move(backingTexture))) {
- auto op = RenderAtlasOp::Make(rtc->surfPriv().getContext(), sk_ref_sp(this),
- atlas->getFillBatchID(), atlas->getStrokeBatchID(),
- atlas->drawBounds());
+ std::unique_ptr<GrDrawOp> op;
+ if (onFlushRP->caps()->shaderCaps()->geometryShaderSupport()) {
+ op = RenderAtlasOp<GrGSCoverageProcessor>::Make(
+ rtc->surfPriv().getContext(), sk_ref_sp(this), atlas->getFillBatchID(),
+ atlas->getStrokeBatchID(), atlas->drawBounds());
+ } else {
+ op = RenderAtlasOp<GrVSCoverageProcessor>::Make(
+ rtc->surfPriv().getContext(), sk_ref_sp(this), atlas->getFillBatchID(),
+ atlas->getStrokeBatchID(), atlas->drawBounds());
+ }
rtc->addDrawOp(GrNoClip(), std::move(op));
out->push_back(std::move(rtc));
}
diff --git a/src/gpu/ccpr/GrCCStroker.cpp b/src/gpu/ccpr/GrCCStroker.cpp
index c097c0a..65f1c41 100644
--- a/src/gpu/ccpr/GrCCStroker.cpp
+++ b/src/gpu/ccpr/GrCCStroker.cpp
@@ -672,8 +672,8 @@
return true;
}
-void GrCCStroker::drawStrokes(GrOpFlushState* flushState, BatchID batchID,
- const SkIRect& drawBounds) const {
+void GrCCStroker::drawStrokes(GrOpFlushState* flushState, GrCCCoverageProcessor* proc,
+ BatchID batchID, const SkIRect& drawBounds) const {
using PrimitiveType = GrCCCoverageProcessor::PrimitiveType;
SkASSERT(fInstanceBuffer);
@@ -708,14 +708,14 @@
}
// Draw triangles.
- GrCCCoverageProcessor triProc(flushState->resourceProvider(), PrimitiveType::kTriangles);
+ proc->reset(PrimitiveType::kTriangles, flushState->resourceProvider());
this->drawConnectingGeometry<&InstanceTallies::fTriangles>(
- flushState, pipeline, triProc, batch, startIndices, startScissorSubBatch, drawBounds);
+ flushState, pipeline, *proc, batch, startIndices, startScissorSubBatch, drawBounds);
// Draw conics.
- GrCCCoverageProcessor conicProc(flushState->resourceProvider(), PrimitiveType::kConics);
+ proc->reset(PrimitiveType::kConics, flushState->resourceProvider());
this->drawConnectingGeometry<&InstanceTallies::fConics>(
- flushState, pipeline, conicProc, batch, startIndices, startScissorSubBatch, drawBounds);
+ flushState, pipeline, *proc, batch, startIndices, startScissorSubBatch, drawBounds);
}
void GrCCStroker::appendStrokeMeshesToBuffers(int numSegmentsLog2, const Batch& batch,
diff --git a/src/gpu/ccpr/GrCCStroker.h b/src/gpu/ccpr/GrCCStroker.h
index 6ddbd15..741f265 100644
--- a/src/gpu/ccpr/GrCCStroker.h
+++ b/src/gpu/ccpr/GrCCStroker.h
@@ -55,7 +55,8 @@
bool prepareToDraw(GrOnFlushResourceProvider*);
// Called after prepareToDraw(). Draws the given batch of path strokes.
- void drawStrokes(GrOpFlushState*, BatchID, const SkIRect& drawBounds) const;
+ void drawStrokes(
+ GrOpFlushState*, GrCCCoverageProcessor*, BatchID, const SkIRect& drawBounds) const;
private:
static constexpr int kNumScissorModes = 2;
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp b/src/gpu/ccpr/GrGSCoverageProcessor.cpp
similarity index 85%
rename from src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
rename to src/gpu/ccpr/GrGSCoverageProcessor.cpp
index 2c1d40a..2a3acc3 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp
+++ b/src/gpu/ccpr/GrGSCoverageProcessor.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "GrCCCoverageProcessor.h"
+#include "GrGSCoverageProcessor.h"
#include "GrMesh.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"
@@ -16,9 +16,9 @@
/**
* This class and its subclasses implement the coverage processor with geometry shaders.
*/
-class GrCCCoverageProcessor::GSImpl : public GrGLSLGeometryProcessor {
+class GrGSCoverageProcessor::Impl : public GrGLSLGeometryProcessor {
protected:
- GSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
+ Impl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}
virtual bool hasCoverage() const { return false; }
@@ -28,11 +28,11 @@
}
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
- const GrCCCoverageProcessor& proc = args.fGP.cast<GrCCCoverageProcessor>();
+ const GrGSCoverageProcessor& proc = args.fGP.cast<GrGSCoverageProcessor>();
// The vertex shader simply forwards transposed x or y values to the geometry shader.
SkASSERT(1 == proc.numVertexAttributes());
- gpArgs->fPositionVar = proc.fVertexAttribute.asShaderVar();
+ gpArgs->fPositionVar = proc.fInputXOrYValues.asShaderVar();
// Geometry shader.
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
@@ -45,9 +45,9 @@
fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
}
- void emitGeometryShader(const GrCCCoverageProcessor& proc,
- GrGLSLVaryingHandler* varyingHandler, GrGLSLGeometryBuilder* g,
- const char* rtAdjust) const {
+ void emitGeometryShader(
+ const GrGSCoverageProcessor& proc, GrGLSLVaryingHandler* varyingHandler,
+ GrGLSLGeometryBuilder* g, const char* rtAdjust) const {
int numInputPoints = proc.numInputPoints();
SkASSERT(3 == numInputPoints || 4 == numInputPoints);
@@ -59,9 +59,9 @@
GrShaderVar wind("wind", kHalf_GrSLType);
g->declareGlobal(wind);
Shader::CalcWind(proc, g, "pts", wind.c_str());
- if (PrimitiveType::kWeightedTriangles == proc.fPrimitiveType) {
+ if (PrimitiveType::kWeightedTriangles == proc.primitiveType()) {
SkASSERT(3 == numInputPoints);
- SkASSERT(kFloat4_GrVertexAttribType == proc.fVertexAttribute.cpuType());
+ SkASSERT(kFloat4_GrVertexAttribType == proc.fInputXOrYValues.cpuType());
g->codeAppendf("%s *= half(sk_in[0].sk_Position.w);", wind.c_str());
}
@@ -74,7 +74,7 @@
coverage = emitArgs.emplace_back("coverage", kHalf_GrSLType).c_str();
}
const char* cornerCoverage = nullptr;
- if (GSSubpass::kCorners == proc.fGSSubpass) {
+ if (Subpass::kCorners == proc.fSubpass) {
cornerCoverage = emitArgs.emplace_back("corner_coverage", kHalf2_GrSLType).c_str();
}
g->emitFunction(kVoid_GrSLType, "emitVertex", emitArgs.count(), emitArgs.begin(), [&]() {
@@ -103,11 +103,9 @@
this->onEmitGeometryShader(proc, g, wind, emitVertexFn.c_str());
}
- virtual void onEmitGeometryShader(const GrCCCoverageProcessor&, GrGLSLGeometryBuilder*,
+ virtual void onEmitGeometryShader(const GrGSCoverageProcessor&, GrGLSLGeometryBuilder*,
const GrShaderVar& wind, const char* emitVertexFn) const = 0;
- virtual ~GSImpl() {}
-
const std::unique_ptr<Shader> fShader;
typedef GrGLSLGeometryProcessor INHERITED;
@@ -121,15 +119,15 @@
* coverage ramp from -1 to 0. These edge coverage values convert jagged conservative raster edges
* into smooth, antialiased ones.
*
- * The final corners get touched up in a later step by GSTriangleCornerImpl.
+ * The final corners get touched up in a later step by TriangleCornerImpl.
*/
-class GrCCCoverageProcessor::GSTriangleHullImpl : public GrCCCoverageProcessor::GSImpl {
+class GrGSCoverageProcessor::TriangleHullImpl : public GrGSCoverageProcessor::Impl {
public:
- GSTriangleHullImpl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {}
+ TriangleHullImpl(std::unique_ptr<Shader> shader) : Impl(std::move(shader)) {}
bool hasCoverage() const override { return true; }
- void onEmitGeometryShader(const GrCCCoverageProcessor&, GrGLSLGeometryBuilder* g,
+ void onEmitGeometryShader(const GrGSCoverageProcessor&, GrGLSLGeometryBuilder* g,
const GrShaderVar& wind, const char* emitVertexFn) const override {
fShader->emitSetupCode(g, "pts", wind.c_str());
@@ -219,11 +217,11 @@
/**
* Generates a conservative raster around a convex quadrilateral that encloses a cubic or quadratic.
*/
-class GrCCCoverageProcessor::GSCurveHullImpl : public GrCCCoverageProcessor::GSImpl {
+class GrGSCoverageProcessor::CurveHullImpl : public GrGSCoverageProcessor::Impl {
public:
- GSCurveHullImpl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {}
+ CurveHullImpl(std::unique_ptr<Shader> shader) : Impl(std::move(shader)) {}
- void onEmitGeometryShader(const GrCCCoverageProcessor&, GrGLSLGeometryBuilder* g,
+ void onEmitGeometryShader(const GrGSCoverageProcessor&, GrGLSLGeometryBuilder* g,
const GrShaderVar& wind, const char* emitVertexFn) const override {
const char* hullPts = "pts";
fShader->emitSetupCode(g, "pts", wind.c_str(), &hullPts);
@@ -286,13 +284,13 @@
* Generates conservative rasters around corners (aka pixel-size boxes) and calculates
* coverage and attenuation ramps to fix up the coverage values written by the hulls.
*/
-class GrCCCoverageProcessor::GSCornerImpl : public GrCCCoverageProcessor::GSImpl {
+class GrGSCoverageProcessor::CornerImpl : public GrGSCoverageProcessor::Impl {
public:
- GSCornerImpl(std::unique_ptr<Shader> shader) : GSImpl(std::move(shader)) {}
+ CornerImpl(std::unique_ptr<Shader> shader) : Impl(std::move(shader)) {}
bool hasCoverage() const override { return true; }
- void onEmitGeometryShader(const GrCCCoverageProcessor& proc, GrGLSLGeometryBuilder* g,
+ void onEmitGeometryShader(const GrGSCoverageProcessor& proc, GrGLSLGeometryBuilder* g,
const GrShaderVar& wind, const char* emitVertexFn) const override {
fShader->emitSetupCode(g, "pts", wind.c_str());
@@ -375,45 +373,58 @@
}
};
-void GrCCCoverageProcessor::initGS() {
- SkASSERT(Impl::kGeometryShader == fImpl);
+void GrGSCoverageProcessor::reset(PrimitiveType primitiveType, GrResourceProvider*) {
+ fPrimitiveType = primitiveType; // This will affect the return values for numInputPoints, etc.
+
if (4 == this->numInputPoints() || this->hasInputWeight()) {
- fVertexAttribute =
+ fInputXOrYValues =
{"x_or_y_values", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
GR_STATIC_ASSERT(sizeof(QuadPointInstance) ==
2 * GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
GR_STATIC_ASSERT(offsetof(QuadPointInstance, fY) ==
GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
} else {
- fVertexAttribute =
+ fInputXOrYValues =
{"x_or_y_values", kFloat3_GrVertexAttribType, kFloat3_GrSLType};
GR_STATIC_ASSERT(sizeof(TriPointInstance) ==
2 * GrVertexAttribTypeSize(kFloat3_GrVertexAttribType));
GR_STATIC_ASSERT(offsetof(TriPointInstance, fY) ==
GrVertexAttribTypeSize(kFloat3_GrVertexAttribType));
}
- this->setVertexAttributes(&fVertexAttribute, 1);
- this->setWillUseGeoShader();
+
+ this->setVertexAttributes(&fInputXOrYValues, 1);
}
-void GrCCCoverageProcessor::appendGSMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount,
- int baseInstance, SkTArray<GrMesh>* out) const {
- // GSImpl doesn't actually make instanced draw calls. Instead, we feed transposed x,y point
- // values to the GPU in a regular vertex array and draw kLines (see initGS). Then, each vertex
- // invocation receives either the shape's x or y values as inputs, which it forwards to the
- // geometry shader.
- SkASSERT(Impl::kGeometryShader == fImpl);
+void GrGSCoverageProcessor::appendMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount,
+ int baseInstance, SkTArray<GrMesh>* out) const {
+ // We don't actually make instanced draw calls. Instead, we feed transposed x,y point values to
+ // the GPU in a regular vertex array and draw kLines (see initGS). Then, each vertex invocation
+ // receives either the shape's x or y values as inputs, which it forwards to the geometry
+ // shader.
GrMesh& mesh = out->emplace_back(GrPrimitiveType::kLines);
mesh.setNonIndexedNonInstanced(instanceCount * 2);
mesh.setVertexData(std::move(instanceBuffer), baseInstance * 2);
}
-GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createGSImpl(std::unique_ptr<Shader> shadr) const {
- if (GSSubpass::kHulls == fGSSubpass) {
- return this->isTriangles()
- ? (GSImpl*) new GSTriangleHullImpl(std::move(shadr))
- : (GSImpl*) new GSCurveHullImpl(std::move(shadr));
+void GrGSCoverageProcessor::draw(
+ GrOpFlushState* flushState, const GrPipeline& pipeline, const SkIRect scissorRects[],
+ const GrMesh meshes[], int meshCount, const SkRect& drawBounds) const {
+ // The geometry shader impl draws primitives in two subpasses: The first pass fills the interior
+ // and does edge AA. The second pass does touch up on corner pixels.
+ for (int i = 0; i < 2; ++i) {
+ fSubpass = (Subpass) i;
+ this->GrCCCoverageProcessor::draw(
+ flushState, pipeline, scissorRects, meshes, meshCount, drawBounds);
}
- SkASSERT(GSSubpass::kCorners == fGSSubpass);
- return new GSCornerImpl(std::move(shadr));
+}
+
+GrGLSLPrimitiveProcessor* GrGSCoverageProcessor::onCreateGLSLInstance(
+ std::unique_ptr<Shader> shader) const {
+ if (Subpass::kHulls == fSubpass) {
+ return this->isTriangles()
+ ? (Impl*) new TriangleHullImpl(std::move(shader))
+ : (Impl*) new CurveHullImpl(std::move(shader));
+ }
+ SkASSERT(Subpass::kCorners == fSubpass);
+ return new CornerImpl(std::move(shader));
}
diff --git a/src/gpu/ccpr/GrGSCoverageProcessor.h b/src/gpu/ccpr/GrGSCoverageProcessor.h
new file mode 100644
index 0000000..f517765
--- /dev/null
+++ b/src/gpu/ccpr/GrGSCoverageProcessor.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGSCoverageProcessor_DEFINED
+#define GrGSCoverageProcessor_DEFINED
+
+#include "ccpr/GrCCCoverageProcessor.h"
+
+/**
+ * This class implements GrCCCoverageProcessor with analytic coverage using geometry shaders.
+ */
+class GrGSCoverageProcessor : public GrCCCoverageProcessor {
+public:
+ GrGSCoverageProcessor() : GrCCCoverageProcessor(kGrGSCoverageProcessor_ClassID) {
+ this->setWillUseGeoShader();
+ }
+
+private:
+ void reset(PrimitiveType, GrResourceProvider*) override;
+
+ void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
+ SkDEBUGCODE(this->getDebugBloatKey(b));
+ b->add32(((int)fPrimitiveType << 16) | (int)fSubpass);
+ }
+
+ void appendMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount, int baseInstance,
+ SkTArray<GrMesh>* out) const override;
+
+ void draw(GrOpFlushState*, const GrPipeline&, const SkIRect scissorRects[], const GrMesh[],
+ int meshCount, const SkRect& drawBounds) const override;
+
+ GrGLSLPrimitiveProcessor* onCreateGLSLInstance(std::unique_ptr<Shader>) const override;
+
+ // The geometry shader impl draws primitives in two subpasses. The first pass fills the interior
+ // and does edge AA. The second pass does touch up on corner pixels.
+ enum class Subpass : bool {
+ kHulls,
+ kCorners
+ };
+
+ Attribute fInputXOrYValues;
+ mutable Subpass fSubpass = Subpass::kHulls;
+
+ class Impl;
+ class TriangleHullImpl;
+ class CurveHullImpl;
+ class CornerImpl;
+};
+
+#endif
diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp b/src/gpu/ccpr/GrVSCoverageProcessor.cpp
similarity index 79%
rename from src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
rename to src/gpu/ccpr/GrVSCoverageProcessor.cpp
index 10300f3..dc00b96 100644
--- a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp
+++ b/src/gpu/ccpr/GrVSCoverageProcessor.cpp
@@ -5,15 +5,15 @@
* found in the LICENSE file.
*/
-#include "GrCCCoverageProcessor.h"
+#include "GrVSCoverageProcessor.h"
#include "GrMesh.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"
// This class implements the coverage processor with vertex shaders.
-class GrCCCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor {
+class GrVSCoverageProcessor::Impl : public GrGLSLGeometryProcessor {
public:
- VSImpl(std::unique_ptr<Shader> shader, int numSides)
+ Impl(std::unique_ptr<Shader> shader, int numSides)
: fShader(std::move(shader)), fNumSides(numSides) {}
private:
@@ -248,28 +248,27 @@
// previous coverage values with ones that ramp to zero in the bloat vertices that fall outside the
// triangle.
//
-// Curves are drawn in two separate passes. Here we just draw a conservative raster around the input
-// points. The Shader takes care of everything else for now. The final curve corners get touched up
-// in a later step by VSCornerImpl.
-void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
- const GrCCCoverageProcessor& proc = args.fGP.cast<GrCCCoverageProcessor>();
+// Curve shaders handle the opposite edge and corners on their own. For curves we just generate a
+// conservative raster here and the shader does the rest.
+void GrVSCoverageProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
+ const GrVSCoverageProcessor& proc = args.fGP.cast<GrVSCoverageProcessor>();
GrGLSLVertexBuilder* v = args.fVertBuilder;
int numInputPoints = proc.numInputPoints();
int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3;
const char* swizzle = (4 == inputWidth) ? "xyzw" : "xyz";
v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s.%s, %s.%s));", inputWidth, inputWidth,
- proc.fInstanceAttributes[kInstanceAttribIdx_X].name(), swizzle,
- proc.fInstanceAttributes[kInstanceAttribIdx_Y].name(), swizzle);
+ proc.fInputXAndYValues[kInstanceAttribIdx_X].name(), swizzle,
+ proc.fInputXAndYValues[kInstanceAttribIdx_Y].name(), swizzle);
v->codeAppend ("half wind;");
Shader::CalcWind(proc, v, "pts", "wind");
if (PrimitiveType::kWeightedTriangles == proc.fPrimitiveType) {
SkASSERT(3 == numInputPoints);
SkASSERT(kFloat4_GrVertexAttribType ==
- proc.fInstanceAttributes[kInstanceAttribIdx_X].cpuType());
+ proc.fInputXAndYValues[kInstanceAttribIdx_X].cpuType());
v->codeAppendf("wind *= half(%s.w);",
- proc.fInstanceAttributes[kInstanceAttribIdx_X].name());
+ proc.fInputXAndYValues[kInstanceAttribIdx_X].name());
}
float bloat = kAABloatRadius;
@@ -285,12 +284,12 @@
// Reverse all indices if the wind is counter-clockwise: [0, 1, 2] -> [2, 1, 0].
v->codeAppendf("int clockwise_indices = wind > 0 ? %s : 0x%x - %s;",
- proc.fVertexAttribute.name(),
+ proc.fPerVertexData.name(),
((fNumSides - 1) << kVertexData_LeftNeighborIdShift) |
((fNumSides - 1) << kVertexData_RightNeighborIdShift) |
(((1 << kVertexData_RightNeighborIdShift) - 1) ^ 3) |
(fNumSides - 1),
- proc.fVertexAttribute.name());
+ proc.fPerVertexData.name());
// Here we generate conservative raster geometry for the input polygon. It is the convex
// hull of N pixel-size boxes, one centered on each the input points. Each corner has three
@@ -323,7 +322,7 @@
v->codeAppend ("rightdir = (float2(0) != rightdir) ? normalize(rightdir) : float2(1, 0);");
v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner?
- proc.fVertexAttribute.name(), kVertexData_IsCornerBit);
+ proc.fPerVertexData.name(), kVertexData_IsCornerBit);
// In corner boxes, all 4 coverage values will not map linearly.
// Therefore it is important to align the box so its diagonal shared
@@ -342,7 +341,7 @@
// continue rotating 90 degrees clockwise until we reach the desired raster vertex for this
// invocation. Corners with less than 3 corresponding raster vertices will result in
// redundant vertices and degenerate triangles.
- v->codeAppendf("int bloatidx = (%s >> %i) & 3;", proc.fVertexAttribute.name(),
+ v->codeAppendf("int bloatidx = (%s >> %i) & 3;", proc.fPerVertexData.name(),
kVertexData_BloatIdxShift);
v->codeAppend ("switch (bloatidx) {");
v->codeAppend ( "case 3:");
@@ -377,12 +376,12 @@
v->codeAppend ("}");
v->codeAppendf("if (0 != (%s & %i)) {", // Are we an edge?
- proc.fVertexAttribute.name(), kVertexData_IsEdgeBit);
+ proc.fPerVertexData.name(), kVertexData_IsEdgeBit);
v->codeAppend ( "coverage = left_coverage;");
v->codeAppend ("}");
v->codeAppendf("if (0 != (%s & %i)) {", // Invert coverage?
- proc.fVertexAttribute.name(),
+ proc.fPerVertexData.name(),
kVertexData_InvertNegativeCoverageBit);
v->codeAppend ( "coverage = -1 - coverage;");
v->codeAppend ("}");
@@ -392,7 +391,7 @@
v->codeAppend ("half2 corner_coverage = half2(0);");
v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner?
- proc.fVertexAttribute.name(), kVertexData_IsCornerBit);
+ proc.fPerVertexData.name(), kVertexData_IsCornerBit);
// We use coverage=-1 to erase what the hull geometry wrote.
//
// In the context of curves, this effectively means "wind = -wind" and
@@ -432,7 +431,7 @@
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
v->codeAppend ("coverage *= wind;");
v->codeAppend ("corner_coverage.x *= wind;");
- fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &v->code(),
+ fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &AccessCodeString(v),
gpArgs->fPositionVar.c_str(), "coverage", "corner_coverage");
varyingHandler->emitAttributes(proc);
@@ -442,31 +441,28 @@
fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
}
-void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) {
- SkASSERT(Impl::kVertexShader == fImpl);
+void GrVSCoverageProcessor::reset(PrimitiveType primitiveType, GrResourceProvider* rp) {
const GrCaps& caps = *rp->caps();
+ fPrimitiveType = primitiveType;
switch (fPrimitiveType) {
case PrimitiveType::kTriangles:
case PrimitiveType::kWeightedTriangles: {
GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey);
- fVSVertexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kVertex,
- sizeof(kTriangleVertices),
- kTriangleVertices,
- gTriangleVertexBufferKey);
+ fVertexBuffer = rp->findOrMakeStaticBuffer(
+ GrGpuBufferType::kVertex, sizeof(kTriangleVertices), kTriangleVertices,
+ gTriangleVertexBufferKey);
GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey);
if (caps.usePrimitiveRestart()) {
- fVSIndexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kIndex,
- sizeof(kTriangleIndicesAsStrips),
- kTriangleIndicesAsStrips,
- gTriangleIndexBufferKey);
- fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsStrips);
+ fIndexBuffer = rp->findOrMakeStaticBuffer(
+ GrGpuBufferType::kIndex, sizeof(kTriangleIndicesAsStrips),
+ kTriangleIndicesAsStrips, gTriangleIndexBufferKey);
+ fNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsStrips);
} else {
- fVSIndexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kIndex,
- sizeof(kTriangleIndicesAsTris),
- kTriangleIndicesAsTris,
- gTriangleIndexBufferKey);
- fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsTris);
+ fIndexBuffer = rp->findOrMakeStaticBuffer(
+ GrGpuBufferType::kIndex, sizeof(kTriangleIndicesAsTris),
+ kTriangleIndicesAsTris, gTriangleIndexBufferKey);
+ fNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsTris);
}
break;
}
@@ -475,22 +471,20 @@
case PrimitiveType::kCubics:
case PrimitiveType::kConics: {
GR_DEFINE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey);
- fVSVertexBuffer =
- rp->findOrMakeStaticBuffer(GrGpuBufferType::kVertex, sizeof(kCurveVertices),
- kCurveVertices, gCurveVertexBufferKey);
+ fVertexBuffer = rp->findOrMakeStaticBuffer(
+ GrGpuBufferType::kVertex, sizeof(kCurveVertices), kCurveVertices,
+ gCurveVertexBufferKey);
GR_DEFINE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey);
if (caps.usePrimitiveRestart()) {
- fVSIndexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kIndex,
- sizeof(kCurveIndicesAsStrips),
- kCurveIndicesAsStrips,
- gCurveIndexBufferKey);
- fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsStrips);
+ fIndexBuffer = rp->findOrMakeStaticBuffer(
+ GrGpuBufferType::kIndex, sizeof(kCurveIndicesAsStrips),
+ kCurveIndicesAsStrips, gCurveIndexBufferKey);
+ fNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsStrips);
} else {
- fVSIndexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kIndex,
- sizeof(kCurveIndicesAsTris),
- kCurveIndicesAsTris,
- gCurveIndexBufferKey);
- fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsTris);
+ fIndexBuffer = rp->findOrMakeStaticBuffer(
+ GrGpuBufferType::kIndex, sizeof(kCurveIndicesAsTris), kCurveIndicesAsTris,
+ gCurveIndexBufferKey);
+ fNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsTris);
}
break;
}
@@ -515,39 +509,39 @@
xyAttribType = kFloat3_GrVertexAttribType;
xySLType = kFloat3_GrSLType;
}
- fInstanceAttributes[kInstanceAttribIdx_X] = {"X", xyAttribType, xySLType};
- fInstanceAttributes[kInstanceAttribIdx_Y] = {"Y", xyAttribType, xySLType};
- this->setInstanceAttributes(fInstanceAttributes, 2);
- fVertexAttribute = {"vertexdata", kInt_GrVertexAttribType, kInt_GrSLType};
- this->setVertexAttributes(&fVertexAttribute, 1);
+ fInputXAndYValues[kInstanceAttribIdx_X] = {"X", xyAttribType, xySLType};
+ fInputXAndYValues[kInstanceAttribIdx_Y] = {"Y", xyAttribType, xySLType};
+ this->setInstanceAttributes(fInputXAndYValues, 2);
+ fPerVertexData = {"vertexdata", kInt_GrVertexAttribType, kInt_GrSLType};
+ this->setVertexAttributes(&fPerVertexData, 1);
if (caps.usePrimitiveRestart()) {
- fVSTriangleType = GrPrimitiveType::kTriangleStrip;
+ fTriangleType = GrPrimitiveType::kTriangleStrip;
} else {
- fVSTriangleType = GrPrimitiveType::kTriangles;
+ fTriangleType = GrPrimitiveType::kTriangles;
}
}
-void GrCCCoverageProcessor::appendVSMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount,
- int baseInstance, SkTArray<GrMesh>* out) const {
- SkASSERT(Impl::kVertexShader == fImpl);
- GrMesh& mesh = out->emplace_back(fVSTriangleType);
- auto primitiveRestart = GrPrimitiveRestart(GrPrimitiveType::kTriangleStrip == fVSTriangleType);
- mesh.setIndexedInstanced(fVSIndexBuffer, fVSNumIndicesPerInstance, std::move(instanceBuffer),
+void GrVSCoverageProcessor::appendMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount,
+ int baseInstance, SkTArray<GrMesh>* out) const {
+ GrMesh& mesh = out->emplace_back(fTriangleType);
+ auto primitiveRestart = GrPrimitiveRestart(GrPrimitiveType::kTriangleStrip == fTriangleType);
+ mesh.setIndexedInstanced(fIndexBuffer, fNumIndicesPerInstance, std::move(instanceBuffer),
instanceCount, baseInstance, primitiveRestart);
- mesh.setVertexData(fVSVertexBuffer, 0);
+ mesh.setVertexData(fVertexBuffer, 0);
}
-GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shadr) const {
+GrGLSLPrimitiveProcessor* GrVSCoverageProcessor::onCreateGLSLInstance(
+ std::unique_ptr<Shader> shader) const {
switch (fPrimitiveType) {
case PrimitiveType::kTriangles:
case PrimitiveType::kWeightedTriangles:
- return new VSImpl(std::move(shadr), 3);
+ return new Impl(std::move(shader), 3);
case PrimitiveType::kQuadratics:
case PrimitiveType::kCubics:
case PrimitiveType::kConics:
- return new VSImpl(std::move(shadr), 4);
+ return new Impl(std::move(shader), 4);
}
- SK_ABORT("Invalid RenderPass");
+ SK_ABORT("Invalid PrimitiveType");
return nullptr;
}
diff --git a/src/gpu/ccpr/GrVSCoverageProcessor.h b/src/gpu/ccpr/GrVSCoverageProcessor.h
new file mode 100644
index 0000000..e278548
--- /dev/null
+++ b/src/gpu/ccpr/GrVSCoverageProcessor.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrVSCoverageProcessor_DEFINED
+#define GrVSCoverageProcessor_DEFINED
+
+#include "ccpr/GrCCCoverageProcessor.h"
+
+/**
+ * This class implements GrCCCoverageProcessor with analytic coverage using vertex shaders.
+ */
+class GrVSCoverageProcessor : public GrCCCoverageProcessor {
+public:
+ GrVSCoverageProcessor() : GrCCCoverageProcessor(kGrVSCoverageProcessor_ClassID) {}
+
+private:
+ void reset(PrimitiveType, GrResourceProvider*) override;
+
+ void appendMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount, int baseInstance,
+ SkTArray<GrMesh>* out) const override;
+
+ GrGLSLPrimitiveProcessor* onCreateGLSLInstance(std::unique_ptr<Shader>) const override;
+
+ Attribute fPerVertexData;
+ Attribute fInputXAndYValues[2];
+ sk_sp<const GrGpuBuffer> fVertexBuffer;
+ sk_sp<const GrGpuBuffer> fIndexBuffer;
+ int fNumIndicesPerInstance;
+ GrPrimitiveType fTriangleType;
+
+ class Impl;
+};
+
+#endif