From 82040a9a056cd830027e255c7da845dcb5c026ed Mon Sep 17 00:00:00 2001 From: Cary Clark Date: Mon, 12 Feb 2018 17:29:48 +0000 Subject: Revert "ccpr: Tessellate fans for very large and/or simple paths" This reverts commit 4138c972effe4eb0227fbb96571df290f3d1979b. Reason for revert: broke android flutter build Original change's description: > ccpr: Tessellate fans for very large and/or simple paths > > This increases CPU work, but reduces overdraw on the GPU as compared to > Redbook fanning. > > Bug: skia: > Change-Id: I47239c964261e0014a94266a71223eab0597bfb8 > Reviewed-on: https://skia-review.googlesource.com/105203 > Reviewed-by: Brian Salomon > Commit-Queue: Chris Dalton TBR=bsalomon@google.com,csmartdalton@google.com Change-Id: I98b5c10b97c3fa603de5122d9bb47ca07659242c No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: skia: Reviewed-on: https://skia-review.googlesource.com/106620 Reviewed-by: Cary Clark Commit-Queue: Cary Clark --- samplecode/SampleCCPRGeometry.cpp | 39 ++-- src/gpu/GrTessellator.cpp | 1 - src/gpu/ccpr/GrCCCoverageProcessor.cpp | 7 +- src/gpu/ccpr/GrCCCoverageProcessor.h | 54 ++--- src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp | 34 +-- src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp | 76 +++---- src/gpu/ccpr/GrCCGeometry.cpp | 2 +- src/gpu/ccpr/GrCCGeometry.h | 18 +- src/gpu/ccpr/GrCCPathParser.cpp | 285 ++++++-------------------- src/gpu/ccpr/GrCCPathParser.h | 12 +- 10 files changed, 155 insertions(+), 373 deletions(-) diff --git a/samplecode/SampleCCPRGeometry.cpp b/samplecode/SampleCCPRGeometry.cpp index a0c5d7be7a..5a2da7f02b 100644 --- a/samplecode/SampleCCPRGeometry.cpp +++ b/samplecode/SampleCCPRGeometry.cpp @@ -26,8 +26,8 @@ #include "gl/GrGLGpu.cpp" #include "ops/GrDrawOp.h" -using TriPointInstance = GrCCCoverageProcessor::TriPointInstance; -using QuadPointInstance = GrCCCoverageProcessor::QuadPointInstance; +using TriangleInstance = GrCCCoverageProcessor::TriangleInstance; +using CubicInstance = GrCCCoverageProcessor::CubicInstance; using RenderPass = GrCCCoverageProcessor::RenderPass; static constexpr float kDebugBloat = 40; @@ -66,8 +66,8 @@ private: SkPoint fPoints[4] = { {100.05f, 100.05f}, {400.75f, 100.05f}, {400.75f, 300.95f}, {100.05f, 300.95f}}; - SkTArray fTriPointInstances; - SkTArray fQuadPointInstances; + SkTArray fTriangleInstances; + SkTArray fCubicInstances; typedef SampleView INHERITED; }; @@ -190,8 +190,8 @@ void CCPRGeometryView::onDrawContent(SkCanvas* canvas) { } void CCPRGeometryView::updateGpuData() { - fTriPointInstances.reset(); - fQuadPointInstances.reset(); + fTriangleInstances.reset(); + fCubicInstances.reset(); if (GrCCCoverageProcessor::RenderPassIsCubic(fRenderPass)) { double t[2], s[2]; @@ -210,7 +210,7 @@ void CCPRGeometryView::updateGpuData() { ptsIdx += 2; continue; case GrCCGeometry::Verb::kMonotonicCubicTo: - fQuadPointInstances.push_back().set(&geometry.points()[ptsIdx], 0, 0); + fCubicInstances.push_back().set(&geometry.points()[ptsIdx], 0, 0); ptsIdx += 3; continue; default: @@ -234,11 +234,11 @@ void CCPRGeometryView::updateGpuData() { continue; } SkASSERT(GrCCGeometry::Verb::kMonotonicQuadraticTo == verb); - fTriPointInstances.push_back().set(&geometry.points()[ptsIdx], Sk2f(0, 0)); + fTriangleInstances.push_back().set(&geometry.points()[ptsIdx], Sk2f(0, 0)); ptsIdx += 2; } } else { - fTriPointInstances.push_back().set(fPoints[0], fPoints[1], fPoints[3], Sk2f(0, 0)); + fTriangleInstances.push_back().set(fPoints[0], fPoints[1], fPoints[3], Sk2f(0, 0)); } } @@ -253,28 +253,27 @@ void CCPRGeometryView::Op::onExecute(GrOpFlushState* state) { return; } - GrCCCoverageProcessor proc(rp, fView->fRenderPass, - GrCCCoverageProcessor::WindMethod::kCrossProduct); + GrCCCoverageProcessor proc(rp, fView->fRenderPass, state->caps()); SkDEBUGCODE(proc.enableDebugVisualizations(kDebugBloat)); SkSTArray<1, GrMesh> mesh; if (GrCCCoverageProcessor::RenderPassIsCubic(fView->fRenderPass)) { sk_sp instBuff(rp->createBuffer( - fView->fQuadPointInstances.count() * sizeof(QuadPointInstance), - kVertex_GrBufferType, kDynamic_GrAccessPattern, + fView->fCubicInstances.count() * sizeof(CubicInstance), kVertex_GrBufferType, + kDynamic_GrAccessPattern, GrResourceProvider::kNoPendingIO_Flag | GrResourceProvider::kRequireGpuMemory_Flag, - fView->fQuadPointInstances.begin())); - if (!fView->fQuadPointInstances.empty() && instBuff) { - proc.appendMesh(instBuff.get(), fView->fQuadPointInstances.count(), 0, &mesh); + fView->fCubicInstances.begin())); + if (!fView->fCubicInstances.empty() && instBuff) { + proc.appendMesh(instBuff.get(), fView->fCubicInstances.count(), 0, &mesh); } } else { sk_sp instBuff(rp->createBuffer( - fView->fTriPointInstances.count() * sizeof(TriPointInstance), kVertex_GrBufferType, + fView->fTriangleInstances.count() * sizeof(TriangleInstance), kVertex_GrBufferType, kDynamic_GrAccessPattern, GrResourceProvider::kNoPendingIO_Flag | GrResourceProvider::kRequireGpuMemory_Flag, - fView->fTriPointInstances.begin())); - if (!fView->fTriPointInstances.empty() && instBuff) { - proc.appendMesh(instBuff.get(), fView->fTriPointInstances.count(), 0, &mesh); + fView->fTriangleInstances.begin())); + if (!fView->fTriangleInstances.empty() && instBuff) { + proc.appendMesh(instBuff.get(), fView->fTriangleInstances.count(), 0, &mesh); } } diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp index 00e5c8a21c..2974cf02db 100644 --- a/src/gpu/GrTessellator.cpp +++ b/src/gpu/GrTessellator.cpp @@ -2359,7 +2359,6 @@ int PathToVertices(const SkPath& path, SkScalar tolerance, const SkRect& clipBou GrTessellator::WindingVertex** verts) { int contourCnt = get_contour_count(path, tolerance); if (contourCnt <= 0) { - *verts = nullptr; return 0; } SkArenaAlloc alloc(kArenaChunkSize); diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.cpp b/src/gpu/ccpr/GrCCCoverageProcessor.cpp index 2c3166d526..c875625745 100644 --- a/src/gpu/ccpr/GrCCCoverageProcessor.cpp +++ b/src/gpu/ccpr/GrCCCoverageProcessor.cpp @@ -66,11 +66,8 @@ int GrCCCoverageProcessor::Shader::DefineSoftSampleLocations(GrGLSLPPFragmentBui void GrCCCoverageProcessor::getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const { - int key = (int)fRenderPass << 2; - if (WindMethod::kInstanceData == fWindMethod) { - key |= 2; - } - if (Impl::kVertexShader == fImpl) { + int key = (int)fRenderPass << 1; + if (Impl::kGeometryShader == fImpl) { key |= 1; } #ifdef SK_DEBUG diff --git a/src/gpu/ccpr/GrCCCoverageProcessor.h b/src/gpu/ccpr/GrCCCoverageProcessor.h index e6adfffe14..1296e089dc 100644 --- a/src/gpu/ccpr/GrCCCoverageProcessor.h +++ b/src/gpu/ccpr/GrCCCoverageProcessor.h @@ -33,9 +33,8 @@ class GrMesh; */ class GrCCCoverageProcessor : public GrGeometryProcessor { public: - // Defines a single primitive shape with 3 input points (i.e. Triangles and Quadratics). - // X,Y point values are transposed. - struct TriPointInstance { + // Defines a single triangle or closed quadratic bezier, with transposed x,y point values. + struct TriangleInstance { float fX[3]; float fY[3]; @@ -43,15 +42,12 @@ public: void set(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans); }; - // Defines a single primitive shape with 4 input points, or 3 input points plus a W parameter - // duplicated in both 4th components (i.e. Cubics or Triangles with a custom winding number). - // X,Y point values are transposed. - struct QuadPointInstance { + // Defines a single closed cubic bezier, with transposed x,y point values. + struct CubicInstance { float fX[4]; float fY[4]; void set(const SkPoint[4], float dx, float dy); - void set(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans, float w); }; // All primitive shapes (triangles and closed, convex bezier curves) require more than one @@ -97,29 +93,24 @@ public: caps.shaderCaps()->geometryShaderSupport(); } - enum class WindMethod : bool { - kCrossProduct, // Calculate wind = +/-1 by sign of the cross product. - kInstanceData // Instance data provides custom, signed wind values of any magnitude. - // (For tightly-wound tessellated triangles.) - }; - - GrCCCoverageProcessor(GrResourceProvider* rp, RenderPass pass, WindMethod windMethod) + GrCCCoverageProcessor(GrResourceProvider* rp, RenderPass pass, const GrCaps& caps) : INHERITED(kGrCCCoverageProcessor_ClassID) , fRenderPass(pass) - , fWindMethod(windMethod) - , fImpl(rp->caps()->shaderCaps()->geometryShaderSupport() ? Impl::kGeometryShader - : Impl::kVertexShader) { - SkASSERT(DoesRenderPass(pass, *rp->caps())); + , fImpl(caps.shaderCaps()->geometryShaderSupport() ? Impl::kGeometryShader + : Impl::kVertexShader) { + SkASSERT(DoesRenderPass(pass, caps)); if (Impl::kGeometryShader == fImpl) { this->initGS(); } else { - this->initVS(rp); + this->initVS(rp, caps); } } // 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. + // of either TriangleInstance or CubicInstance, depending on this processor's RendererPass, with + // coordinates in the desired shape's final atlas-space position. + // + // NOTE: Quadratics use TriangleInstance since both have 3 points. void appendMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance, SkTArray* out) { if (Impl::kGeometryShader == fImpl) { @@ -236,7 +227,7 @@ private: }; void initGS(); - void initVS(GrResourceProvider*); + void initVS(GrResourceProvider*, const GrCaps&); void appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance, SkTArray* out) const; @@ -247,7 +238,6 @@ private: GrGLSLPrimitiveProcessor* createVSImpl(std::unique_ptr) const; const RenderPass fRenderPass; - const WindMethod fWindMethod; const Impl fImpl; SkDEBUGCODE(float fDebugBloat = 0); @@ -260,11 +250,11 @@ private: typedef GrGeometryProcessor INHERITED; }; -inline void GrCCCoverageProcessor::TriPointInstance::set(const SkPoint p[3], const Sk2f& trans) { +inline void GrCCCoverageProcessor::TriangleInstance::set(const SkPoint p[3], const Sk2f& trans) { this->set(p[0], p[1], p[2], trans); } -inline void GrCCCoverageProcessor::TriPointInstance::set(const SkPoint& p0, const SkPoint& p1, +inline void GrCCCoverageProcessor::TriangleInstance::set(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2, const Sk2f& trans) { Sk2f P0 = Sk2f::Load(&p0) + trans; Sk2f P1 = Sk2f::Load(&p1) + trans; @@ -272,23 +262,13 @@ inline void GrCCCoverageProcessor::TriPointInstance::set(const SkPoint& p0, cons Sk2f::Store3(this, P0, P1, P2); } -inline void GrCCCoverageProcessor::QuadPointInstance::set(const SkPoint p[4], float dx, float dy) { +inline void GrCCCoverageProcessor::CubicInstance::set(const SkPoint p[4], float dx, float dy) { Sk4f X,Y; Sk4f::Load2(p, &X, &Y); (X + dx).store(&fX); (Y + dy).store(&fY); } -inline void GrCCCoverageProcessor::QuadPointInstance::set(const SkPoint& p0, const SkPoint& p1, - const SkPoint& p2, const Sk2f& trans, - float w) { - Sk2f P0 = Sk2f::Load(&p0) + trans; - Sk2f P1 = Sk2f::Load(&p1) + trans; - Sk2f P2 = Sk2f::Load(&p2) + trans; - Sk2f W = Sk2f(w); - Sk2f::Store4(this, P0, P1, P2, W); -} - inline bool GrCCCoverageProcessor::RenderPassIsCubic(RenderPass pass) { switch (pass) { case RenderPass::kTriangleHulls: diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp b/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp index 224533b298..0754389c0e 100644 --- a/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp +++ b/src/gpu/ccpr/GrCCCoverageProcessor_GSImpl.cpp @@ -31,7 +31,7 @@ protected: // The vertex shader simply forwards transposed x or y values to the geometry shader. SkASSERT(1 == proc.numAttribs()); - gpArgs->fPositionVar.set(GrVertexAttribTypeToSLType(proc.getAttrib(0).fType), + gpArgs->fPositionVar.set(4 == proc.numInputPoints() ? kFloat4_GrSLType : kFloat3_GrSLType, proc.getAttrib(0).fName); // Geometry shader. @@ -57,20 +57,11 @@ protected: GrShaderVar wind("wind", kHalf_GrSLType); g->declareGlobal(wind); - if (WindMethod::kCrossProduct == proc.fWindMethod) { - g->codeAppend ("float area_x2 = determinant(float2x2(pts[0] - pts[1], " - "pts[0] - pts[2]));"); - if (4 == numInputPoints) { - g->codeAppend ("area_x2 += determinant(float2x2(pts[0] - pts[2], " - "pts[0] - pts[3]));"); - } - g->codeAppendf("%s = sign(area_x2);", wind.c_str()); - } else { - SkASSERT(WindMethod::kInstanceData == proc.fWindMethod); - SkASSERT(3 == numInputPoints); - SkASSERT(kFloat4_GrVertexAttribType == proc.getAttrib(0).fType); - g->codeAppendf("%s = sk_in[0].sk_Position.w;", wind.c_str()); + g->codeAppend ("float area_x2 = determinant(float2x2(pts[0] - pts[1], pts[0] - pts[2]));"); + if (4 == numInputPoints) { + g->codeAppend ("area_x2 += determinant(float2x2(pts[0] - pts[2], pts[0] - pts[3]));"); } + g->codeAppendf("%s = sign(area_x2);", wind.c_str()); SkString emitVertexFn; SkSTArray<2, GrShaderVar> emitArgs; @@ -331,17 +322,12 @@ private: void GrCCCoverageProcessor::initGS() { SkASSERT(Impl::kGeometryShader == fImpl); - if (RenderPassIsCubic(fRenderPass) || WindMethod::kInstanceData == fWindMethod) { - SkASSERT(WindMethod::kCrossProduct == fWindMethod || 3 == this->numInputPoints()); - this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); - SkASSERT(sizeof(QuadPointInstance) == this->getVertexStride() * 2); - SkASSERT(offsetof(QuadPointInstance, fY) == this->getVertexStride()); - GR_STATIC_ASSERT(0 == offsetof(QuadPointInstance, fX)); + if (RenderPassIsCubic(fRenderPass)) { + this->addVertexAttrib("x_or_y_values", kFloat4_GrVertexAttribType); // (See appendMesh.) + SkASSERT(sizeof(CubicInstance) == this->getVertexStride() * 2); } else { - this->addVertexAttrib("x_or_y_values", kFloat3_GrVertexAttribType); - SkASSERT(sizeof(TriPointInstance) == this->getVertexStride() * 2); - SkASSERT(offsetof(TriPointInstance, fY) == this->getVertexStride()); - GR_STATIC_ASSERT(0 == offsetof(TriPointInstance, fX)); + this->addVertexAttrib("x_or_y_values", kFloat3_GrVertexAttribType); // (See appendMesh.) + SkASSERT(sizeof(TriangleInstance) == this->getVertexStride() * 2); } this->setWillUseGeoShader(); } diff --git a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp index 4ac6443322..8f2884ae75 100644 --- a/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp +++ b/src/gpu/ccpr/GrCCCoverageProcessor_VSImpl.cpp @@ -35,25 +35,15 @@ protected: GrGLSLVertexBuilder* v = args.fVertBuilder; int numInputPoints = proc.numInputPoints(); - const char* swizzle = (4 == numInputPoints) ? "xyzw" : "xyz"; - v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s.%s, %s.%s));", - numInputPoints, numInputPoints, proc.getAttrib(kAttribIdx_X).fName, swizzle, - proc.getAttrib(kAttribIdx_Y).fName, swizzle); - - if (WindMethod::kCrossProduct == proc.fWindMethod) { - v->codeAppend ("float area_x2 = determinant(float2x2(pts[0] - pts[1], " - "pts[0] - pts[2]));"); - if (4 == numInputPoints) { - v->codeAppend ("area_x2 += determinant(float2x2(pts[0] - pts[2], " - "pts[0] - pts[3]));"); - } - v->codeAppend ("half wind = sign(area_x2);"); - } else { - SkASSERT(WindMethod::kInstanceData == proc.fWindMethod); - SkASSERT(3 == numInputPoints); - SkASSERT(kFloat4_GrVertexAttribType == proc.getAttrib(kAttribIdx_X).fType); - v->codeAppendf("half wind = %s.w;", proc.getAttrib(kAttribIdx_X).fName); + v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s, %s));", + numInputPoints, numInputPoints, proc.getAttrib(kAttribIdx_X).fName, + proc.getAttrib(kAttribIdx_Y).fName); + + v->codeAppend ("float area_x2 = determinant(float2x2(pts[0] - pts[1], pts[0] - pts[2]));"); + if (4 == numInputPoints) { + v->codeAppend ("area_x2 += determinant(float2x2(pts[0] - pts[2], pts[0] - pts[3]));"); } + v->codeAppend ("half wind = sign(area_x2);"); float bloat = kAABloatRadius; #ifdef SK_DEBUG @@ -350,9 +340,17 @@ public: } }; -void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) { +void GrCCCoverageProcessor::initVS(GrResourceProvider* rp, const GrCaps& caps) { SkASSERT(Impl::kVertexShader == fImpl); - const GrCaps& caps = *rp->caps(); + + GrVertexAttribType inputPtsType = RenderPassIsCubic(fRenderPass) ? + kFloat4_GrVertexAttribType : kFloat3_GrVertexAttribType; + + SkASSERT(kAttribIdx_X == this->numAttribs()); + this->addInstanceAttrib("X", inputPtsType); + + SkASSERT(kAttribIdx_Y == this->numAttribs()); + this->addInstanceAttrib("Y", inputPtsType); switch (fRenderPass) { case RenderPass::kTriangleHulls: { @@ -375,6 +373,8 @@ void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) { gHull3AndEdgeIndexBufferKey); fNumIndicesPerInstance = SK_ARRAY_COUNT(kHull3AndEdgeIndicesAsTris); } + SkASSERT(kAttribIdx_VertexData == this->numAttribs()); + this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType); break; } case RenderPass::kQuadraticHulls: @@ -396,6 +396,8 @@ void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) { gHull4IndexBufferKey); fNumIndicesPerInstance = SK_ARRAY_COUNT(kHull4IndicesAsTris); } + SkASSERT(kAttribIdx_VertexData == this->numAttribs()); + this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType); break; } case RenderPass::kTriangleEdges: @@ -425,36 +427,20 @@ void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) { } } - if (RenderPassIsCubic(fRenderPass) || WindMethod::kInstanceData == fWindMethod) { - SkASSERT(WindMethod::kCrossProduct == fWindMethod || 3 == this->numInputPoints()); - - SkASSERT(kAttribIdx_X == this->numAttribs()); - this->addInstanceAttrib("X", kFloat4_GrVertexAttribType); - - SkASSERT(kAttribIdx_Y == this->numAttribs()); - this->addInstanceAttrib("Y", kFloat4_GrVertexAttribType); - - SkASSERT(offsetof(QuadPointInstance, fX) == this->getAttrib(kAttribIdx_X).fOffsetInRecord); - SkASSERT(offsetof(QuadPointInstance, fY) == this->getAttrib(kAttribIdx_Y).fOffsetInRecord); - SkASSERT(sizeof(QuadPointInstance) == this->getInstanceStride()); +#ifdef SK_DEBUG + if (RenderPassIsCubic(fRenderPass)) { + SkASSERT(offsetof(CubicInstance, fX) == this->getAttrib(kAttribIdx_X).fOffsetInRecord); + SkASSERT(offsetof(CubicInstance, fY) == this->getAttrib(kAttribIdx_Y).fOffsetInRecord); + SkASSERT(sizeof(CubicInstance) == this->getInstanceStride()); } else { - SkASSERT(kAttribIdx_X == this->numAttribs()); - this->addInstanceAttrib("X", kFloat3_GrVertexAttribType); - - SkASSERT(kAttribIdx_Y == this->numAttribs()); - this->addInstanceAttrib("Y", kFloat3_GrVertexAttribType); - - SkASSERT(offsetof(TriPointInstance, fX) == this->getAttrib(kAttribIdx_X).fOffsetInRecord); - SkASSERT(offsetof(TriPointInstance, fY) == this->getAttrib(kAttribIdx_Y).fOffsetInRecord); - SkASSERT(sizeof(TriPointInstance) == this->getInstanceStride()); + SkASSERT(offsetof(TriangleInstance, fX) == this->getAttrib(kAttribIdx_X).fOffsetInRecord); + SkASSERT(offsetof(TriangleInstance, fY) == this->getAttrib(kAttribIdx_Y).fOffsetInRecord); + SkASSERT(sizeof(TriangleInstance) == this->getInstanceStride()); } - if (fVertexBuffer) { - SkASSERT(kAttribIdx_VertexData == this->numAttribs()); - this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType); - SkASSERT(sizeof(int32_t) == this->getVertexStride()); } +#endif if (caps.usePrimitiveRestart()) { this->setWillUsePrimitiveRestart(); diff --git a/src/gpu/ccpr/GrCCGeometry.cpp b/src/gpu/ccpr/GrCCGeometry.cpp index 481f4e4725..19bc8747b7 100644 --- a/src/gpu/ccpr/GrCCGeometry.cpp +++ b/src/gpu/ccpr/GrCCGeometry.cpp @@ -30,7 +30,7 @@ void GrCCGeometry::beginContour(const SkPoint& devPt) { // Store the current verb count in the fTriangles field for now. When we close the contour we // will use this value to calculate the actual number of triangles in its fan. - fCurrContourTallies = {fVerbs.count(), 0, 0, 0}; + fCurrContourTallies = {fVerbs.count(), 0, 0}; fPoints.push_back(devPt); fVerbs.push_back(Verb::kBeginContour); diff --git a/src/gpu/ccpr/GrCCGeometry.h b/src/gpu/ccpr/GrCCGeometry.h index 47b57c1c72..b50dd015eb 100644 --- a/src/gpu/ccpr/GrCCGeometry.h +++ b/src/gpu/ccpr/GrCCGeometry.h @@ -35,10 +35,9 @@ public: kEndOpenContour // endPt != startPt. }; - // These tallies track numbers of CCPR primitives that are required to draw a contour. + // These tallies track numbers of CCPR primitives are required to draw a contour. struct PrimitiveTallies { int fTriangles; // Number of triangles in the contour's fan. - int fWoundTriangles; // Triangles (from the tessellator) whose winding magnitude > 1. int fQuadratics; int fCubics; @@ -116,11 +115,11 @@ private: int maxSubdivisions = kMaxSubdivionsPerCubicSection); // Transient state used while building a contour. - SkPoint fCurrAnchorPoint; - SkPoint fCurrFanPoint; - PrimitiveTallies fCurrContourTallies; - SkCubicType fCurrCubicType; - SkDEBUGCODE(bool fBuildingContour = false); + SkPoint fCurrAnchorPoint; + SkPoint fCurrFanPoint; + PrimitiveTallies fCurrContourTallies; + SkCubicType fCurrCubicType; + SkDEBUGCODE(bool fBuildingContour = false); // TODO: These points could eventually be written directly to block-allocated GPU buffers. SkSTArray<128, SkPoint, true> fPoints; @@ -129,7 +128,6 @@ private: inline void GrCCGeometry::PrimitiveTallies::operator+=(const PrimitiveTallies& b) { fTriangles += b.fTriangles; - fWoundTriangles += b.fWoundTriangles; fQuadratics += b.fQuadratics; fCubics += b.fCubics; } @@ -137,14 +135,12 @@ inline void GrCCGeometry::PrimitiveTallies::operator+=(const PrimitiveTallies& b GrCCGeometry::PrimitiveTallies inline GrCCGeometry::PrimitiveTallies::operator-(const PrimitiveTallies& b) const { return {fTriangles - b.fTriangles, - fWoundTriangles - b.fWoundTriangles, fQuadratics - b.fQuadratics, fCubics - b.fCubics}; } inline bool GrCCGeometry::PrimitiveTallies::operator==(const PrimitiveTallies& b) { - return fTriangles == b.fTriangles && fWoundTriangles == b.fWoundTriangles && - fQuadratics == b.fQuadratics && fCubics == b.fCubics; + return fTriangles == b.fTriangles && fQuadratics == b.fQuadratics && fCubics == b.fCubics; } #endif diff --git a/src/gpu/ccpr/GrCCPathParser.cpp b/src/gpu/ccpr/GrCCPathParser.cpp index f729290187..2a632d3bda 100644 --- a/src/gpu/ccpr/GrCCPathParser.cpp +++ b/src/gpu/ccpr/GrCCPathParser.cpp @@ -17,8 +17,8 @@ #include "SkPoint.h" #include "ccpr/GrCCGeometry.h" -using TriPointInstance = GrCCCoverageProcessor::TriPointInstance; -using QuadPointInstance = GrCCCoverageProcessor::QuadPointInstance; +using TriangleInstance = GrCCCoverageProcessor::TriangleInstance; +using CubicInstance = GrCCCoverageProcessor::CubicInstance; GrCCPathParser::GrCCPathParser(int maxTotalPaths, int maxPathPoints, int numSkPoints, int numSkVerbs) @@ -32,8 +32,7 @@ GrCCPathParser::GrCCPathParser(int maxTotalPaths, int maxPathPoints, int numSkPo // that "end" at the beginning of the data. These will not be drawn, but will only be be read by // the first actual batch. fScissorSubBatches.push_back() = {PrimitiveTallies(), SkIRect::MakeEmpty()}; - fCoverageCountBatches.push_back() = {PrimitiveTallies(), fScissorSubBatches.count(), - PrimitiveTallies()}; + fCoverageCountBatches.push_back() = {PrimitiveTallies(), fScissorSubBatches.count()}; } void GrCCPathParser::parsePath(const SkMatrix& m, const SkPath& path, SkRect* devBounds, @@ -106,7 +105,6 @@ void GrCCPathParser::parsePath(const SkPath& path, const SkPoint* deviceSpacePts fCurrPathPointsIdx = fGeometry.points().count(); fCurrPathVerbsIdx = fGeometry.verbs().count(); fCurrPathPrimitiveCounts = PrimitiveTallies(); - fCurrPathFillType = path.getFillType(); fGeometry.beginPath(); @@ -162,81 +160,7 @@ void GrCCPathParser::saveParsedPath(ScissorMode scissorMode, const SkIRect& clip int16_t atlasOffsetX, int16_t atlasOffsetY) { SkASSERT(fParsingPath); - fPathsInfo.emplace_back(scissorMode, atlasOffsetX, atlasOffsetY); - - // Tessellate fans from very large and/or simple paths, in order to reduce overdraw. - int numVerbs = fGeometry.verbs().count() - fCurrPathVerbsIdx - 1; - int64_t tessellationWork = (int64_t)numVerbs * (32 - SkCLZ(numVerbs)); // N log N. - int64_t fanningWork = (int64_t)clippedDevIBounds.height() * clippedDevIBounds.width(); - if (tessellationWork * (50*50) + (100*100) < fanningWork) { // Don't tessellate under 100x100. - fCurrPathPrimitiveCounts.fTriangles = - fCurrPathPrimitiveCounts.fWoundTriangles = 0; - - const SkTArray& verbs = fGeometry.verbs(); - const SkTArray& pts = fGeometry.points(); - int ptsIdx = fCurrPathPointsIdx; - - // Build an SkPath of the Redbook fan. - SkPath fan; - fan.setFillType(fCurrPathFillType); - SkASSERT(GrCCGeometry::Verb::kBeginPath == verbs[fCurrPathVerbsIdx]); - for (int i = fCurrPathVerbsIdx + 1; i < fGeometry.verbs().count(); ++i) { - switch (verbs[i]) { - case GrCCGeometry::Verb::kBeginPath: - SK_ABORT("Invalid GrCCGeometry"); - continue; - - case GrCCGeometry::Verb::kBeginContour: - fan.moveTo(pts[ptsIdx++]); - continue; - - case GrCCGeometry::Verb::kLineTo: - fan.lineTo(pts[ptsIdx++]); - continue; - - case GrCCGeometry::Verb::kMonotonicQuadraticTo: - fan.lineTo(pts[ptsIdx + 1]); - ptsIdx += 2; - continue; - - case GrCCGeometry::Verb::kMonotonicCubicTo: - fan.lineTo(pts[ptsIdx + 2]); - ptsIdx += 3; - continue; - - case GrCCGeometry::Verb::kEndClosedContour: - case GrCCGeometry::Verb::kEndOpenContour: - fan.close(); - continue; - } - } - GrTessellator::WindingVertex* vertices = nullptr; - int count = GrTessellator::PathToVertices(fan, std::numeric_limits::infinity(), - SkRect::Make(clippedDevIBounds), &vertices); - SkASSERT(0 == count % 3); - for (int i = 0; i < count; i += 3) { - SkASSERT(vertices[i].fWinding == vertices[i + 1].fWinding); - SkASSERT(vertices[i].fWinding == vertices[i + 2].fWinding); - if (1 == abs(vertices[i].fWinding)) { - // Ensure this triangle's points actually wind in the same direction as fWinding. - float ax = vertices[i].fPos.fX - vertices[i + 1].fPos.fX; - float ay = vertices[i].fPos.fY - vertices[i + 1].fPos.fY; - float bx = vertices[i].fPos.fX - vertices[i + 2].fPos.fX; - float by = vertices[i].fPos.fY - vertices[i + 2].fPos.fY; - float wind = ay*bx - ax*by; - if ((wind > 0) != (vertices[i].fWinding > 0)) { - std::swap(vertices[i + 1].fPos, vertices[i + 2].fPos); - } - ++fCurrPathPrimitiveCounts.fTriangles; - } else { - ++fCurrPathPrimitiveCounts.fWoundTriangles; - } - } - - fPathsInfo.back().fFanTessellation.reset(vertices); - fPathsInfo.back().fFanTessellationCount = count; - } - + fPathsInfo.push_back() = {scissorMode, atlasOffsetX, atlasOffsetY}; fTotalPrimitiveCounts[(int)scissorMode] += fCurrPathPrimitiveCounts; if (ScissorMode::kScissored == scissorMode) { @@ -256,23 +180,15 @@ void GrCCPathParser::discardParsedPath() { GrCCPathParser::CoverageCountBatchID GrCCPathParser::closeCurrentBatch() { SkASSERT(!fInstanceBuffer); SkASSERT(!fCoverageCountBatches.empty()); - const auto& lastBatch = fCoverageCountBatches.back(); - const auto& lastScissorSubBatch = fScissorSubBatches[lastBatch.fEndScissorSubBatchIdx - 1]; - PrimitiveTallies batchTotalCounts = fTotalPrimitiveCounts[(int)ScissorMode::kNonScissored] - - lastBatch.fEndNonScissorIndices; - batchTotalCounts += fTotalPrimitiveCounts[(int)ScissorMode::kScissored] - - lastScissorSubBatch.fEndPrimitiveIndices; + int maxMeshes = 1 + fScissorSubBatches.count() - + fCoverageCountBatches.back().fEndScissorSubBatchIdx; + fMaxMeshesPerDraw = SkTMax(fMaxMeshesPerDraw, maxMeshes); fCoverageCountBatches.push_back() = { fTotalPrimitiveCounts[(int)ScissorMode::kNonScissored], - fScissorSubBatches.count(), - batchTotalCounts + fScissorSubBatches.count() }; - - int maxMeshes = 1 + fScissorSubBatches.count() - lastBatch.fEndScissorSubBatchIdx; - fMaxMeshesPerDraw = SkTMax(fMaxMeshesPerDraw, maxMeshes); - return fCoverageCountBatches.count() - 1; } @@ -289,10 +205,10 @@ GrCCPathParser::CoverageCountBatchID GrCCPathParser::closeCurrentBatch() { // elements past the end for this method to use as scratch space. // // Returns the next triangle instance after the final one emitted. -static TriPointInstance* emit_recursive_fan(const SkTArray& pts, +static TriangleInstance* emit_recursive_fan(const SkTArray& pts, SkTArray& indices, int firstIndex, int indexCount, const Sk2f& atlasOffset, - TriPointInstance out[]) { + TriangleInstance out[]) { if (indexCount < 3) { return out; } @@ -316,22 +232,6 @@ static TriPointInstance* emit_recursive_fan(const SkTArray& pts, return out; } -static void emit_tessellated_fan(const GrTessellator::WindingVertex* vertices, int numVertices, - const Sk2f& atlasOffset, TriPointInstance* triPointInstanceData, - QuadPointInstance* quadPointInstanceData, - GrCCGeometry::PrimitiveTallies* indices) { - for (int i = 0; i < numVertices; i += 3) { - if (1 == abs(vertices[i].fWinding)) { - triPointInstanceData[indices->fTriangles++].set(vertices[i].fPos, vertices[i + 1].fPos, - vertices[i + 2].fPos, atlasOffset); - } else { - quadPointInstanceData[indices->fWoundTriangles++].set( - vertices[i].fPos, vertices[i+1].fPos, vertices[i + 2].fPos, atlasOffset, - static_cast(vertices[i].fWinding)); - } - } -} - bool GrCCPathParser::finalize(GrOnFlushResourceProvider* onFlushRP) { SkASSERT(!fParsingPath); // Call saveParsedPath() or discardParsedPath(). SkASSERT(fCoverageCountBatches.back().fEndNonScissorIndices == // Call closeCurrentBatch(). @@ -350,7 +250,7 @@ bool GrCCPathParser::finalize(GrOnFlushResourceProvider* onFlushRP) { // // We already know how big to make each of the 6 arrays from fTotalPrimitiveCounts, so layout is // straightforward. Start with triangles and quadratics. They both view the instance buffer as - // an array of TriPointInstance[], so we can begin at zero and lay them out one after the other. + // an array of TriangleInstance[], so we can begin at zero and lay them out one after the other. fBaseInstances[0].fTriangles = 0; fBaseInstances[1].fTriangles = fBaseInstances[0].fTriangles + fTotalPrimitiveCounts[0].fTriangles; @@ -360,112 +260,85 @@ bool GrCCPathParser::finalize(GrOnFlushResourceProvider* onFlushRP) { fTotalPrimitiveCounts[0].fQuadratics; int triEndIdx = fBaseInstances[1].fQuadratics + fTotalPrimitiveCounts[1].fQuadratics; - // Wound triangles and cubics both view the same instance buffer as an array of - // QuadPointInstance[]. So, reinterpreting the instance data as QuadPointInstance[], we start - // them on the first index that will not overwrite previous TriPointInstance data. - int quadBaseIdx = - GR_CT_DIV_ROUND_UP(triEndIdx * sizeof(TriPointInstance), sizeof(QuadPointInstance)); - fBaseInstances[0].fWoundTriangles = quadBaseIdx; - fBaseInstances[1].fWoundTriangles = fBaseInstances[0].fWoundTriangles + - fTotalPrimitiveCounts[0].fWoundTriangles; - fBaseInstances[0].fCubics = fBaseInstances[1].fWoundTriangles + - fTotalPrimitiveCounts[1].fWoundTriangles; + // Cubics view the same instance buffer as an array of CubicInstance[]. So, reinterpreting the + // instance data as CubicInstance[], we start them on the first index that will not overwrite + // previous TriangleInstance data. + int cubicBaseIdx = + GR_CT_DIV_ROUND_UP(triEndIdx * sizeof(TriangleInstance), sizeof(CubicInstance)); + fBaseInstances[0].fCubics = cubicBaseIdx; fBaseInstances[1].fCubics = fBaseInstances[0].fCubics + fTotalPrimitiveCounts[0].fCubics; - int quadEndIdx = fBaseInstances[1].fCubics + fTotalPrimitiveCounts[1].fCubics; + int cubicEndIdx = fBaseInstances[1].fCubics + fTotalPrimitiveCounts[1].fCubics; fInstanceBuffer = onFlushRP->makeBuffer(kVertex_GrBufferType, - quadEndIdx * sizeof(QuadPointInstance)); + cubicEndIdx * sizeof(CubicInstance)); if (!fInstanceBuffer) { return false; } - TriPointInstance* triPointInstanceData = static_cast(fInstanceBuffer->map()); - QuadPointInstance* quadPointInstanceData = - reinterpret_cast(triPointInstanceData); - SkASSERT(quadPointInstanceData); + TriangleInstance* triangleInstanceData = static_cast(fInstanceBuffer->map()); + CubicInstance* cubicInstanceData = reinterpret_cast(triangleInstanceData); + SkASSERT(cubicInstanceData); - PathInfo* nextPathInfo = fPathsInfo.begin(); + PathInfo* currPathInfo = fPathsInfo.begin(); float atlasOffsetX = 0.0, atlasOffsetY = 0.0; Sk2f atlasOffset; + int ptsIdx = -1; PrimitiveTallies instanceIndices[2] = {fBaseInstances[0], fBaseInstances[1]}; PrimitiveTallies* currIndices = nullptr; SkSTArray<256, int32_t, true> currFan; - bool currFanIsTessellated = false; const SkTArray& pts = fGeometry.points(); - int ptsIdx = -1; // Expand the ccpr verbs into GPU instance buffers. for (GrCCGeometry::Verb verb : fGeometry.verbs()) { switch (verb) { case GrCCGeometry::Verb::kBeginPath: SkASSERT(currFan.empty()); - currIndices = &instanceIndices[(int)nextPathInfo->fScissorMode]; - atlasOffsetX = static_cast(nextPathInfo->fAtlasOffsetX); - atlasOffsetY = static_cast(nextPathInfo->fAtlasOffsetY); + currIndices = &instanceIndices[(int)currPathInfo->fScissorMode]; + atlasOffsetX = static_cast(currPathInfo->fAtlasOffsetX); + atlasOffsetY = static_cast(currPathInfo->fAtlasOffsetY); atlasOffset = {atlasOffsetX, atlasOffsetY}; - currFanIsTessellated = nextPathInfo->fFanTessellation.get(); - if (currFanIsTessellated) { - emit_tessellated_fan(nextPathInfo->fFanTessellation.get(), - nextPathInfo->fFanTessellationCount, atlasOffset, - triPointInstanceData, quadPointInstanceData, currIndices); - } - ++nextPathInfo; + ++currPathInfo; continue; case GrCCGeometry::Verb::kBeginContour: SkASSERT(currFan.empty()); - ++ptsIdx; - if (!currFanIsTessellated) { - currFan.push_back(ptsIdx); - } + currFan.push_back(++ptsIdx); continue; case GrCCGeometry::Verb::kLineTo: - ++ptsIdx; - if (!currFanIsTessellated) { - SkASSERT(!currFan.empty()); - currFan.push_back(ptsIdx); - } + SkASSERT(!currFan.empty()); + currFan.push_back(++ptsIdx); continue; case GrCCGeometry::Verb::kMonotonicQuadraticTo: - triPointInstanceData[currIndices->fQuadratics++].set(&pts[ptsIdx], atlasOffset); - ptsIdx += 2; - if (!currFanIsTessellated) { - SkASSERT(!currFan.empty()); - currFan.push_back(ptsIdx); - } + SkASSERT(!currFan.empty()); + triangleInstanceData[currIndices->fQuadratics++].set(&pts[ptsIdx], atlasOffset); + currFan.push_back(ptsIdx += 2); continue; case GrCCGeometry::Verb::kMonotonicCubicTo: - quadPointInstanceData[currIndices->fCubics++].set(&pts[ptsIdx], atlasOffsetX, - atlasOffsetY); - ptsIdx += 3; - if (!currFanIsTessellated) { - SkASSERT(!currFan.empty()); - currFan.push_back(ptsIdx); - } + SkASSERT(!currFan.empty()); + cubicInstanceData[currIndices->fCubics++].set(&pts[ptsIdx], atlasOffsetX, + atlasOffsetY); + currFan.push_back(ptsIdx += 3); continue; case GrCCGeometry::Verb::kEndClosedContour: // endPt == startPt. - if (!currFanIsTessellated) { - SkASSERT(!currFan.empty()); - currFan.pop_back(); - } + SkASSERT(!currFan.empty()); + currFan.pop_back(); // fallthru. case GrCCGeometry::Verb::kEndOpenContour: // endPt != startPt. - SkASSERT(!currFanIsTessellated || currFan.empty()); - if (!currFanIsTessellated && currFan.count() >= 3) { + if (currFan.count() >= 3) { int fanSize = currFan.count(); // Reserve space for emit_recursive_fan. Technically this can grow to // fanSize + log3(fanSize), but we approximate with log2. currFan.push_back_n(SkNextLog2(fanSize)); - SkDEBUGCODE(TriPointInstance* end =) + SkDEBUGCODE(TriangleInstance* end =) emit_recursive_fan(pts, currFan, 0, fanSize, atlasOffset, - triPointInstanceData + currIndices->fTriangles); + triangleInstanceData + currIndices->fTriangles); currIndices->fTriangles += fanSize - 2; - SkASSERT(triPointInstanceData + currIndices->fTriangles == end); + SkASSERT(triangleInstanceData + currIndices->fTriangles == end); } currFan.reset(); continue; @@ -474,16 +347,14 @@ bool GrCCPathParser::finalize(GrOnFlushResourceProvider* onFlushRP) { fInstanceBuffer->unmap(); - SkASSERT(nextPathInfo == fPathsInfo.end()); + SkASSERT(currPathInfo == fPathsInfo.end()); SkASSERT(ptsIdx == pts.count() - 1); SkASSERT(instanceIndices[0].fTriangles == fBaseInstances[1].fTriangles); SkASSERT(instanceIndices[1].fTriangles == fBaseInstances[0].fQuadratics); SkASSERT(instanceIndices[0].fQuadratics == fBaseInstances[1].fQuadratics); SkASSERT(instanceIndices[1].fQuadratics == triEndIdx); - SkASSERT(instanceIndices[0].fWoundTriangles == fBaseInstances[1].fWoundTriangles); - SkASSERT(instanceIndices[1].fWoundTriangles == fBaseInstances[0].fCubics); SkASSERT(instanceIndices[0].fCubics == fBaseInstances[1].fCubics); - SkASSERT(instanceIndices[1].fCubics == quadEndIdx); + SkASSERT(instanceIndices[1].fCubics == cubicEndIdx); fMeshesScratchBuffer.reserve(fMaxMeshesPerDraw); fDynamicStatesScratchBuffer.reserve(fMaxMeshesPerDraw); @@ -494,56 +365,36 @@ bool GrCCPathParser::finalize(GrOnFlushResourceProvider* onFlushRP) { void GrCCPathParser::drawCoverageCount(GrOpFlushState* flushState, CoverageCountBatchID batchID, const SkIRect& drawBounds) const { using RenderPass = GrCCCoverageProcessor::RenderPass; - using WindMethod = GrCCCoverageProcessor::WindMethod; SkASSERT(fInstanceBuffer); - const PrimitiveTallies& batchTotalCounts = fCoverageCountBatches[batchID].fTotalPrimitiveCounts; - GrPipeline pipeline(flushState->drawOpArgs().fProxy, GrPipeline::ScissorState::kEnabled, SkBlendMode::kPlus); - if (batchTotalCounts.fTriangles) { - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kTriangleHulls, - WindMethod::kCrossProduct, &PrimitiveTallies::fTriangles, drawBounds); - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kTriangleEdges, - WindMethod::kCrossProduct, &PrimitiveTallies::fTriangles, - drawBounds); // Might get skipped. - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kTriangleCorners, - WindMethod::kCrossProduct, &PrimitiveTallies::fTriangles, drawBounds); - } - - if (batchTotalCounts.fWoundTriangles) { - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kTriangleHulls, - WindMethod::kInstanceData, &PrimitiveTallies::fWoundTriangles, - drawBounds); - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kTriangleEdges, - WindMethod::kInstanceData, &PrimitiveTallies::fWoundTriangles, - drawBounds); // Might get skipped. - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kTriangleCorners, - WindMethod::kInstanceData, &PrimitiveTallies::fWoundTriangles, - drawBounds); - } - - if (batchTotalCounts.fQuadratics) { - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kQuadraticHulls, - WindMethod::kCrossProduct, &PrimitiveTallies::fQuadratics, drawBounds); - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kQuadraticCorners, - WindMethod::kCrossProduct, &PrimitiveTallies::fQuadratics, drawBounds); - } - - if (batchTotalCounts.fCubics) { - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kCubicHulls, - WindMethod::kCrossProduct, &PrimitiveTallies::fCubics, drawBounds); - this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kCubicCorners, - WindMethod::kCrossProduct, &PrimitiveTallies::fCubics, drawBounds); - } + // Triangles. + this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kTriangleHulls, + &PrimitiveTallies::fTriangles, drawBounds); + this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kTriangleEdges, + &PrimitiveTallies::fTriangles, drawBounds); // Might get skipped. + this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kTriangleCorners, + &PrimitiveTallies::fTriangles, drawBounds); + + // Quadratics. + this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kQuadraticHulls, + &PrimitiveTallies::fQuadratics, drawBounds); + this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kQuadraticCorners, + &PrimitiveTallies::fQuadratics, drawBounds); + + // Cubics. + this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kCubicHulls, + &PrimitiveTallies::fCubics, drawBounds); + this->drawRenderPass(flushState, pipeline, batchID, RenderPass::kCubicCorners, + &PrimitiveTallies::fCubics, drawBounds); } void GrCCPathParser::drawRenderPass(GrOpFlushState* flushState, const GrPipeline& pipeline, CoverageCountBatchID batchID, GrCCCoverageProcessor::RenderPass renderPass, - GrCCCoverageProcessor::WindMethod windMethod, int PrimitiveTallies::*instanceType, const SkIRect& drawBounds) const { SkASSERT(pipeline.getScissorState().enabled()); @@ -556,13 +407,12 @@ void GrCCPathParser::drawRenderPass(GrOpFlushState* flushState, const GrPipeline fMeshesScratchBuffer.pop_back_n(fMeshesScratchBuffer.count()); fDynamicStatesScratchBuffer.pop_back_n(fDynamicStatesScratchBuffer.count()); - GrCCCoverageProcessor proc(flushState->resourceProvider(), renderPass, windMethod); + GrCCCoverageProcessor proc(flushState->resourceProvider(), renderPass, flushState->caps()); SkASSERT(batchID > 0); SkASSERT(batchID < fCoverageCountBatches.count()); const CoverageCountBatch& previousBatch = fCoverageCountBatches[batchID - 1]; const CoverageCountBatch& batch = fCoverageCountBatches[batchID]; - SkDEBUGCODE(int totalInstanceCount = 0); if (int instanceCount = batch.fEndNonScissorIndices.*instanceType - previousBatch.fEndNonScissorIndices.*instanceType) { @@ -572,7 +422,6 @@ void GrCCPathParser::drawRenderPass(GrOpFlushState* flushState, const GrPipeline proc.appendMesh(fInstanceBuffer.get(), instanceCount, baseInstance, &fMeshesScratchBuffer); fDynamicStatesScratchBuffer.push_back().fScissorRect.setXYWH(0, 0, drawBounds.width(), drawBounds.height()); - SkDEBUGCODE(totalInstanceCount += instanceCount); } SkASSERT(previousBatch.fEndScissorSubBatchIdx > 0); @@ -590,12 +439,10 @@ void GrCCPathParser::drawRenderPass(GrOpFlushState* flushState, const GrPipeline proc.appendMesh(fInstanceBuffer.get(), instanceCount, baseScissorInstance + startIndex, &fMeshesScratchBuffer); fDynamicStatesScratchBuffer.push_back().fScissorRect = scissorSubBatch.fScissor; - SkDEBUGCODE(totalInstanceCount += instanceCount); } SkASSERT(fMeshesScratchBuffer.count() == fDynamicStatesScratchBuffer.count()); SkASSERT(fMeshesScratchBuffer.count() <= fMaxMeshesPerDraw); - SkASSERT(totalInstanceCount == batch.fTotalPrimitiveCounts.*instanceType); if (!fMeshesScratchBuffer.empty()) { SkASSERT(flushState->rtCommandBuffer()); diff --git a/src/gpu/ccpr/GrCCPathParser.h b/src/gpu/ccpr/GrCCPathParser.h index f041610521..aff6b1069d 100644 --- a/src/gpu/ccpr/GrCCPathParser.h +++ b/src/gpu/ccpr/GrCCPathParser.h @@ -10,7 +10,6 @@ #include "GrMesh.h" #include "GrNonAtomicRef.h" -#include "GrTessellator.h" #include "SkRect.h" #include "SkRefCnt.h" #include "ccpr/GrCCCoverageProcessor.h" @@ -77,13 +76,8 @@ private: // Every kBeginPath verb has a corresponding PathInfo entry. struct PathInfo { - PathInfo(ScissorMode scissorMode, int16_t offsetX, int16_t offsetY) - : fScissorMode(scissorMode), fAtlasOffsetX(offsetX), fAtlasOffsetY(offsetY) {} - ScissorMode fScissorMode; int16_t fAtlasOffsetX, fAtlasOffsetY; - std::unique_ptr fFanTessellation; - int fFanTessellationCount = 0; }; // Defines a batch of CCPR primitives. Start indices are deduced by looking at the previous @@ -91,7 +85,6 @@ private: struct CoverageCountBatch { PrimitiveTallies fEndNonScissorIndices; int fEndScissorSubBatchIdx; - PrimitiveTallies fTotalPrimitiveCounts; }; // Defines a sub-batch from CoverageCountBatch that will be drawn with the given scissor rect. @@ -105,8 +98,8 @@ private: void endContourIfNeeded(bool insideContour); void drawRenderPass(GrOpFlushState*, const GrPipeline&, CoverageCountBatchID, - GrCCCoverageProcessor::RenderPass, GrCCCoverageProcessor::WindMethod, - int PrimitiveTallies::*instanceType, const SkIRect& drawBounds) const; + GrCCCoverageProcessor::RenderPass, int PrimitiveTallies::*instanceType, + const SkIRect& drawBounds) const; // Staging area for the path being parsed. SkDEBUGCODE(int fParsingPath = false); @@ -114,7 +107,6 @@ private: int fCurrPathPointsIdx; int fCurrPathVerbsIdx; PrimitiveTallies fCurrPathPrimitiveCounts; - SkPath::FillType fCurrPathFillType; GrCCGeometry fGeometry; SkSTArray<32, PathInfo, true> fPathsInfo; -- cgit v1.2.3