aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrPathRendererChain.cpp6
-rw-r--r--src/gpu/batches/GrDefaultPathRenderer.cpp124
-rw-r--r--src/gpu/batches/GrDefaultPathRenderer.h1
-rw-r--r--src/gpu/batches/GrMSAAPathRenderer.cpp745
-rw-r--r--src/gpu/batches/GrMSAAPathRenderer.h35
-rw-r--r--src/gpu/batches/GrPathStencilSettings.h131
6 files changed, 125 insertions, 917 deletions
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index e19a134467..098d8fb2d9 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -20,10 +20,9 @@
#include "batches/GrAALinearizingConvexPathRenderer.h"
#include "batches/GrDashLinePathRenderer.h"
#include "batches/GrDefaultPathRenderer.h"
-#include "batches/GrMSAAPathRenderer.h"
-#include "batches/GrPLSPathRenderer.h"
#include "batches/GrStencilAndCoverPathRenderer.h"
#include "batches/GrTessellatingPathRenderer.h"
+#include "batches/GrPLSPathRenderer.h"
GrPathRendererChain::GrPathRendererChain(GrContext* context) {
const GrCaps& caps = *context->caps();
@@ -33,9 +32,6 @@ GrPathRendererChain::GrPathRendererChain(GrContext* context) {
caps)) {
this->addPathRenderer(pr)->unref();
}
- if (caps.sampleShadingSupport()) {
- this->addPathRenderer(new GrMSAAPathRenderer)->unref();
- }
this->addPathRenderer(new GrTessellatingPathRenderer)->unref();
this->addPathRenderer(new GrAAHairLinePathRenderer)->unref();
this->addPathRenderer(new GrAAConvexPathRenderer)->unref();
diff --git a/src/gpu/batches/GrDefaultPathRenderer.cpp b/src/gpu/batches/GrDefaultPathRenderer.cpp
index 708bcd7234..94508b130b 100644
--- a/src/gpu/batches/GrDefaultPathRenderer.cpp
+++ b/src/gpu/batches/GrDefaultPathRenderer.cpp
@@ -29,6 +29,130 @@ GrDefaultPathRenderer::GrDefaultPathRenderer(bool separateStencilSupport,
, fStencilWrapOps(stencilWrapOpsSupport) {
}
+
+////////////////////////////////////////////////////////////////////////////////
+// Stencil rules for paths
+
+////// Even/Odd
+
+GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
+ kInvert_StencilOp,
+ kKeep_StencilOp,
+ kAlwaysIfInClip_StencilFunc,
+ 0xffff,
+ 0xffff,
+ 0xffff);
+
+// ok not to check clip b/c stencil pass only wrote inside clip
+GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
+ kZero_StencilOp,
+ kZero_StencilOp,
+ kNotEqual_StencilFunc,
+ 0xffff,
+ 0x0000,
+ 0xffff);
+
+// have to check clip b/c outside clip will always be zero.
+GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
+ kZero_StencilOp,
+ kZero_StencilOp,
+ kEqualIfInClip_StencilFunc,
+ 0xffff,
+ 0x0000,
+ 0xffff);
+
+////// Winding
+
+// when we have separate stencil we increment front faces / decrement back faces
+// when we don't have wrap incr and decr we use the stencil test to simulate
+// them.
+
+GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
+ kIncWrap_StencilOp, kDecWrap_StencilOp,
+ kKeep_StencilOp, kKeep_StencilOp,
+ kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
+ 0xffff, 0xffff,
+ 0xffff, 0xffff,
+ 0xffff, 0xffff);
+
+// if inc'ing the max value, invert to make 0
+// if dec'ing zero invert to make all ones.
+// we can't avoid touching the stencil on both passing and
+// failing, so we can't resctrict ourselves to the clip.
+GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
+ kInvert_StencilOp, kInvert_StencilOp,
+ kIncClamp_StencilOp, kDecClamp_StencilOp,
+ kEqual_StencilFunc, kEqual_StencilFunc,
+ 0xffff, 0xffff,
+ 0xffff, 0x0000,
+ 0xffff, 0xffff);
+
+// When there are no separate faces we do two passes to setup the winding rule
+// stencil. First we draw the front faces and inc, then we draw the back faces
+// and dec. These are same as the above two split into the incrementing and
+// decrementing passes.
+GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
+ kIncWrap_StencilOp,
+ kKeep_StencilOp,
+ kAlwaysIfInClip_StencilFunc,
+ 0xffff,
+ 0xffff,
+ 0xffff);
+
+GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
+ kDecWrap_StencilOp,
+ kKeep_StencilOp,
+ kAlwaysIfInClip_StencilFunc,
+ 0xffff,
+ 0xffff,
+ 0xffff);
+
+GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
+ kInvert_StencilOp,
+ kIncClamp_StencilOp,
+ kEqual_StencilFunc,
+ 0xffff,
+ 0xffff,
+ 0xffff);
+
+GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
+ kInvert_StencilOp,
+ kDecClamp_StencilOp,
+ kEqual_StencilFunc,
+ 0xffff,
+ 0x0000,
+ 0xffff);
+
+// Color passes are the same whether we use the two-sided stencil or two passes
+
+GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
+ kZero_StencilOp,
+ kZero_StencilOp,
+ kNonZeroIfInClip_StencilFunc,
+ 0xffff,
+ 0x0000,
+ 0xffff);
+
+GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
+ kZero_StencilOp,
+ kZero_StencilOp,
+ kEqualIfInClip_StencilFunc,
+ 0xffff,
+ 0x0000,
+ 0xffff);
+
+////// Normal render to stencil
+
+// Sometimes the default path renderer can draw a path directly to the stencil
+// buffer without having to first resolve the interior / exterior.
+GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
+ kZero_StencilOp,
+ kIncClamp_StencilOp,
+ kAlwaysIfInClip_StencilFunc,
+ 0xffff,
+ 0x0000,
+ 0xffff);
+
////////////////////////////////////////////////////////////////////////////////
// Helpers for drawPath
diff --git a/src/gpu/batches/GrDefaultPathRenderer.h b/src/gpu/batches/GrDefaultPathRenderer.h
index 9973c2be5e..8a2ce7b9c4 100644
--- a/src/gpu/batches/GrDefaultPathRenderer.h
+++ b/src/gpu/batches/GrDefaultPathRenderer.h
@@ -9,7 +9,6 @@
#define GrDefaultPathRenderer_DEFINED
#include "GrPathRenderer.h"
-#include "GrPathStencilSettings.h"
#include "SkTypes.h"
/**
diff --git a/src/gpu/batches/GrMSAAPathRenderer.cpp b/src/gpu/batches/GrMSAAPathRenderer.cpp
deleted file mode 100644
index 988952822a..0000000000
--- a/src/gpu/batches/GrMSAAPathRenderer.cpp
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrMSAAPathRenderer.h"
-
-#include "GrBatchFlushState.h"
-#include "GrDefaultGeoProcFactory.h"
-#include "GrPathStencilSettings.h"
-#include "GrPathUtils.h"
-#include "GrPipelineBuilder.h"
-#include "GrMesh.h"
-#include "SkGeometry.h"
-#include "SkTraceEvent.h"
-#include "glsl/GrGLSLGeometryProcessor.h"
-#include "glsl/GrGLSLFragmentShaderBuilder.h"
-#include "glsl/GrGLSLVertexShaderBuilder.h"
-#include "glsl/GrGLSLProgramDataManager.h"
-#include "glsl/GrGLSLUtil.h"
-#include "gl/GrGLVaryingHandler.h"
-#include "batches/GrRectBatchFactory.h"
-#include "batches/GrVertexBatch.h"
-
-static const float kTolerance = 0.5f;
-
-////////////////////////////////////////////////////////////////////////////////
-// Helpers for drawPath
-
-static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& stroke) {
- if (!path.isInverseFillType()) {
- return path.isConvex();
- }
- return false;
-}
-
-GrPathRenderer::StencilSupport
-GrMSAAPathRenderer::onGetStencilSupport(const SkPath& path, const GrStrokeInfo& stroke) const {
- if (single_pass_path(path, stroke)) {
- return GrPathRenderer::kNoRestriction_StencilSupport;
- } else {
- return GrPathRenderer::kStencilOnly_StencilSupport;
- }
-}
-
-struct MSAALineVertices {
- struct Vertex {
- SkPoint fPosition;
- SkColor fColor;
- };
- Vertex* vertices;
- Vertex* nextVertex;
-#ifdef SK_DEBUG
- Vertex* verticesEnd;
-#endif
- uint16_t* indices;
- uint16_t* nextIndex;
-};
-
-struct MSAAQuadVertices {
- struct Vertex {
- SkPoint fPosition;
- SkPoint fUV;
- SkColor fColor;
- };
- Vertex* vertices;
- Vertex* nextVertex;
-#ifdef SK_DEBUG
- Vertex* verticesEnd;
-#endif
- uint16_t* indices;
- uint16_t* nextIndex;
-};
-
-static inline void append_contour_edge_indices(uint16_t fanCenterIdx,
- uint16_t edgeV0Idx,
- MSAALineVertices& lines) {
- *(lines.nextIndex++) = fanCenterIdx;
- *(lines.nextIndex++) = edgeV0Idx;
- *(lines.nextIndex++) = edgeV0Idx + 1;
-}
-
-static inline void add_quad(MSAALineVertices& lines, MSAAQuadVertices& quads, const SkPoint pts[],
- SkColor color, bool indexed, uint16_t subpathLineIdxStart) {
- SkASSERT(lines.nextVertex < lines.verticesEnd);
- *lines.nextVertex = { pts[2], color };
- if (indexed) {
- int prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1);
- if (prevIdx > subpathLineIdxStart) {
- append_contour_edge_indices(subpathLineIdxStart, prevIdx, lines);
- }
- }
- lines.nextVertex++;
-
- SkASSERT(quads.nextVertex + 2 < quads.verticesEnd);
- // the texture coordinates are drawn from the Loop-Blinn rendering algorithm
- *(quads.nextVertex++) = { pts[0], SkPoint::Make(0.0, 0.0), color };
- *(quads.nextVertex++) = { pts[1], SkPoint::Make(0.5, 0.0), color };
- *(quads.nextVertex++) = { pts[2], SkPoint::Make(1.0, 1.0), color };
- if (indexed) {
- uint16_t offset = (uint16_t) (quads.nextVertex - quads.vertices) - 3;
- *(quads.nextIndex++) = offset++;
- *(quads.nextIndex++) = offset++;
- *(quads.nextIndex++) = offset++;
- }
-}
-
-class MSAAQuadProcessor : public GrGeometryProcessor {
-public:
- static GrGeometryProcessor* Create(const SkMatrix& viewMatrix) {
- return new MSAAQuadProcessor(viewMatrix);
- }
-
- virtual ~MSAAQuadProcessor() {}
-
- const char* name() const override { return "MSAAQuadProcessor"; }
-
- const Attribute* inPosition() const { return fInPosition; }
- const Attribute* inUV() const { return fInUV; }
- const Attribute* inColor() const { return fInColor; }
- const SkMatrix& viewMatrix() const { return fViewMatrix; }
- const SkMatrix& localMatrix() const { return SkMatrix::I(); }
-
- class GLSLProcessor : public GrGLSLGeometryProcessor {
- public:
- GLSLProcessor(const GrGeometryProcessor& qpr) {}
-
- void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
- const MSAAQuadProcessor& qp = args.fGP.cast<MSAAQuadProcessor>();
- GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
- GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-
- // emit attributes
- varyingHandler->emitAttributes(qp);
- varyingHandler->addPassThroughAttribute(qp.inColor(), args.fOutputColor);
-
- GrGLSLVertToFrag uv(kVec2f_GrSLType);
- varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qp.inUV()->fName);
-
- // Setup position
- this->setupPosition(vsBuilder, uniformHandler, gpArgs, qp.inPosition()->fName,
- qp.viewMatrix(), &fViewMatrixUniform);
-
- // emit transforms
- this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
- qp.inPosition()->fName, SkMatrix::I(), args.fTransformsIn,
- args.fTransformsOut);
-
- GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
- fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(),
- uv.fsIn());
- fsBuilder->codeAppendf("%s = vec4(1.0);", args.fOutputCoverage);
- }
-
- static inline void GenKey(const GrGeometryProcessor& gp,
- const GrGLSLCaps&,
- GrProcessorKeyBuilder* b) {
- const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
- uint32_t key = 0;
- key |= qp.viewMatrix().hasPerspective() ? 0x1 : 0x0;
- key |= qp.viewMatrix().isIdentity() ? 0x2: 0x0;
- b->add32(key);
- }
-
- virtual void setData(const GrGLSLProgramDataManager& pdman,
- const GrPrimitiveProcessor& gp) override {
- const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
- if (!qp.viewMatrix().isIdentity()) {
- float viewMatrix[3 * 3];
- GrGLSLGetMatrix<3>(viewMatrix, qp.viewMatrix());
- pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
- }
- }
-
- void setTransformData(const GrPrimitiveProcessor& primProc,
- const GrGLSLProgramDataManager& pdman,
- int index,
- const SkTArray<const GrCoordTransform*, true>& transforms) override {
- this->setTransformDataHelper<MSAAQuadProcessor>(primProc, pdman, index, transforms);
- }
-
- private:
- typedef GrGLSLGeometryProcessor INHERITED;
-
- UniformHandle fViewMatrixUniform;
- };
-
- virtual void getGLSLProcessorKey(const GrGLSLCaps& caps,
- GrProcessorKeyBuilder* b) const override {
- GLSLProcessor::GenKey(*this, caps, b);
- }
-
- virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrGLSLCaps&) const override {
- return new GLSLProcessor(*this);
- }
-
-private:
- MSAAQuadProcessor(const SkMatrix& viewMatrix)
- : fViewMatrix(viewMatrix) {
- this->initClassID<MSAAQuadProcessor>();
- fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInUV = &this->addVertexAttrib(Attribute("inUV", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
- this->setSampleShading(1.0f);
- }
-
- const Attribute* fInPosition;
- const Attribute* fInUV;
- const Attribute* fInColor;
- SkMatrix fViewMatrix;
-
- GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
-
- typedef GrGeometryProcessor INHERITED;
-};
-
-class MSAAPathBatch : public GrVertexBatch {
-public:
- DEFINE_BATCH_CLASS_ID
-
- struct Geometry {
- GrColor fColor;
- SkPath fPath;
- SkScalar fTolerance;
- };
-
- static MSAAPathBatch* Create(const Geometry& geometry, const SkMatrix& viewMatrix,
- const SkRect& devBounds) {
- return new MSAAPathBatch(geometry, viewMatrix, devBounds);
- }
-
- const char* name() const override { return "MSAAPathBatch"; }
-
- 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);
- coverage->setKnownSingleComponent(0xff);
- }
-
- bool isValid() const {
- return !fIsIndexed || fMaxLineIndices <= SK_MaxU16;
- }
-
-private:
- void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
- // Handle any color overrides
- if (!overrides.readsColor()) {
- fGeoData[0].fColor = GrColor_ILLEGAL;
- }
- overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
- }
-
- void computeWorstCasePointCount(const SkPath& path, int* subpaths, SkScalar tol,
- int* outLinePointCount, int* outQuadPointCount) const {
- int linePointCount = 0;
- int quadPointCount = 0;
- *subpaths = 1;
-
- bool first = true;
-
- SkPath::Iter iter(path, false);
- SkPath::Verb verb;
-
- SkPoint pts[4];
- while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
- switch (verb) {
- case SkPath::kLine_Verb:
- linePointCount += 1;
- break;
- case SkPath::kConic_Verb: {
- SkScalar weight = iter.conicWeight();
- SkAutoConicToQuads converter;
- converter.computeQuads(pts, weight, kTolerance);
- int quadPts = converter.countQuads();
- linePointCount += quadPts;
- quadPointCount += 3 * quadPts;
- }
- case SkPath::kQuad_Verb:
- linePointCount += 1;
- quadPointCount += 3;
- break;
- case SkPath::kCubic_Verb: {
- SkSTArray<15, SkPoint, true> quadPts;
- GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts);
- int count = quadPts.count();
- linePointCount += count / 3;
- quadPointCount += count;
- break;
- }
- case SkPath::kMove_Verb:
- linePointCount += 1;
- if (!first) {
- ++(*subpaths);
- }
- break;
- default:
- break;
- }
- first = false;
- }
- *outLinePointCount = linePointCount;
- *outQuadPointCount = quadPointCount;
- }
-
- void onPrepareDraws(Target* target) const override {
- SkASSERT(this->isValid());
- if (fMaxLineVertices == 0) {
- SkASSERT(fMaxQuadVertices == 0);
- return;
- }
-
- GrPrimitiveType primitiveType = fIsIndexed ? kTriangles_GrPrimitiveType
- : kTriangleFan_GrPrimitiveType;
-
- // allocate vertex / index buffers
- const GrBuffer* lineVertexBuffer;
- int firstLineVertex;
- MSAALineVertices lines;
- size_t lineVertexStride = sizeof(MSAALineVertices::Vertex);
- lines.vertices = (MSAALineVertices::Vertex*) target->makeVertexSpace(lineVertexStride,
- fMaxLineVertices,
- &lineVertexBuffer,
- &firstLineVertex);
- if (!lines.vertices) {
- SkDebugf("Could not allocate vertices\n");
- return;
- }
- lines.nextVertex = lines.vertices;
- SkDEBUGCODE(lines.verticesEnd = lines.vertices + fMaxLineVertices;)
-
- MSAAQuadVertices quads;
- size_t quadVertexStride = sizeof(MSAAQuadVertices::Vertex);
- SkAutoFree quadVertexPtr(sk_malloc_throw(fMaxQuadVertices * quadVertexStride));
- quads.vertices = (MSAAQuadVertices::Vertex*) quadVertexPtr.get();
- quads.nextVertex = quads.vertices;
- SkDEBUGCODE(quads.verticesEnd = quads.vertices + fMaxQuadVertices;)
-
- const GrBuffer* lineIndexBuffer = nullptr;
- int firstLineIndex;
- if (fIsIndexed) {
- lines.indices = target->makeIndexSpace(fMaxLineIndices, &lineIndexBuffer,
- &firstLineIndex);
- if (!lines.indices) {
- SkDebugf("Could not allocate indices\n");
- return;
- }
- lines.nextIndex = lines.indices;
- } else {
- lines.indices = nullptr;
- lines.nextIndex = nullptr;
- }
-
- SkAutoFree quadIndexPtr;
- if (fIsIndexed) {
- quads.indices = (uint16_t*) sk_malloc_throw(fMaxQuadIndices * sizeof(uint16_t));
- quadIndexPtr.set(quads.indices);
- quads.nextIndex = quads.indices;
- } else {
- quads.indices = nullptr;
- quads.nextIndex = nullptr;
- }
-
- // fill buffers
- for (int i = 0; i < fGeoData.count(); i++) {
- const Geometry& args = fGeoData[i];
-
- if (!this->createGeom(lines,
- quads,
- args.fPath,
- args.fTolerance,
- fViewMatrix,
- args.fColor,
- fIsIndexed)) {
- return;
- }
- }
- int lineVertexOffset = (int) (lines.nextVertex - lines.vertices);
- int lineIndexOffset = (int) (lines.nextIndex - lines.indices);
- SkASSERT(lineVertexOffset <= fMaxLineVertices && lineIndexOffset <= fMaxLineIndices);
- int quadVertexOffset = (int) (quads.nextVertex - quads.vertices);
- int quadIndexOffset = (int) (quads.nextIndex - quads.indices);
- SkASSERT(quadVertexOffset <= fMaxQuadVertices && quadIndexOffset <= fMaxQuadIndices);
-
- if (lineVertexOffset) {
- SkAutoTUnref<const GrGeometryProcessor> lineGP;
- {
- using namespace GrDefaultGeoProcFactory;
- lineGP.reset(GrDefaultGeoProcFactory::Create(Color(Color::kAttribute_Type),
- Coverage(255),
- LocalCoords(LocalCoords::kUnused_Type),
- fViewMatrix));
- }
- SkASSERT(lineVertexStride == lineGP->getVertexStride());
-
- GrMesh lineMeshes;
- if (fIsIndexed) {
- lineMeshes.initIndexed(primitiveType, lineVertexBuffer, lineIndexBuffer,
- firstLineVertex, firstLineIndex, lineVertexOffset,
- lineIndexOffset);
- } else {
- lineMeshes.init(primitiveType, lineVertexBuffer, firstLineVertex,
- lineVertexOffset);
- }
- target->draw(lineGP, lineMeshes);
- }
-
- if (quadVertexOffset) {
- SkAutoTUnref<const GrGeometryProcessor> quadGP(MSAAQuadProcessor::Create(fViewMatrix));
- SkASSERT(quadVertexStride == quadGP->getVertexStride());
-
- const GrBuffer* quadVertexBuffer;
- int firstQuadVertex;
- MSAAQuadVertices::Vertex* quadVertices = (MSAAQuadVertices::Vertex*)
- target->makeVertexSpace(quadVertexStride, quadVertexOffset, &quadVertexBuffer,
- &firstQuadVertex);
- memcpy(quadVertices, quads.vertices, quadVertexStride * quadVertexOffset);
- GrMesh quadMeshes;
- if (fIsIndexed) {
- const GrBuffer* quadIndexBuffer;
- int firstQuadIndex;
- uint16_t* quadIndices = (uint16_t*) target->makeIndexSpace(quadIndexOffset,
- &quadIndexBuffer,
- &firstQuadIndex);
- memcpy(quadIndices, quads.indices, sizeof(uint16_t) * quadIndexOffset);
- quadMeshes.initIndexed(kTriangles_GrPrimitiveType, quadVertexBuffer,
- quadIndexBuffer, firstQuadVertex, firstQuadIndex,
- quadVertexOffset, quadIndexOffset);
- } else {
- quadMeshes.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVertex,
- quadVertexOffset);
- }
- target->draw(quadGP, quadMeshes);
- }
- }
-
- SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
-
- MSAAPathBatch(const Geometry& geometry, const SkMatrix& viewMatrix, const SkRect& devBounds)
- : INHERITED(ClassID())
- , fViewMatrix(viewMatrix) {
- fGeoData.push_back(geometry);
- this->setBounds(devBounds);
- int contourCount;
- this->computeWorstCasePointCount(geometry.fPath, &contourCount, kTolerance,
- &fMaxLineVertices, &fMaxQuadVertices);
- fMaxLineIndices = fMaxLineVertices * 3;
- fMaxQuadIndices = fMaxQuadVertices * 3;
- fIsIndexed = contourCount > 1;
- }
-
- bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
- MSAAPathBatch* that = t->cast<MSAAPathBatch>();
- if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
- that->bounds(), caps)) {
- return false;
- }
-
- if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
- return false;
- }
-
- if ((fMaxLineIndices + that->fMaxLineIndices > SK_MaxU16) ||
- (fMaxQuadIndices + that->fMaxQuadIndices > SK_MaxU16)) {
- return false;
- }
-
- fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
- this->joinBounds(that->bounds());
- fIsIndexed = true;
- fMaxLineVertices += that->fMaxLineVertices;
- fMaxQuadVertices += that->fMaxQuadVertices;
- fMaxLineIndices += that->fMaxLineIndices;
- fMaxQuadIndices += that->fMaxQuadIndices;
- return true;
- }
-
- bool createGeom(MSAALineVertices& lines,
- MSAAQuadVertices& quads,
- const SkPath& path,
- SkScalar srcSpaceTol,
- const SkMatrix& m,
- SkColor color,
- bool isIndexed) const {
- {
- uint16_t subpathIdxStart = (uint16_t) (lines.nextVertex - lines.vertices);
-
- SkPoint pts[4];
-
- bool first = true;
- SkPath::Iter iter(path, false);
-
- bool done = false;
- while (!done) {
- SkPath::Verb verb = iter.next(pts);
- switch (verb) {
- case SkPath::kMove_Verb:
- if (!first) {
- uint16_t currIdx = (uint16_t) (lines.nextVertex - lines.vertices);
- subpathIdxStart = currIdx;
- }
- SkASSERT(lines.nextVertex < lines.verticesEnd);
- *(lines.nextVertex++) = { pts[0], color };
- break;
- case SkPath::kLine_Verb:
- if (isIndexed) {
- uint16_t prevIdx = (uint16_t) (lines.nextVertex - lines.vertices - 1);
- if (prevIdx > subpathIdxStart) {
- append_contour_edge_indices(subpathIdxStart, prevIdx, lines);
- }
- }
- SkASSERT(lines.nextVertex < lines.verticesEnd);
- *(lines.nextVertex++) = { pts[1], color };
- break;
- case SkPath::kConic_Verb: {
- SkScalar weight = iter.conicWeight();
- SkAutoConicToQuads converter;
- const SkPoint* quadPts = converter.computeQuads(pts, weight,
- kTolerance);
- for (int i = 0; i < converter.countQuads(); ++i) {
- add_quad(lines, quads, quadPts + i * 2, color, isIndexed,
- subpathIdxStart);
- }
- break;
- }
- case SkPath::kQuad_Verb: {
- add_quad(lines, quads, pts, color, isIndexed, subpathIdxStart);
- break;
- }
- case SkPath::kCubic_Verb: {
- SkSTArray<15, SkPoint, true> quadPts;
- GrPathUtils::convertCubicToQuads(pts, kTolerance, &quadPts);
- int count = quadPts.count();
- for (int i = 0; i < count; i += 3) {
- add_quad(lines, quads, &quadPts[i], color, isIndexed, subpathIdxStart);
- }
- break;
- }
- case SkPath::kClose_Verb:
- break;
- case SkPath::kDone_Verb:
- done = true;
- }
- first = false;
- }
- }
- return true;
- }
-
- SkSTArray<1, Geometry, true> fGeoData;
-
- SkMatrix fViewMatrix;
- int fMaxLineVertices;
- int fMaxQuadVertices;
- int fMaxLineIndices;
- int fMaxQuadIndices;
- bool fIsIndexed;
-
- typedef GrVertexBatch INHERITED;
-};
-
-bool GrMSAAPathRenderer::internalDrawPath(GrDrawTarget* target,
- GrPipelineBuilder* pipelineBuilder,
- GrColor color,
- const SkMatrix& viewMatrix,
- const SkPath& path,
- const GrStrokeInfo& origStroke,
- bool stencilOnly) {
- SkTCopyOnFirstWrite<GrStrokeInfo> stroke(origStroke);
-
- const GrXPFactory* xpFactory = pipelineBuilder->getXPFactory();
- SkAutoTUnref<const GrXPFactory> backupXPFactory(SkSafeRef(xpFactory));
- // face culling doesn't make sense here
- SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace());
-
- int passCount = 0;
- const GrStencilSettings* passes[3];
- GrPipelineBuilder::DrawFace drawFace[3];
- bool reverse = false;
- bool lastPassIsBounds;
-
- if (single_pass_path(path, *stroke)) {
- passCount = 1;
- if (stencilOnly) {
- passes[0] = &gDirectToStencil;
- } else {
- passes[0] = nullptr;
- }
- drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
- lastPassIsBounds = false;
- } else {
- switch (path.getFillType()) {
- case SkPath::kInverseEvenOdd_FillType:
- reverse = true;
- // fallthrough
- case SkPath::kEvenOdd_FillType:
- passes[0] = &gEOStencilPass;
- if (stencilOnly) {
- passCount = 1;
- lastPassIsBounds = false;
- } else {
- passCount = 2;
- lastPassIsBounds = true;
- if (reverse) {
- passes[1] = &gInvEOColorPass;
- } else {
- passes[1] = &gEOColorPass;
- }
- }
- drawFace[0] = drawFace[1] = GrPipelineBuilder::kBoth_DrawFace;
- break;
-
- case SkPath::kInverseWinding_FillType:
- reverse = true;
- // fallthrough
- case SkPath::kWinding_FillType:
- passes[0] = &gWindStencilSeparateWithWrap;
- passCount = 2;
- drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
- if (stencilOnly) {
- lastPassIsBounds = false;
- --passCount;
- } else {
- lastPassIsBounds = true;
- drawFace[passCount-1] = GrPipelineBuilder::kBoth_DrawFace;
- if (reverse) {
- passes[passCount-1] = &gInvWindColorPass;
- } else {
- passes[passCount-1] = &gWindColorPass;
- }
- }
- break;
- default:
- SkDEBUGFAIL("Unknown path fFill!");
- return false;
- }
- }
-
- SkRect devBounds;
- GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devBounds);
-
- for (int p = 0; p < passCount; ++p) {
- pipelineBuilder->setDrawFace(drawFace[p]);
- if (passes[p]) {
- *pipelineBuilder->stencil() = *passes[p];
- }
-
- if (lastPassIsBounds && (p == passCount-1)) {
- // Reset the XP Factory on pipelineBuilder
- pipelineBuilder->setXPFactory(backupXPFactory);
- SkRect bounds;
- SkMatrix localMatrix = SkMatrix::I();
- if (reverse) {
- SkASSERT(pipelineBuilder->getRenderTarget());
- // draw over the dev bounds (which will be the whole dst surface for inv fill).
- bounds = devBounds;
- SkMatrix vmi;
- // mapRect through persp matrix may not be correct
- if (!viewMatrix.hasPerspective() && viewMatrix.invert(&vmi)) {
- vmi.mapRect(&bounds);
- } else {
- if (!viewMatrix.invert(&localMatrix)) {
- return false;
- }
- }
- } else {
- bounds = path.getBounds();
- }
- const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? SkMatrix::I() :
- viewMatrix;
- SkAutoTUnref<GrDrawBatch> batch(
- GrRectBatchFactory::CreateNonAAFill(color, viewM, bounds, nullptr,
- &localMatrix));
- target->drawBatch(*pipelineBuilder, batch);
- } else {
- if (passCount > 1) {
- pipelineBuilder->setDisableColorXPFactory();
- }
-
- MSAAPathBatch::Geometry geometry;
- geometry.fColor = color;
- geometry.fPath = path;
- geometry.fTolerance = kTolerance;
-
- SkAutoTUnref<MSAAPathBatch> batch(MSAAPathBatch::Create(geometry, viewMatrix,
- devBounds));
- if (batch->isValid()) {
- target->drawBatch(*pipelineBuilder, batch);
- }
- else {
- return false;
- }
- }
- }
- return true;
-}
-
-bool GrMSAAPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
- return !IsStrokeHairlineOrEquivalent(*args.fStroke, *args.fViewMatrix, nullptr) &&
- !args.fAntiAlias;
-}
-
-bool GrMSAAPathRenderer::onDrawPath(const DrawPathArgs& args) {
- GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrMSAAPathRenderer::onDrawPath");
- SkPath path;
- GrStrokeInfo stroke(*args.fStroke);
- if (stroke.isDashed()) {
- if (!stroke.applyDashToPath(&path, &stroke, *args.fPath)) {
- return false;
- }
- } else {
- path = *args.fPath;
- }
- if (!stroke.isFillStyle()) {
- stroke.setResScale(SkScalarAbs(args.fViewMatrix->getMaxScale()));
- if (!stroke.applyToPath(&path, path)) {
- return false;
- }
- stroke.setFillStyle();
- }
- return this->internalDrawPath(args.fTarget,
- args.fPipelineBuilder,
- args.fColor,
- *args.fViewMatrix,
- path,
- stroke,
- false);
-}
-
-void GrMSAAPathRenderer::onStencilPath(const StencilPathArgs& args) {
- GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(),"GrMSAAPathRenderer::onStencilPath");
- SkASSERT(SkPath::kInverseEvenOdd_FillType != args.fPath->getFillType());
- SkASSERT(SkPath::kInverseWinding_FillType != args.fPath->getFillType());
- this->internalDrawPath(args.fTarget, args.fPipelineBuilder, GrColor_WHITE, *args.fViewMatrix,
- *args.fPath, *args.fStroke, true);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/batches/GrMSAAPathRenderer.h b/src/gpu/batches/GrMSAAPathRenderer.h
deleted file mode 100644
index 0ffd280291..0000000000
--- a/src/gpu/batches/GrMSAAPathRenderer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrMSAAPathRenderer_DEFINED
-#define GrMSAAPathRenderer_DEFINED
-
-#include "GrPathRenderer.h"
-#include "SkTypes.h"
-
-class SK_API GrMSAAPathRenderer : public GrPathRenderer {
-private:
- StencilSupport onGetStencilSupport(const SkPath&, const GrStrokeInfo&) const override;
-
- bool onCanDrawPath(const CanDrawPathArgs&) const override;
-
- bool onDrawPath(const DrawPathArgs&) override;
-
- void onStencilPath(const StencilPathArgs&) override;
-
- bool internalDrawPath(GrDrawTarget*,
- GrPipelineBuilder*,
- GrColor,
- const SkMatrix& viewMatrix,
- const SkPath&,
- const GrStrokeInfo&,
- bool stencilOnly);
-
- typedef GrPathRenderer INHERITED;
-};
-
-#endif
diff --git a/src/gpu/batches/GrPathStencilSettings.h b/src/gpu/batches/GrPathStencilSettings.h
deleted file mode 100644
index a04f77a200..0000000000
--- a/src/gpu/batches/GrPathStencilSettings.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrPathStencilSettings_DEFINED
-#define GrPathStencilSettings_DEFINED
-
-////// Even/Odd
-
-GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
- kInvert_StencilOp,
- kKeep_StencilOp,
- kAlwaysIfInClip_StencilFunc,
- 0xffff,
- 0xffff,
- 0xffff);
-
-// ok not to check clip b/c stencil pass only wrote inside clip
-GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
- kZero_StencilOp,
- kZero_StencilOp,
- kNotEqual_StencilFunc,
- 0xffff,
- 0x0000,
- 0xffff);
-
-// have to check clip b/c outside clip will always be zero.
-GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
- kZero_StencilOp,
- kZero_StencilOp,
- kEqualIfInClip_StencilFunc,
- 0xffff,
- 0x0000,
- 0xffff);
-
-////// Winding
-
-// when we have separate stencil we increment front faces / decrement back faces
-// when we don't have wrap incr and decr we use the stencil test to simulate
-// them.
-
-GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
- kIncWrap_StencilOp, kDecWrap_StencilOp,
- kKeep_StencilOp, kKeep_StencilOp,
- kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
- 0xffff, 0xffff,
- 0xffff, 0xffff,
- 0xffff, 0xffff);
-
-// if inc'ing the max value, invert to make 0
-// if dec'ing zero invert to make all ones.
-// we can't avoid touching the stencil on both passing and
-// failing, so we can't resctrict ourselves to the clip.
-GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
- kInvert_StencilOp, kInvert_StencilOp,
- kIncClamp_StencilOp, kDecClamp_StencilOp,
- kEqual_StencilFunc, kEqual_StencilFunc,
- 0xffff, 0xffff,
- 0xffff, 0x0000,
- 0xffff, 0xffff);
-
-// When there are no separate faces we do two passes to setup the winding rule
-// stencil. First we draw the front faces and inc, then we draw the back faces
-// and dec. These are same as the above two split into the incrementing and
-// decrementing passes.
-GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
- kIncWrap_StencilOp,
- kKeep_StencilOp,
- kAlwaysIfInClip_StencilFunc,
- 0xffff,
- 0xffff,
- 0xffff);
-
-GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
- kDecWrap_StencilOp,
- kKeep_StencilOp,
- kAlwaysIfInClip_StencilFunc,
- 0xffff,
- 0xffff,
- 0xffff);
-
-GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
- kInvert_StencilOp,
- kIncClamp_StencilOp,
- kEqual_StencilFunc,
- 0xffff,
- 0xffff,
- 0xffff);
-
-GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
- kInvert_StencilOp,
- kDecClamp_StencilOp,
- kEqual_StencilFunc,
- 0xffff,
- 0x0000,
- 0xffff);
-
-// Color passes are the same whether we use the two-sided stencil or two passes
-
-GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
- kZero_StencilOp,
- kZero_StencilOp,
- kNonZeroIfInClip_StencilFunc,
- 0xffff,
- 0x0000,
- 0xffff);
-
-GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
- kZero_StencilOp,
- kZero_StencilOp,
- kEqualIfInClip_StencilFunc,
- 0xffff,
- 0x0000,
- 0xffff);
-
-////// Normal render to stencil
-
-// Sometimes the default path renderer can draw a path directly to the stencil
-// buffer without having to first resolve the interior / exterior.
-GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
- kZero_StencilOp,
- kIncClamp_StencilOp,
- kAlwaysIfInClip_StencilFunc,
- 0xffff,
- 0x0000,
- 0xffff);
-
-#endif