Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(628)

Unified Diff: src/gpu/batches/GrPLSPathRenderer.cpp

Issue 1626553002: Revert of added support for PLS path rendering (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/batches/GrPLSPathRenderer.h ('k') | src/gpu/effects/GrCoverageSetOpXP.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/batches/GrPLSPathRenderer.cpp
diff --git a/src/gpu/batches/GrPLSPathRenderer.cpp b/src/gpu/batches/GrPLSPathRenderer.cpp
deleted file mode 100644
index 7f8eaa4da94ca006bba8c5c2e6df23aa9a8e2ba1..0000000000000000000000000000000000000000
--- a/src/gpu/batches/GrPLSPathRenderer.cpp
+++ /dev/null
@@ -1,1011 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrPLSPathRenderer.h"
-
-#include "SkChunkAlloc.h"
-#include "SkGeometry.h"
-#include "SkPathPriv.h"
-#include "SkString.h"
-#include "SkTSort.h"
-#include "SkTraceEvent.h"
-#include "GrBatchFlushState.h"
-#include "GrBatchTest.h"
-#include "GrCaps.h"
-#include "GrContext.h"
-#include "GrDefaultGeoProcFactory.h"
-#include "GrPLSGeometryProcessor.h"
-#include "GrInvariantOutput.h"
-#include "GrPathUtils.h"
-#include "GrProcessor.h"
-#include "GrPipelineBuilder.h"
-#include "GrStrokeInfo.h"
-#include "GrTessellator.h"
-#include "batches/GrVertexBatch.h"
-#include "glsl/GrGLSLGeometryProcessor.h"
-#include "gl/builders/GrGLProgramBuilder.h"
-#include "glsl/GrGLSLPLSPathRendering.h"
-
-GrPLSPathRenderer::GrPLSPathRenderer() {
-}
-
-struct PLSVertex {
- SkPoint fPos;
- // for triangles, these are the three triangle vertices
- // for quads, vert1 is the texture UV coords, and vert2 and vert3 are the line segment
- // comprising the flat edge of the quad
- SkPoint fVert1;
- SkPoint fVert2;
- SkPoint fVert3;
- int fWinding;
-};
-typedef SkTArray<PLSVertex, true> PLSVertices;
-
-typedef SkTArray<SkPoint, true> FinishVertices;
-
-static const float kCubicTolerance = 0.5f;
-static const float kConicTolerance = 0.5f;
-
-static const float kBloatSize = 1.0f;
-
-static const float kBloatLimit = 640000.0f;
-
-#define kQuadNumVertices 5
-static void add_quad(SkPoint pts[3], PLSVertices& vertices) {
- SkPoint normal = SkPoint::Make(pts[0].fY - pts[2].fY,
- pts[2].fX - pts[0].fX);
- normal.setLength(kBloatSize);
- SkScalar cross = (pts[1] - pts[0]).cross(pts[2] - pts[0]);
- if (cross < 0) {
- normal = -normal;
- }
- PLSVertex quad[kQuadNumVertices];
- quad[0].fPos = pts[0] + normal;
- quad[1].fPos = pts[0] - normal;
- quad[2].fPos = pts[1] - normal;
- quad[3].fPos = pts[2] - normal;
- quad[4].fPos = pts[2] + normal;
- for (int i = 0; i < kQuadNumVertices; i++) {
- quad[i].fWinding = cross < 0 ? 1 : -1;
- if (cross > 0.0) {
- quad[i].fVert2 = pts[0];
- quad[i].fVert3 = pts[2];
- }
- else {
- quad[i].fVert2 = pts[2];
- quad[i].fVert3 = pts[0];
- }
- }
- GrPathUtils::QuadUVMatrix DevToUV(pts);
- DevToUV.apply<kQuadNumVertices, sizeof(PLSVertex), sizeof(SkPoint)>(quad);
- for (int i = 2; i < kQuadNumVertices; i++) {
- vertices.push_back(quad[0]);
- vertices.push_back(quad[i - 1]);
- vertices.push_back(quad[i]);
- }
-}
-
-/* Used by bloat_tri; outsets a single point. */
-static bool outset(SkPoint* p1, SkPoint line1, SkPoint line2) {
- // rotate the two line vectors 90 degrees to form the normals, and compute
- // the dot product of the normals
- SkScalar dotProd = line1.fY * line2.fY + line1.fX * line2.fX;
- SkScalar lengthSq = 1.0f / ((1.0f - dotProd) / 2.0f);
- if (lengthSq > kBloatLimit) {
- return false;
- }
- SkPoint bisector = line1 + line2;
- bisector.setLength(SkScalarSqrt(lengthSq) * kBloatSize);
- *p1 += bisector;
- return true;
-}
-
-/* Bloats a triangle so as to create a border kBloatSize pixels wide all around it. */
-static bool bloat_tri(SkPoint pts[3]) {
- SkPoint line1 = pts[0] - pts[1];
- line1.normalize();
- SkPoint line2 = pts[0] - pts[2];
- line2.normalize();
- SkPoint line3 = pts[1] - pts[2];
- line3.normalize();
-
- SkPoint result[3];
- result[0] = pts[0];
- if (!outset(&result[0], line1, line2)) {
- return false;
- }
- result[1] = pts[1];
- if (!outset(&result[1], -line1, line3)) {
- return false;
- }
- result[2] = pts[2];
- if (!outset(&result[2], -line3, -line2)) {
- return false;
- }
- pts[0] = result[0];
- pts[1] = result[1];
- pts[2] = result[2];
- return true;
-}
-
-static bool get_geometry(const SkPath& path, const SkMatrix& m, PLSVertices& triVertices,
- PLSVertices& quadVertices, GrResourceProvider* resourceProvider,
- SkRect bounds) {
- SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
- SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, m, bounds);
- int contourCnt;
- int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol);
- if (maxPts <= 0) {
- return 0;
- }
- SkPath linesOnlyPath;
- linesOnlyPath.setFillType(path.getFillType());
- SkSTArray<15, SkPoint, true> quadPoints;
- SkPathPriv::FirstDirection dir = SkPathPriv::FirstDirection::kUnknown_FirstDirection;
- SkPath::Iter iter(path, true);
- bool done = false;
- while (!done) {
- SkPoint pts[4];
- SkPath::Verb verb = iter.next(pts);
- switch (verb) {
- case SkPath::kMove_Verb:
- SkASSERT(quadPoints.count() % 3 == 0);
- for (int i = 0; i < quadPoints.count(); i += 3) {
- add_quad(&quadPoints[i], quadVertices);
- }
- quadPoints.reset();
- m.mapPoints(&pts[0], 1);
- linesOnlyPath.moveTo(pts[0]);
- break;
- case SkPath::kLine_Verb:
- m.mapPoints(&pts[1], 1);
- linesOnlyPath.lineTo(pts[1]);
- break;
- case SkPath::kQuad_Verb:
- m.mapPoints(pts, 3);
- linesOnlyPath.lineTo(pts[2]);
- quadPoints.push_back(pts[0]);
- quadPoints.push_back(pts[1]);
- quadPoints.push_back(pts[2]);
- break;
- case SkPath::kCubic_Verb: {
- m.mapPoints(pts, 4);
- SkSTArray<15, SkPoint, true> quads;
- GrPathUtils::convertCubicToQuads(pts, kCubicTolerance, false, dir, &quads);
- int count = quads.count();
- for (int q = 0; q < count; q += 3) {
- linesOnlyPath.lineTo(quads[q + 2]);
- quadPoints.push_back(quads[q]);
- quadPoints.push_back(quads[q + 1]);
- quadPoints.push_back(quads[q + 2]);
- }
- break;
- }
- case SkPath::kConic_Verb: {
- m.mapPoints(pts, 3);
- SkScalar weight = iter.conicWeight();
- SkAutoConicToQuads converter;
- const SkPoint* quads = converter.computeQuads(pts, weight, kConicTolerance);
- int count = converter.countQuads();
- for (int i = 0; i < count; ++i) {
- linesOnlyPath.lineTo(quads[2 * i + 2]);
- quadPoints.push_back(quads[2 * i]);
- quadPoints.push_back(quads[2 * i + 1]);
- quadPoints.push_back(quads[2 * i + 2]);
- }
- break;
- }
- case SkPath::kClose_Verb:
- linesOnlyPath.close();
- break;
- case SkPath::kDone_Verb:
- done = true;
- break;
- default: SkASSERT(false);
- }
- }
- SkASSERT(quadPoints.count() % 3 == 0);
- for (int i = 0; i < quadPoints.count(); i += 3) {
- add_quad(&quadPoints[i], quadVertices);
- }
-
- static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
- GrUniqueKey key;
- GrUniqueKey::Builder builder(&key, kDomain, 2);
- builder[0] = path.getGenerationID();
- builder[1] = path.getFillType();
- builder.finish();
- GrTessellator::WindingVertex* windingVertices;
- int triVertexCount = GrTessellator::PathToVertices(linesOnlyPath, 0, bounds, &windingVertices);
- if (triVertexCount > 0) {
- for (int i = 0; i < triVertexCount; i += 3) {
- SkPoint p1 = windingVertices[i].fPos;
- SkPoint p2 = windingVertices[i + 1].fPos;
- SkPoint p3 = windingVertices[i + 2].fPos;
- int winding = windingVertices[i].fWinding;
- SkASSERT(windingVertices[i + 1].fWinding == winding);
- SkASSERT(windingVertices[i + 2].fWinding == winding);
- SkScalar cross = (p2 - p1).cross(p3 - p1);
- SkPoint bloated[3] = { p1, p2, p3 };
- if (cross < 0.0f) {
- SkTSwap(p1, p3);
- }
- if (bloat_tri(bloated)) {
- triVertices.push_back({ bloated[0], p1, p2, p3, winding });
- triVertices.push_back({ bloated[1], p1, p2, p3, winding });
- triVertices.push_back({ bloated[2], p1, p2, p3, winding });
- }
- else {
- SkScalar minX = SkTMin(p1.fX, SkTMin(p2.fX, p3.fX)) - 1.0f;
- SkScalar minY = SkTMin(p1.fY, SkTMin(p2.fY, p3.fY)) - 1.0f;
- SkScalar maxX = SkTMax(p1.fX, SkTMax(p2.fX, p3.fX)) + 1.0f;
- SkScalar maxY = SkTMax(p1.fY, SkTMax(p2.fY, p3.fY)) + 1.0f;
- triVertices.push_back({ { minX, minY }, p1, p2, p3, winding });
- triVertices.push_back({ { maxX, minY }, p1, p2, p3, winding });
- triVertices.push_back({ { minX, maxY }, p1, p2, p3, winding });
- triVertices.push_back({ { maxX, minY }, p1, p2, p3, winding });
- triVertices.push_back({ { maxX, maxY }, p1, p2, p3, winding });
- triVertices.push_back({ { minX, maxY }, p1, p2, p3, winding });
- }
- }
- delete[] windingVertices;
- }
- return triVertexCount > 0 || quadVertices.count() > 0;
-}
-
-class PLSAATriangleEffect : public GrPLSGeometryProcessor {
-public:
-
- static GrPLSGeometryProcessor* Create(const SkMatrix& localMatrix,
- bool usesLocalCoords) {
- return new PLSAATriangleEffect(localMatrix, usesLocalCoords);
- }
-
- virtual ~PLSAATriangleEffect() {}
-
- const char* name() const override { return "PLSAATriangle"; }
-
- const Attribute* inPosition() const { return fInPosition; }
- const Attribute* inVertex1() const { return fInVertex1; }
- const Attribute* inVertex2() const { return fInVertex2; }
- const Attribute* inVertex3() const { return fInVertex3; }
- const Attribute* inWindings() const { return fInWindings; }
- const SkMatrix& localMatrix() const { return fLocalMatrix; }
- bool usesLocalCoords() const { return fUsesLocalCoords; }
-
- class GLSLProcessor : public GrGLSLGeometryProcessor {
- public:
- GLSLProcessor(const GrGeometryProcessor&) {}
-
- void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
- const PLSAATriangleEffect& te = args.fGP.cast<PLSAATriangleEffect>();
- GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
- GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-
- varyingHandler->emitAttributes(te);
-
- this->setupPosition(vsBuilder, gpArgs, te.inPosition()->fName);
-
- GrGLSLVertToFrag v1(kVec2f_GrSLType);
- varyingHandler->addVarying("Vertex1", &v1, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);",
- v1.vsOut(),
- te.inVertex1()->fName,
- te.inVertex1()->fName);
-
- GrGLSLVertToFrag v2(kVec2f_GrSLType);
- varyingHandler->addVarying("Vertex2", &v2, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);",
- v2.vsOut(),
- te.inVertex2()->fName,
- te.inVertex2()->fName);
-
- GrGLSLVertToFrag v3(kVec2f_GrSLType);
- varyingHandler->addVarying("Vertex3", &v3, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);",
- v3.vsOut(),
- te.inVertex3()->fName,
- te.inVertex3()->fName);
-
- GrGLSLVertToFrag delta1(kVec2f_GrSLType);
- varyingHandler->addVarying("delta1", &delta1, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;",
- delta1.vsOut(), v1.vsOut(), v2.vsOut(), v2.vsOut(), v1.vsOut());
-
- GrGLSLVertToFrag delta2(kVec2f_GrSLType);
- varyingHandler->addVarying("delta2", &delta2, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;",
- delta2.vsOut(), v2.vsOut(), v3.vsOut(), v3.vsOut(), v2.vsOut());
-
- GrGLSLVertToFrag delta3(kVec2f_GrSLType);
- varyingHandler->addVarying("delta3", &delta3, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;",
- delta3.vsOut(), v3.vsOut(), v1.vsOut(), v1.vsOut(), v3.vsOut());
-
- GrGLSLVertToFrag windings(kInt_GrSLType);
- varyingHandler->addVarying("windings", &windings, kLow_GrSLPrecision);
- vsBuilder->codeAppendf("%s = %s;",
- windings.vsOut(), te.inWindings()->fName);
-
- // emit transforms
- this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
- te.inPosition()->fName, te.localMatrix(), args.fTransformsIn,
- args.fTransformsOut);
-
- GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
- SkAssertResult(fsBuilder->enableFeature(
- GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature));
- SkAssertResult(fsBuilder->enableFeature(
- GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
- fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL);
- // Compute four subsamples, each shifted a quarter pixel along x and y from
- // gl_FragCoord. The oriented box positioning of the subsamples is of course not
- // optimal, but it greatly simplifies the math and this simplification is necessary for
- // performance reasons.
- fsBuilder->codeAppendf("highp vec2 firstSample = %s.xy - vec2(0.25);",
- fsBuilder->fragmentPosition());
- fsBuilder->codeAppendf("highp vec2 delta1 = %s;", delta1.fsIn());
- fsBuilder->codeAppendf("highp vec2 delta2 = %s;", delta2.fsIn());
- fsBuilder->codeAppendf("highp vec2 delta3 = %s;", delta3.fsIn());
- // Check whether first sample is inside the triangle by computing three dot products. If
- // all are < 0, we're inside. The first vector in each case is half of what it is
- // "supposed" to be, because we re-use them later as adjustment factors for which half
- // is the correct value, so we multiply the dots by two to compensate.
- fsBuilder->codeAppendf("highp float d1 = dot(delta1, (firstSample - %s).yx) * 2.0;",
- v1.fsIn());
- fsBuilder->codeAppendf("highp float d2 = dot(delta2, (firstSample - %s).yx) * 2.0;",
- v2.fsIn());
- fsBuilder->codeAppendf("highp float d3 = dot(delta3, (firstSample - %s).yx) * 2.0;",
- v3.fsIn());
- fsBuilder->codeAppend("highp float dmax = max(d1, max(d2, d3));");
- fsBuilder->codeAppendf("pls.windings[0] += (dmax <= 0.0) ? %s : 0;", windings.fsIn());
- // for subsequent samples, we don't recalculate the entire dot product -- just adjust it
- // to the value it would have if we did recompute it.
- fsBuilder->codeAppend("d1 += delta1.x;");
- fsBuilder->codeAppend("d2 += delta2.x;");
- fsBuilder->codeAppend("d3 += delta3.x;");
- fsBuilder->codeAppend("dmax = max(d1, max(d2, d3));");
- fsBuilder->codeAppendf("pls.windings[1] += (dmax <= 0.0) ? %s : 0;", windings.fsIn());
- fsBuilder->codeAppend("d1 += delta1.y;");
- fsBuilder->codeAppend("d2 += delta2.y;");
- fsBuilder->codeAppend("d3 += delta3.y;");
- fsBuilder->codeAppend("dmax = max(d1, max(d2, d3));");
- fsBuilder->codeAppendf("pls.windings[2] += (dmax <= 0.0) ? %s : 0;", windings.fsIn());
- fsBuilder->codeAppend("d1 -= delta1.x;");
- fsBuilder->codeAppend("d2 -= delta2.x;");
- fsBuilder->codeAppend("d3 -= delta3.x;");
- fsBuilder->codeAppend("dmax = max(d1, max(d2, d3));");
- fsBuilder->codeAppendf("pls.windings[3] += (dmax <= 0.0) ? %s : 0;", windings.fsIn());
- }
-
- static inline void GenKey(const GrGeometryProcessor& gp,
- const GrGLSLCaps&,
- GrProcessorKeyBuilder* b) {
- const PLSAATriangleEffect& te = gp.cast<PLSAATriangleEffect>();
- uint32_t key = 0;
- key |= te.localMatrix().hasPerspective() ? 0x1 : 0x0;
- b->add32(key);
- }
-
- virtual void setData(const GrGLSLProgramDataManager& pdman,
- const GrPrimitiveProcessor& gp) override {
- }
-
- void setTransformData(const GrPrimitiveProcessor& primProc,
- const GrGLSLProgramDataManager& pdman,
- int index,
- const SkTArray<const GrCoordTransform*, true>& transforms) override {
- this->setTransformDataHelper<PLSAATriangleEffect>(primProc, pdman, index, transforms);
- }
-
- private:
- typedef GrGLSLGeometryProcessor INHERITED;
- };
-
- 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:
- PLSAATriangleEffect(const SkMatrix& localMatrix, bool usesLocalCoords)
- : fLocalMatrix(localMatrix)
- , fUsesLocalCoords(usesLocalCoords) {
- this->initClassID<PLSAATriangleEffect>();
- fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInVertex1 = &this->addVertexAttrib(Attribute("inVertex1", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInVertex2 = &this->addVertexAttrib(Attribute("inVertex2", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInVertex3 = &this->addVertexAttrib(Attribute("inVertex3", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInWindings = &this->addVertexAttrib(Attribute("inWindings", kInt_GrVertexAttribType,
- kLow_GrSLPrecision));
- this->setWillReadFragmentPosition();
- }
-
- const Attribute* fInPosition;
- const Attribute* fInVertex1;
- const Attribute* fInVertex2;
- const Attribute* fInVertex3;
- const Attribute* fInWindings;
- SkMatrix fLocalMatrix;
- bool fUsesLocalCoords;
-
- GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
-
- typedef GrGeometryProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-/*
- * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
- * two components of the vertex attribute. Coverage is based on signed
- * distance with negative being inside, positive outside. The edge is specified in
- * window space (y-down). If either the third or fourth component of the interpolated
- * vertex coord is > 0 then the pixel is considered outside the edge. This is used to
- * attempt to trim to a portion of the infinite quad.
- * Requires shader derivative instruction support.
- */
-
-class PLSQuadEdgeEffect : public GrPLSGeometryProcessor {
-public:
-
- static GrPLSGeometryProcessor* Create(const SkMatrix& localMatrix,
- bool usesLocalCoords) {
- return new PLSQuadEdgeEffect(localMatrix, usesLocalCoords);
- }
-
- virtual ~PLSQuadEdgeEffect() {}
-
- const char* name() const override { return "PLSQuadEdge"; }
-
- const Attribute* inPosition() const { return fInPosition; }
- const Attribute* inUV() const { return fInUV; }
- const Attribute* inEndpoint1() const { return fInEndpoint1; }
- const Attribute* inEndpoint2() const { return fInEndpoint2; }
- const Attribute* inWindings() const { return fInWindings; }
- const SkMatrix& localMatrix() const { return fLocalMatrix; }
- bool usesLocalCoords() const { return fUsesLocalCoords; }
-
- class GLSLProcessor : public GrGLSLGeometryProcessor {
- public:
- GLSLProcessor(const GrGeometryProcessor&) {}
-
- void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
- const PLSQuadEdgeEffect& qe = args.fGP.cast<PLSQuadEdgeEffect>();
- GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
- GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-
- // emit attributes
- varyingHandler->emitAttributes(qe);
-
- GrGLSLVertToFrag uv(kVec2f_GrSLType);
- varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qe.inUV()->fName);
-
- GrGLSLVertToFrag ep1(kVec2f_GrSLType);
- varyingHandler->addVarying("endpoint1", &ep1, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);", ep1.vsOut(),
- qe.inEndpoint1()->fName, qe.inEndpoint1()->fName);
-
- GrGLSLVertToFrag ep2(kVec2f_GrSLType);
- varyingHandler->addVarying("endpoint2", &ep2, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);", ep2.vsOut(),
- qe.inEndpoint2()->fName, qe.inEndpoint2()->fName);
-
- GrGLSLVertToFrag delta(kVec2f_GrSLType);
- varyingHandler->addVarying("delta", &delta, kHigh_GrSLPrecision);
- vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;",
- delta.vsOut(), ep1.vsOut(), ep2.vsOut(), ep2.vsOut(),
- ep1.vsOut());
-
- GrGLSLVertToFrag windings(kInt_GrSLType);
- varyingHandler->addVarying("windings", &windings, kLow_GrSLPrecision);
- vsBuilder->codeAppendf("%s = %s;",
- windings.vsOut(), qe.inWindings()->fName);
-
- // Setup position
- this->setupPosition(vsBuilder, gpArgs, qe.inPosition()->fName);
-
- // emit transforms
- this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
- qe.inPosition()->fName, qe.localMatrix(), args.fTransformsIn,
- args.fTransformsOut);
-
- GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
- SkAssertResult(fsBuilder->enableFeature(
- GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature));
- SkAssertResult(fsBuilder->enableFeature(
- GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
- static const int QUAD_ARGS = 2;
- GrGLSLShaderVar inQuadArgs[QUAD_ARGS] = {
- GrGLSLShaderVar("dot", kFloat_GrSLType, 0, kHigh_GrSLPrecision),
- GrGLSLShaderVar("uv", kVec2f_GrSLType, 0, kHigh_GrSLPrecision)
- };
- SkString inQuadName;
-
- const char* inQuadCode = "if (uv.x * uv.x <= uv.y) {"
- "return dot >= 0.0;"
- "} else {"
- "return false;"
- "}";
- fsBuilder->emitFunction(kBool_GrSLType, "in_quad", QUAD_ARGS, inQuadArgs, inQuadCode,
- &inQuadName);
- fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL);
- // keep the derivative instructions outside the conditional
- fsBuilder->codeAppendf("highp vec2 uvdX = dFdx(%s);", uv.fsIn());
- fsBuilder->codeAppendf("highp vec2 uvdY = dFdy(%s);", uv.fsIn());
- fsBuilder->codeAppend("highp vec2 uvIncX = uvdX * 0.45 + uvdY * -0.1;");
- fsBuilder->codeAppend("highp vec2 uvIncY = uvdX * 0.1 + uvdY * 0.55;");
- fsBuilder->codeAppendf("highp vec2 uv = %s.xy - uvdX * 0.35 - uvdY * 0.25;",
- uv.fsIn());
- fsBuilder->codeAppendf("highp vec2 firstSample = %s.xy - vec2(0.25);",
- fsBuilder->fragmentPosition());
- fsBuilder->codeAppendf("highp float d = dot(%s, (firstSample - %s).yx) * 2.0;",
- delta.fsIn(), ep1.fsIn());
- fsBuilder->codeAppendf("pls.windings[0] += %s(d, uv) ? %s : 0;", inQuadName.c_str(),
- windings.fsIn());
- fsBuilder->codeAppend("uv += uvIncX;");
- fsBuilder->codeAppendf("d += %s.x;", delta.fsIn());
- fsBuilder->codeAppendf("pls.windings[1] += %s(d, uv) ? %s : 0;", inQuadName.c_str(),
- windings.fsIn());
- fsBuilder->codeAppend("uv += uvIncY;");
- fsBuilder->codeAppendf("d += %s.y;", delta.fsIn());
- fsBuilder->codeAppendf("pls.windings[2] += %s(d, uv) ? %s : 0;", inQuadName.c_str(),
- windings.fsIn());
- fsBuilder->codeAppend("uv -= uvIncX;");
- fsBuilder->codeAppendf("d -= %s.x;", delta.fsIn());
- fsBuilder->codeAppendf("pls.windings[3] += %s(d, uv) ? %s : 0;", inQuadName.c_str(),
- windings.fsIn());
- }
-
- static inline void GenKey(const GrGeometryProcessor& gp,
- const GrGLSLCaps&,
- GrProcessorKeyBuilder* b) {
- const PLSQuadEdgeEffect& qee = gp.cast<PLSQuadEdgeEffect>();
- uint32_t key = 0;
- key |= qee.usesLocalCoords() && qee.localMatrix().hasPerspective() ? 0x1 : 0x0;
- b->add32(key);
- }
-
- virtual void setData(const GrGLSLProgramDataManager& pdman,
- const GrPrimitiveProcessor& gp) override {
- }
-
- void setTransformData(const GrPrimitiveProcessor& primProc,
- const GrGLSLProgramDataManager& pdman,
- int index,
- const SkTArray<const GrCoordTransform*, true>& transforms) override {
- this->setTransformDataHelper<PLSQuadEdgeEffect>(primProc, pdman, index, transforms);
- }
-
- private:
- typedef GrGLSLGeometryProcessor INHERITED;
- };
-
- 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:
- PLSQuadEdgeEffect(const SkMatrix& localMatrix, bool usesLocalCoords)
- : fLocalMatrix(localMatrix)
- , fUsesLocalCoords(usesLocalCoords) {
- this->initClassID<PLSQuadEdgeEffect>();
- fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInUV = &this->addVertexAttrib(Attribute("inUV", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInEndpoint1 = &this->addVertexAttrib(Attribute("inEndpoint1", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInEndpoint2 = &this->addVertexAttrib(Attribute("inEndpoint2", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- fInWindings = &this->addVertexAttrib(Attribute("inWindings", kInt_GrVertexAttribType,
- kLow_GrSLPrecision));
- this->setWillReadFragmentPosition();
- }
-
- const Attribute* fInPosition;
- const Attribute* fInUV;
- const Attribute* fInEndpoint1;
- const Attribute* fInEndpoint2;
- const Attribute* fInWindings;
- SkMatrix fLocalMatrix;
- bool fUsesLocalCoords;
-
- GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
-
- typedef GrGeometryProcessor INHERITED;
-};
-
-class PLSFinishEffect : public GrGeometryProcessor {
-public:
-
- static GrGeometryProcessor* Create(GrColor color, bool useEvenOdd, const SkMatrix& localMatrix,
- bool usesLocalCoords) {
- return new PLSFinishEffect(color, useEvenOdd, localMatrix, usesLocalCoords);
- }
-
- virtual ~PLSFinishEffect() {}
-
- const char* name() const override { return "PLSFinish"; }
-
- const Attribute* inPosition() const { return fInPosition; }
- GrColor color() const { return fColor; }
- bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
- const SkMatrix& localMatrix() const { return fLocalMatrix; }
- bool usesLocalCoords() const { return fUsesLocalCoords; }
-
- GrPixelLocalStorageState getPixelLocalStorageState() const override {
- return GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState;
- }
-
- const char* getDestColorOverride() const override {
- return GR_GL_PLS_DSTCOLOR_NAME;
- }
-
- class GLSLProcessor : public GrGLSLGeometryProcessor {
- public:
- GLSLProcessor(const GrGeometryProcessor&) {}
-
- void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
- const PLSFinishEffect& fe = args.fGP.cast<PLSFinishEffect>();
- GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
- GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
- GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-
- fUseEvenOdd = uniformHandler->addUniform(GrGLUniformHandler::kFragment_Visibility,
- kFloat_GrSLType, kLow_GrSLPrecision,
- "useEvenOdd");
- const char* useEvenOdd = uniformHandler->getUniformCStr(fUseEvenOdd);
-
- varyingHandler->emitAttributes(fe);
- this->setupPosition(vsBuilder, gpArgs, fe.inPosition()->fName);
- this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
- fe.inPosition()->fName, fe.localMatrix(), args.fTransformsIn,
- args.fTransformsOut);
-
- GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
- SkAssertResult(fsBuilder->enableFeature(
- GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature));
- fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL);
- fsBuilder->codeAppend("float coverage;");
- fsBuilder->codeAppendf("if (%s != 0.0) {", useEvenOdd);
- fsBuilder->codeAppend("coverage = float(abs(pls.windings[0]) % 2) * 0.25;");
- fsBuilder->codeAppend("coverage += float(abs(pls.windings[1]) % 2) * 0.25;");
- fsBuilder->codeAppend("coverage += float(abs(pls.windings[2]) % 2) * 0.25;");
- fsBuilder->codeAppend("coverage += float(abs(pls.windings[3]) % 2) * 0.25;");
- fsBuilder->codeAppend("} else {");
- fsBuilder->codeAppend("coverage = pls.windings[0] != 0 ? 0.25 : 0.0;");
- fsBuilder->codeAppend("coverage += pls.windings[1] != 0 ? 0.25 : 0.0;");
- fsBuilder->codeAppend("coverage += pls.windings[2] != 0 ? 0.25 : 0.0;");
- fsBuilder->codeAppend("coverage += pls.windings[3] != 0 ? 0.25 : 0.0;");
- fsBuilder->codeAppend("}");
- if (!fe.colorIgnored()) {
- this->setupUniformColor(fsBuilder, uniformHandler, args.fOutputColor,
- &fColorUniform);
- }
- fsBuilder->codeAppendf("%s = vec4(coverage);", args.fOutputCoverage);
- }
-
- static inline void GenKey(const GrGeometryProcessor& gp,
- const GrGLSLCaps&,
- GrProcessorKeyBuilder* b) {
- const PLSFinishEffect& fe = gp.cast<PLSFinishEffect>();
- uint32_t key = 0;
- key |= fe.usesLocalCoords() && fe.localMatrix().hasPerspective() ? 0x1 : 0x0;
- b->add32(key);
- }
-
- virtual void setData(const GrGLSLProgramDataManager& pdman,
- const GrPrimitiveProcessor& gp) override {
- const PLSFinishEffect& fe = gp.cast<PLSFinishEffect>();
- pdman.set1f(fUseEvenOdd, fe.fUseEvenOdd);
- if (fe.color() != fColor && !fe.colorIgnored()) {
- GrGLfloat c[4];
- GrColorToRGBAFloat(fe.color(), c);
- pdman.set4fv(fColorUniform, 1, c);
- fColor = fe.color();
- }
- }
-
- void setTransformData(const GrPrimitiveProcessor& primProc,
- const GrGLSLProgramDataManager& pdman,
- int index,
- const SkTArray<const GrCoordTransform*, true>& transforms) override {
- this->setTransformDataHelper<PLSFinishEffect>(primProc, pdman, index, transforms);
- }
-
- private:
- GrColor fColor;
- UniformHandle fColorUniform;
- UniformHandle fUseEvenOdd;
-
- typedef GrGLSLGeometryProcessor INHERITED;
- };
-
- 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:
- PLSFinishEffect(GrColor color, bool useEvenOdd, const SkMatrix& localMatrix,
- bool usesLocalCoords)
- : fColor(color)
- , fUseEvenOdd(useEvenOdd)
- , fLocalMatrix(localMatrix)
- , fUsesLocalCoords(usesLocalCoords) {
- this->initClassID<PLSFinishEffect>();
- fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
- kHigh_GrSLPrecision));
- }
-
- const Attribute* fInPosition;
- GrColor fColor;
- bool fUseEvenOdd;
- SkMatrix fLocalMatrix;
- bool fUsesLocalCoords;
-
- typedef GrGeometryProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-bool GrPLSPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
- // We have support for even-odd rendering, but are having some troublesome
- // seams. Disable in the presence of even-odd for now.
- return args.fShaderCaps->shaderDerivativeSupport() && args.fAntiAlias &&
- args.fStroke->isFillStyle() && !args.fPath->isInverseFillType() &&
- args.fPath->getFillType() == SkPath::FillType::kWinding_FillType;
-}
-
-class PLSPathBatch : public GrVertexBatch {
-public:
- DEFINE_BATCH_CLASS_ID
- struct Geometry {
- GrColor fColor;
- SkMatrix fViewMatrix;
- SkPath fPath;
- };
-
- static GrDrawBatch* Create(const Geometry& geometry) {
- return new PLSPathBatch(geometry);
- }
-
- const char* name() const override { return "PLSBatch"; }
-
- 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->setUnknownSingleComponent();
- overrides->fUsePLSDstRead = true;
- }
-
- void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
- // Handle any color overrides
- if (!overrides.readsColor()) {
- fGeoData[0].fColor = GrColor_ILLEGAL;
- }
- overrides.getOverrideColorIfSet(&fGeoData[0].fColor);
-
- // setup batch properties
- fBatch.fColorIgnored = !overrides.readsColor();
- fBatch.fColor = fGeoData[0].fColor;
- fBatch.fUsesLocalCoords = overrides.readsLocalCoords();
- fBatch.fCoverageIgnored = !overrides.readsCoverage();
- fBatch.fCanTweakAlphaForCoverage = overrides.canTweakAlphaForCoverage();
- }
-
- void onPrepareDraws(Target* target) const override {
- int instanceCount = fGeoData.count();
-
- SkMatrix invert;
- if (this->usesLocalCoords() && !this->viewMatrix().invert(&invert)) {
- SkDebugf("Could not invert viewmatrix\n");
- return;
- }
-
- // Setup GrGeometryProcessors
- SkAutoTUnref<GrPLSGeometryProcessor> triangleProcessor(
- PLSAATriangleEffect::Create(invert, this->usesLocalCoords()));
- SkAutoTUnref<GrPLSGeometryProcessor> quadProcessor(
- PLSQuadEdgeEffect::Create(invert, this->usesLocalCoords()));
-
- GrResourceProvider* rp = target->resourceProvider();
- for (int i = 0; i < instanceCount; ++i) {
- const Geometry& args = fGeoData[i];
- SkRect bounds = args.fPath.getBounds();
- args.fViewMatrix.mapRect(&bounds);
- bounds.fLeft = SkScalarFloorToScalar(bounds.fLeft);
- bounds.fTop = SkScalarFloorToScalar(bounds.fTop);
- bounds.fRight = SkScalarCeilToScalar(bounds.fRight);
- bounds.fBottom = SkScalarCeilToScalar(bounds.fBottom);
- triangleProcessor->setBounds(bounds);
- quadProcessor->setBounds(bounds);
-
- // We use the fact that SkPath::transform path does subdivision based on
- // perspective. Otherwise, we apply the view matrix when copying to the
- // segment representation.
- const SkMatrix* viewMatrix = &args.fViewMatrix;
-
- // We avoid initializing the path unless we have to
- const SkPath* pathPtr = &args.fPath;
- SkTLazy<SkPath> tmpPath;
- if (viewMatrix->hasPerspective()) {
- SkPath* tmpPathPtr = tmpPath.init(*pathPtr);
- tmpPathPtr->setIsVolatile(true);
- tmpPathPtr->transform(*viewMatrix);
- viewMatrix = &SkMatrix::I();
- pathPtr = tmpPathPtr;
- }
-
- GrVertices grVertices;
-
- PLSVertices triVertices;
- PLSVertices quadVertices;
- if (!get_geometry(*pathPtr, *viewMatrix, triVertices, quadVertices, rp, bounds)) {
- continue;
- }
-
- if (triVertices.count()) {
- const GrVertexBuffer* triVertexBuffer;
- int firstTriVertex;
- size_t triStride = triangleProcessor->getVertexStride();
- PLSVertex* triVerts = reinterpret_cast<PLSVertex*>(target->makeVertexSpace(
- triStride, triVertices.count(), &triVertexBuffer, &firstTriVertex));
- if (!triVerts) {
- SkDebugf("Could not allocate vertices\n");
- return;
- }
- for (int i = 0; i < triVertices.count(); ++i) {
- triVerts[i] = triVertices[i];
- }
- grVertices.init(kTriangles_GrPrimitiveType, triVertexBuffer, firstTriVertex,
- triVertices.count());
- target->initDraw(triangleProcessor, this->pipeline());
- target->draw(grVertices);
- }
-
- if (quadVertices.count()) {
- const GrVertexBuffer* quadVertexBuffer;
- int firstQuadVertex;
- size_t quadStride = quadProcessor->getVertexStride();
- PLSVertex* quadVerts = reinterpret_cast<PLSVertex*>(target->makeVertexSpace(
- quadStride, quadVertices.count(), &quadVertexBuffer, &firstQuadVertex));
- if (!quadVerts) {
- SkDebugf("Could not allocate vertices\n");
- return;
- }
- for (int i = 0; i < quadVertices.count(); ++i) {
- quadVerts[i] = quadVertices[i];
- }
- grVertices.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVertex,
- quadVertices.count());
- target->initDraw(quadProcessor, this->pipeline());
- target->draw(grVertices);
- }
-
- SkAutoTUnref<GrGeometryProcessor> finishProcessor(
- PLSFinishEffect::Create(this->color(),
- pathPtr->getFillType() ==
- SkPath::FillType::kEvenOdd_FillType,
- invert,
- this->usesLocalCoords()));
- const GrVertexBuffer* rectVertexBuffer;
- size_t finishStride = finishProcessor->getVertexStride();
- int firstRectVertex;
- static const int kRectVertexCount = 6;
- SkPoint* rectVerts = reinterpret_cast<SkPoint*>(target->makeVertexSpace(
- finishStride, kRectVertexCount, &rectVertexBuffer, &firstRectVertex));
- if (!rectVerts) {
- SkDebugf("Could not allocate vertices\n");
- return;
- }
- rectVerts[0] = { bounds.fLeft, bounds.fTop };
- rectVerts[1] = { bounds.fLeft, bounds.fBottom };
- rectVerts[2] = { bounds.fRight, bounds.fBottom };
- rectVerts[3] = { bounds.fLeft, bounds.fTop };
- rectVerts[4] = { bounds.fRight, bounds.fTop };
- rectVerts[5] = { bounds.fRight, bounds.fBottom };
-
- grVertices.init(kTriangles_GrPrimitiveType, rectVertexBuffer, firstRectVertex,
- kRectVertexCount);
- target->initDraw(finishProcessor, this->pipeline());
- target->draw(grVertices);
- }
- }
-
- SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
-
-private:
- PLSPathBatch(const Geometry& geometry) : INHERITED(ClassID()) {
- fGeoData.push_back(geometry);
-
- // compute bounds
- fBounds = geometry.fPath.getBounds();
- geometry.fViewMatrix.mapRect(&fBounds);
- }
-
- bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
- return false;
- }
-
- GrColor color() const { return fBatch.fColor; }
- bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
- bool canTweakAlphaForCoverage() const { return fBatch.fCanTweakAlphaForCoverage; }
- const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
- bool coverageIgnored() const { return fBatch.fCoverageIgnored; }
-
- struct BatchTracker {
- GrColor fColor;
- bool fUsesLocalCoords;
- bool fColorIgnored;
- bool fCoverageIgnored;
- bool fCanTweakAlphaForCoverage;
- };
-
- BatchTracker fBatch;
- SkSTArray<1, Geometry, true> fGeoData;
-
- typedef GrVertexBatch INHERITED;
-};
-
-SkDEBUGCODE(bool inPLSDraw = false;)
-bool GrPLSPathRenderer::onDrawPath(const DrawPathArgs& args) {
- if (args.fPath->isEmpty()) {
- return true;
- }
- SkASSERT(!inPLSDraw);
- SkDEBUGCODE(inPLSDraw = true;)
- PLSPathBatch::Geometry geometry;
- geometry.fColor = args.fColor;
- geometry.fViewMatrix = *args.fViewMatrix;
- geometry.fPath = *args.fPath;
-
- SkAutoTUnref<GrDrawBatch> batch(PLSPathBatch::Create(geometry));
- args.fTarget->drawBatch(*args.fPipelineBuilder, batch);
-
- SkDEBUGCODE(inPLSDraw = false;)
- return true;
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef GR_TEST_UTILS
-
-DRAW_BATCH_TEST_DEFINE(PLSPathBatch) {
- PLSPathBatch::Geometry geometry;
- geometry.fColor = GrRandomColor(random);
- geometry.fViewMatrix = GrTest::TestMatrixInvertible(random);
- geometry.fPath = GrTest::TestPathConvex(random);
-
- return PLSPathBatch::Create(geometry);
-}
-
-#endif
« no previous file with comments | « src/gpu/batches/GrPLSPathRenderer.h ('k') | src/gpu/effects/GrCoverageSetOpXP.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698