/*
 * 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 "GrCaps.h"
#include "GrContext.h"
#include "GrDefaultGeoProcFactory.h"
#include "GrDrawOpTest.h"
#include "GrInvariantOutput.h"
#include "GrOpFlushState.h"
#include "GrPLSGeometryProcessor.h"
#include "GrPathUtils.h"
#include "GrPipelineBuilder.h"
#include "GrProcessor.h"
#include "GrStyle.h"
#include "GrTessellator.h"
#include "SkChunkAlloc.h"
#include "SkGeometry.h"
#include "SkPathPriv.h"
#include "SkString.h"
#include "SkTSort.h"
#include "SkTraceEvent.h"
#include "gl/builders/GrGLProgramBuilder.h"
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLPLSPathRendering.h"
#include "ops/GrMeshDrawOp.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;
    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, &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->addFlatVarying("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.fFPCoordTransformHandler);

            GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
            SkAssertResult(fsBuilder->enableFeature(
                           GrGLSLFragmentShaderBuilder::kPixelLocalStorage_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 = sk_FragCoord.xy - vec2(0.25);");
            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 GrShaderCaps&,
                                  GrProcessorKeyBuilder* b) {
            const PLSAATriangleEffect& te = gp.cast<PLSAATriangleEffect>();
            uint32_t key = 0;
            key |= te.localMatrix().hasPerspective() ? 0x1 : 0x0;
            b->add32(key);
        }

        void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
                     FPCoordTransformIter&& transformIter) override {
            this->setTransformDataHelper(gp.cast<PLSAATriangleEffect>().fLocalMatrix, pdman,
                                         &transformIter);
        }

    private:
        typedef GrGLSLGeometryProcessor INHERITED;
    };

    virtual void getGLSLProcessorKey(const GrShaderCaps& caps,
                                   GrProcessorKeyBuilder* b) const override {
        GLSLProcessor::GenKey(*this, caps, b);
    }

    virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
        return new GLSLProcessor(*this);
    }

private:
    PLSAATriangleEffect(const SkMatrix& localMatrix, bool usesLocalCoords)
        : fLocalMatrix(localMatrix)
        , fUsesLocalCoords(usesLocalCoords) {
        this->initClassID<PLSAATriangleEffect>();
        fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
                                             kHigh_GrSLPrecision);
        fInVertex1 = &this->addVertexAttrib("inVertex1", kVec2f_GrVertexAttribType,
                                            kHigh_GrSLPrecision);
        fInVertex2 = &this->addVertexAttrib("inVertex2", kVec2f_GrVertexAttribType,
                                            kHigh_GrSLPrecision);
        fInVertex3 = &this->addVertexAttrib("inVertex3", kVec2f_GrVertexAttribType,
                                            kHigh_GrSLPrecision);
        fInWindings = &this->addVertexAttrib("inWindings", kInt_GrVertexAttribType,
                                             kLow_GrSLPrecision);
    }

    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->addFlatVarying("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.fFPCoordTransformHandler);

            GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
            SkAssertResult(fsBuilder->enableFeature(
                           GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature));
            static const int QUAD_ARGS = 2;
            GrShaderVar inQuadArgs[QUAD_ARGS] = {
                GrShaderVar("dot", kFloat_GrSLType, 0, kHigh_GrSLPrecision),
                GrShaderVar("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 = sk_FragCoord.xy - vec2(0.25);");
            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 GrShaderCaps&,
                                  GrProcessorKeyBuilder* b) {
            const PLSQuadEdgeEffect& qee = gp.cast<PLSQuadEdgeEffect>();
            uint32_t key = 0;
            key |= qee.usesLocalCoords() && qee.localMatrix().hasPerspective() ? 0x1 : 0x0;
            b->add32(key);
        }

        void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
                             FPCoordTransformIter&& transformIter) override {
            this->setTransformDataHelper(gp.cast<PLSQuadEdgeEffect>().fLocalMatrix, pdman,
                                         &transformIter);
        }

    private:
        typedef GrGLSLGeometryProcessor INHERITED;
    };

    virtual void getGLSLProcessorKey(const GrShaderCaps& caps,
                                   GrProcessorKeyBuilder* b) const override {
        GLSLProcessor::GenKey(*this, caps, b);
    }

    virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
        return new GLSLProcessor(*this);
    }

private:
    PLSQuadEdgeEffect(const SkMatrix& localMatrix, bool usesLocalCoords)
        : fLocalMatrix(localMatrix)
        , fUsesLocalCoords(usesLocalCoords) {
        this->initClassID<PLSQuadEdgeEffect>();
        fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
                                             kHigh_GrSLPrecision);
        fInUV = &this->addVertexAttrib("inUV", kVec2f_GrVertexAttribType, kHigh_GrSLPrecision);
        fInEndpoint1 = &this->addVertexAttrib("inEndpoint1", kVec2f_GrVertexAttribType,
                                              kHigh_GrSLPrecision);
        fInEndpoint2 = &this->addVertexAttrib("inEndpoint2", kVec2f_GrVertexAttribType,
                                              kHigh_GrSLPrecision);
        fInWindings  = &this->addVertexAttrib("inWindings", kInt_GrVertexAttribType,
                                              kLow_GrSLPrecision);
    }

    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; }
    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(kFragment_GrShaderFlag,
                                                    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.fFPCoordTransformHandler);

            GrGLSLPPFragmentBuilder* 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("}");
            this->setupUniformColor(fsBuilder, uniformHandler, args.fOutputColor,
                                    &fColorUniform);
            fsBuilder->codeAppendf("%s = vec4(coverage);", args.fOutputCoverage);
            fsBuilder->codeAppendf("%s = vec4(1.0, 0.0, 1.0, 1.0);", args.fOutputColor);
        }

        static inline void GenKey(const GrGeometryProcessor& gp,
                                  const GrShaderCaps&,
                                  GrProcessorKeyBuilder* b) {
            const PLSFinishEffect& fe = gp.cast<PLSFinishEffect>();
            uint32_t key = 0;
            key |= fe.usesLocalCoords() && fe.localMatrix().hasPerspective() ? 0x1 : 0x0;
            b->add32(key);
        }

        void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
                     FPCoordTransformIter&& transformIter) override {
            const PLSFinishEffect& fe = gp.cast<PLSFinishEffect>();
            pdman.set1f(fUseEvenOdd, fe.fUseEvenOdd);
            if (fe.color() != fColor) {
                GrGLfloat c[4];
                GrColorToRGBAFloat(fe.color(), c);
                pdman.set4fv(fColorUniform, 1, c);
                fColor = fe.color();
            }
            this->setTransformDataHelper(fe.fLocalMatrix, pdman, &transformIter);
        }

    private:
        GrColor fColor;
        UniformHandle fColorUniform;
        UniformHandle fUseEvenOdd;

        typedef GrGLSLGeometryProcessor INHERITED;
    };

    virtual void getGLSLProcessorKey(const GrShaderCaps& caps,
                                   GrProcessorKeyBuilder* b) const override {
        GLSLProcessor::GenKey(*this, caps, b);
    }

    virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) 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("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.
    SkPath path;
    args.fShape->asPath(&path);
    return args.fShaderCaps->shaderDerivativeSupport() && GrAAType::kCoverage == args.fAAType &&
            args.fShape->style().isSimpleFill() && !path.isInverseFillType() &&
            path.getFillType() == SkPath::FillType::kWinding_FillType;
}

class PLSPathOp final : public GrMeshDrawOp {
public:
    DEFINE_OP_CLASS_ID
    static std::unique_ptr<GrDrawOp> Make(GrColor color, const SkPath& path,
                                          const SkMatrix& viewMatrix) {
        return std::unique_ptr<GrDrawOp>(new PLSPathOp(color, path, viewMatrix));
    }

    const char* name() const override { return "PLSPathOp"; }

    SkString dumpInfo() const override {
        SkString string;
        string.printf("Color 0x%08x, UsesLocalCoords: %d\n", fColor, fUsesLocalCoords);
        string.append(DumpPipelineInfo(*this->pipeline()));
        string.append(INHERITED::dumpInfo());
        return string;
    }

private:
    PLSPathOp(GrColor color, const SkPath& path, const SkMatrix& viewMatrix)
            : INHERITED(ClassID()), fColor(color), fPath(path), fViewMatrix(viewMatrix) {
        // compute bounds
        this->setTransformedBounds(path.getBounds(), fViewMatrix, HasAABloat::kYes,
                                   IsZeroArea::kNo);
    }

    void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
        input->pipelineColorInput()->setKnownFourComponents(fColor);
        input->pipelineCoverageInput()->setUnknownSingleComponent();
        input->setUsesPLSDstRead();
    }

    void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
        optimizations.getOverrideColorIfSet(&fColor);

        fUsesLocalCoords = optimizations.readsLocalCoords();
    }

    void onPrepareDraws(Target* target) const override {

        SkMatrix invert;
        if (fUsesLocalCoords && !fViewMatrix.invert(&invert)) {
            SkDebugf("Could not invert viewmatrix\n");
            return;
        }

        // Setup GrGeometryProcessors
        sk_sp<GrPLSGeometryProcessor> triangleProcessor(
                PLSAATriangleEffect::Create(invert, fUsesLocalCoords));
        sk_sp<GrPLSGeometryProcessor> quadProcessor(
                PLSQuadEdgeEffect::Create(invert, fUsesLocalCoords));

        GrResourceProvider* rp = target->resourceProvider();
        SkRect bounds;
        this->bounds().roundOut(&bounds);
        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 = &fViewMatrix;

        // We avoid initializing the path unless we have to
        const SkPath* pathPtr = &fPath;
        SkTLazy<SkPath> tmpPath;
        if (viewMatrix->hasPerspective()) {
            SkPath* tmpPathPtr = tmpPath.init(*pathPtr);
            tmpPathPtr->setIsVolatile(true);
            tmpPathPtr->transform(*viewMatrix);
            viewMatrix = &SkMatrix::I();
            pathPtr = tmpPathPtr;
        }

        GrMesh mesh;

        PLSVertices triVertices;
        PLSVertices quadVertices;
        if (!get_geometry(*pathPtr, *viewMatrix, triVertices, quadVertices, rp, bounds)) {
            return;
        }

        if (triVertices.count()) {
            const GrBuffer* 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];
            }
            mesh.init(kTriangles_GrPrimitiveType, triVertexBuffer, firstTriVertex,
                      triVertices.count());
            target->draw(triangleProcessor.get(), mesh);
        }

        if (quadVertices.count()) {
            const GrBuffer* 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];
            }
            mesh.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVertex,
                      quadVertices.count());
            target->draw(quadProcessor.get(), mesh);
        }

        sk_sp<GrGeometryProcessor> finishProcessor(
                PLSFinishEffect::Create(fColor,
                                        pathPtr->getFillType() ==
                                                            SkPath::FillType::kEvenOdd_FillType,
                                        invert,
                                        fUsesLocalCoords));
        const GrBuffer* 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 };

        mesh.init(kTriangles_GrPrimitiveType, rectVertexBuffer, firstRectVertex,
                  kRectVertexCount);
        target->draw(finishProcessor.get(), mesh);
    }

    bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
        return false;
    }

    bool fUsesLocalCoords;

    GrColor fColor;
    SkPath fPath;
    SkMatrix fViewMatrix;
    typedef GrMeshDrawOp INHERITED;
};

SkDEBUGCODE(bool inPLSDraw = false;)
bool GrPLSPathRenderer::onDrawPath(const DrawPathArgs& args) {
    SkASSERT(!args.fShape->isEmpty());
    SkASSERT(!inPLSDraw);
    SkDEBUGCODE(inPLSDraw = true;)
    SkPath path;
    args.fShape->asPath(&path);

    std::unique_ptr<GrDrawOp> op = PLSPathOp::Make(args.fPaint.getColor(), path, *args.fViewMatrix);
    GrPipelineBuilder pipelineBuilder(std::move(args.fPaint), args.fAAType);
    pipelineBuilder.setUserStencil(args.fUserStencilSettings);

    args.fRenderTargetContext->addDrawOp(pipelineBuilder, *args.fClip, std::move(op));
    SkDEBUGCODE(inPLSDraw = false;)
    return true;

}

///////////////////////////////////////////////////////////////////////////////////////////////////

#ifdef GR_TEST_UTILS

DRAW_OP_TEST_DEFINE(PLSPathOp) {
    GrColor color = GrRandomColor(random);
    SkMatrix vm = GrTest::TestMatrixInvertible(random);
    SkPath path = GrTest::TestPathConvex(random);

    return PLSPathOp::Make(color, path, vm);
}

#endif
