/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrCCCoverageProcessor.h"

#include "GrMesh.h"
#include "glsl/GrGLSLVertexGeoBuilder.h"

using Shader = GrCCCoverageProcessor::Shader;

static constexpr int kAttribIdx_X = 0;
static constexpr int kAttribIdx_Y = 1;
static constexpr int kAttribIdx_VertexData = 2;

/**
 * This class and its subclasses implement the coverage processor with vertex shaders.
 */
class GrCCCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor {
protected:
    VSImpl(std::unique_ptr<Shader> shader) : fShader(std::move(shader)) {}

    void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
                 FPCoordTransformIter&& transformIter) final {
        this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
    }

    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
        const GrCCCoverageProcessor& proc = args.fGP.cast<GrCCCoverageProcessor>();

        // Vertex shader.
        GrGLSLVertexBuilder* v = args.fVertBuilder;
        int numInputPoints = proc.numInputPoints();

        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
        if (proc.debugVisualizationsEnabled()) {
            bloat *= proc.debugBloat();
        }
#endif
        v->defineConstant("bloat", bloat);

        const char* coverage = this->emitVertexPosition(proc, v, gpArgs);
        SkASSERT(kFloat2_GrSLType == gpArgs->fPositionVar.getType());

        GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
        SkString varyingCode;
        fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &varyingCode,
                              gpArgs->fPositionVar.c_str(), coverage, "wind");
        v->codeAppend(varyingCode.c_str());

        varyingHandler->emitAttributes(proc);
        SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform());

        // Fragment shader.
        fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
    }

    virtual const char* emitVertexPosition(const GrCCCoverageProcessor&, GrGLSLVertexBuilder*,
                                           GrGPArgs*) const = 0;

    virtual ~VSImpl() {}

    const std::unique_ptr<Shader> fShader;

    typedef GrGLSLGeometryProcessor INHERITED;
};

/**
 * Vertex data tells the shader how to offset vertices for conservative raster, and how/whether to
 * calculate initial coverage values for edges. See VSHullAndEdgeImpl.
 */
static constexpr int32_t pack_vertex_data(int32_t bloatIdx, int32_t edgeData,
                                          int32_t cornerVertexID, int32_t cornerIdx) {
    return (bloatIdx << 6) | (edgeData << 4) | (cornerVertexID << 2) | cornerIdx;
}

static constexpr int32_t hull_vertex_data(int32_t cornerIdx, int32_t cornerVertexID, int n) {
    return pack_vertex_data((cornerIdx + (2 == cornerVertexID ? 1 : n - 1)) % n, 0, cornerVertexID,
                            cornerIdx);
}

static constexpr int32_t edge_vertex_data(int32_t edgeID, int32_t endptIdx, int32_t endptVertexID,
                                          int n) {
    return pack_vertex_data(0 == endptIdx ? (edgeID + 1) % n : edgeID, (endptIdx << 1) | 1,
                            endptVertexID, 0 == endptIdx ? edgeID : (edgeID + 1) % n);
}

static constexpr int32_t kHull3AndEdgeVertices[] = {
    hull_vertex_data(0, 0, 3),
    hull_vertex_data(0, 1, 3),
    hull_vertex_data(0, 2, 3),
    hull_vertex_data(1, 0, 3),
    hull_vertex_data(1, 1, 3),
    hull_vertex_data(1, 2, 3),
    hull_vertex_data(2, 0, 3),
    hull_vertex_data(2, 1, 3),
    hull_vertex_data(2, 2, 3),

    edge_vertex_data(0, 0, 0, 3),
    edge_vertex_data(0, 0, 1, 3),
    edge_vertex_data(0, 0, 2, 3),
    edge_vertex_data(0, 1, 0, 3),
    edge_vertex_data(0, 1, 1, 3),
    edge_vertex_data(0, 1, 2, 3),

    edge_vertex_data(1, 0, 0, 3),
    edge_vertex_data(1, 0, 1, 3),
    edge_vertex_data(1, 0, 2, 3),
    edge_vertex_data(1, 1, 0, 3),
    edge_vertex_data(1, 1, 1, 3),
    edge_vertex_data(1, 1, 2, 3),

    edge_vertex_data(2, 0, 0, 3),
    edge_vertex_data(2, 0, 1, 3),
    edge_vertex_data(2, 0, 2, 3),
    edge_vertex_data(2, 1, 0, 3),
    edge_vertex_data(2, 1, 1, 3),
    edge_vertex_data(2, 1, 2, 3),
};

GR_DECLARE_STATIC_UNIQUE_KEY(gHull3AndEdgeVertexBufferKey);

static constexpr uint16_t kRestartStrip = 0xffff;

static constexpr uint16_t kHull3AndEdgeIndicesAsStrips[] =  {
    1, 2, 0, 3, 8, kRestartStrip, // First corner and main body of the hull.
    4, 5, 3, 6, 8, 7, kRestartStrip, // Opposite side and corners of the hull.
    10, 9, 11, 14, 12, 13, kRestartStrip, // First edge.
    16, 15, 17, 20, 18, 19, kRestartStrip, // Second edge.
    22, 21, 23, 26, 24, 25 // Third edge.
};

static constexpr uint16_t kHull3AndEdgeIndicesAsTris[] =  {
    // First corner and main body of the hull.
    1, 2, 0,
    2, 3, 0,
    0, 3, 8, // Main body.

    // Opposite side and corners of the hull.
    4, 5, 3,
    5, 6, 3,
    3, 6, 8,
    6, 7, 8,

    // First edge.
    10,  9, 11,
     9, 14, 11,
    11, 14, 12,
    14, 13, 12,

    // Second edge.
    16, 15, 17,
    15, 20, 17,
    17, 20, 18,
    20, 19, 18,

    // Third edge.
    22, 21, 23,
    21, 26, 23,
    23, 26, 24,
    26, 25, 24,
};

GR_DECLARE_STATIC_UNIQUE_KEY(gHull3AndEdgeIndexBufferKey);

static constexpr int32_t kHull4Vertices[] = {
    hull_vertex_data(0, 0, 4),
    hull_vertex_data(0, 1, 4),
    hull_vertex_data(0, 2, 4),
    hull_vertex_data(1, 0, 4),
    hull_vertex_data(1, 1, 4),
    hull_vertex_data(1, 2, 4),
    hull_vertex_data(2, 0, 4),
    hull_vertex_data(2, 1, 4),
    hull_vertex_data(2, 2, 4),
    hull_vertex_data(3, 0, 4),
    hull_vertex_data(3, 1, 4),
    hull_vertex_data(3, 2, 4),

    // No edges for now (beziers don't use edges).
};

GR_DECLARE_STATIC_UNIQUE_KEY(gHull4VertexBufferKey);

static constexpr uint16_t kHull4IndicesAsStrips[] =  {
    1, 0, 2, 11, 3, 5, 4, kRestartStrip, // First half of the hull (split diagonally).
    7, 6, 8, 5, 9, 11, 10 // Second half of the hull.
};

static constexpr uint16_t kHull4IndicesAsTris[] =  {
    // First half of the hull (split diagonally).
     1,  0,  2,
     0, 11,  2,
     2, 11,  3,
    11,  5,  3,
     3,  5,  4,

    // Second half of the hull.
    7,  6,  8,
    6,  5,  8,
    8,  5,  9,
    5, 11,  9,
    9, 11, 10,
};

GR_DECLARE_STATIC_UNIQUE_KEY(gHull4IndexBufferKey);

/**
 * Generates a conservative raster hull around a convex polygon. For triangles, we also generate
 * independent conservative rasters around each edge. (See comments for RenderPass)
 */
class VSHullAndEdgeImpl : public GrCCCoverageProcessor::VSImpl {
public:
    VSHullAndEdgeImpl(std::unique_ptr<Shader> shader, int numSides)
            : VSImpl(std::move(shader)), fNumSides(numSides) {}

    const char* emitVertexPosition(const GrCCCoverageProcessor& proc, GrGLSLVertexBuilder* v,
                                   GrGPArgs* gpArgs) const override {
        Shader::GeometryVars vars;
        fShader->emitSetupCode(v, "pts", nullptr, "wind", &vars);

        const char* hullPts = vars.fHullVars.fAlternatePoints;
        if (!hullPts) {
            hullPts = "pts";
        }

        // Reverse all indices if the wind is counter-clockwise: [0, 1, 2] -> [2, 1, 0].
        v->codeAppendf("int clockwise_indices = wind > 0 ? %s : 0x%x - %s;",
                       proc.getAttrib(kAttribIdx_VertexData).fName,
                       ((fNumSides - 1) << 6) | (0xf << 2) | (fNumSides - 1),
                       proc.getAttrib(kAttribIdx_VertexData).fName);

        // Here we generate conservative raster geometry for the input polygon. It is the convex
        // hull of N pixel-size boxes, one centered on each the input points. Each corner has three
        // vertices, where one or two may cause degenerate triangles. The vertex data tells us how
        // to offset each vertex. Triangle edges are also handled here (see kHull3AndEdgeIndices).
        // For more details on conservative raster, see:
        // https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html
        v->codeAppendf("float2 corner = %s[clockwise_indices & 3];", hullPts);
        v->codeAppendf("float2 bloatpoint = %s[clockwise_indices >> 6];", hullPts);
        v->codeAppend ("float2 vertexbloat = float2(bloatpoint.y > corner.y ? -bloat : +bloat, "
                                                   "bloatpoint.x > corner.x ? +bloat : -bloat);");

        v->codeAppendf("if ((1 << 2) == (%s & (3 << 2))) {",
                       proc.getAttrib(kAttribIdx_VertexData).fName);
                           // We are the corner's middle vertex (of 3).
        v->codeAppend (    "vertexbloat = float2(-vertexbloat.y, vertexbloat.x);");
        v->codeAppend ("}");

        v->codeAppendf("if ((2 << 2) == (%s & (3 << 2))) {",
                       proc.getAttrib(kAttribIdx_VertexData).fName);
                           // We are the corner's third vertex (of 3).
        v->codeAppend (    "vertexbloat = -vertexbloat;");
        v->codeAppend ("}");

        v->codeAppend ("float2 vertex = corner + vertexbloat;");
        gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");

        if (4 == fNumSides) {
            // We don't generate edges around 4-sided polygons.
            return nullptr; // Known hull vertices don't need an initial coverage value.
        }

        // Find coverage for edge vertices.
        Shader::EmitEdgeDistanceEquation(v, "bloatpoint", "corner",
                                         "float3 edge_distance_equation");
        v->codeAppend ("half coverage = dot(edge_distance_equation.xy, vertex) + "
                                       "edge_distance_equation.z;");
        v->codeAppendf("if (0 == (%s & (1 << 5))) {", proc.getAttrib(kAttribIdx_VertexData).fName);
                           // We are the opposite endpoint. Invert coverage.
        v->codeAppend (    "coverage = -1 - coverage;");
        v->codeAppend ("}");
        v->codeAppendf("if (0 == (%s & (1 << 4))) {", proc.getAttrib(kAttribIdx_VertexData).fName);
                           // We are actually a hull vertex. Hull coverage is +1 all around.
        v->codeAppend (    "coverage = +1;");
        v->codeAppend ("}");

        return "coverage";
    }

private:
    const int fNumSides;
};

static constexpr uint16_t kCornerIndicesAsStrips[] =  {
    0, 1, 2, 3, kRestartStrip, // First corner.
    4, 5, 6, 7, kRestartStrip, // Second corner.
    8, 9, 10, 11 // Third corner.
};

static constexpr uint16_t kCornerIndicesAsTris[] =  {
    // First corner.
    0,  1,  2,
    1,  3,  2,

    // Second corner.
    4,  5,  6,
    5,  7,  6,

    // Third corner.
    8,  9, 10,
    9, 11, 10,
};

GR_DECLARE_STATIC_UNIQUE_KEY(gCornerIndexBufferKey);

/**
 * Generates conservative rasters around corners. (See comments for RenderPass)
 */
class VSCornerImpl : public GrCCCoverageProcessor::VSImpl {
public:
    VSCornerImpl(std::unique_ptr<Shader> shader) : VSImpl(std::move(shader)) {}

    const char* emitVertexPosition(const GrCCCoverageProcessor&, GrGLSLVertexBuilder* v,
                                   GrGPArgs* gpArgs) const override {
        Shader::GeometryVars vars;
        v->codeAppend ("int corner_id = sk_VertexID / 4;");
        fShader->emitSetupCode(v, "pts", "corner_id", "wind", &vars);

        v->codeAppendf("float2 vertex = %s;", vars.fCornerVars.fPoint);
        v->codeAppend ("vertex.x += (0 == (sk_VertexID & 2)) ? -bloat : +bloat;");
        v->codeAppend ("vertex.y += (0 == (sk_VertexID & 1)) ? -bloat : +bloat;");

        gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
        return nullptr; // Corner vertices don't have an initial coverage value.
    }
};

void GrCCCoverageProcessor::initVS(GrResourceProvider* rp, const GrCaps& caps) {
    SkASSERT(Impl::kVertexShader == fImpl);

    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: {
            GR_DEFINE_STATIC_UNIQUE_KEY(gHull3AndEdgeVertexBufferKey);
            fVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType,
                                                       sizeof(kHull3AndEdgeVertices),
                                                       kHull3AndEdgeVertices,
                                                       gHull3AndEdgeVertexBufferKey);
            GR_DEFINE_STATIC_UNIQUE_KEY(gHull3AndEdgeIndexBufferKey);
            if (caps.usePrimitiveRestart()) {
                fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
                                                          sizeof(kHull3AndEdgeIndicesAsStrips),
                                                          kHull3AndEdgeIndicesAsStrips,
                                                          gHull3AndEdgeIndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kHull3AndEdgeIndicesAsStrips);
            } else {
                fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
                                                          sizeof(kHull3AndEdgeIndicesAsTris),
                                                          kHull3AndEdgeIndicesAsTris,
                                                          gHull3AndEdgeIndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kHull3AndEdgeIndicesAsTris);
            }
            SkASSERT(kAttribIdx_VertexData == this->numAttribs());
            this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType);
            break;
        }
        case RenderPass::kQuadraticHulls:
        case RenderPass::kCubicHulls: {
            GR_DEFINE_STATIC_UNIQUE_KEY(gHull4VertexBufferKey);
            fVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType, sizeof(kHull4Vertices),
                                                       kHull4Vertices, gHull4VertexBufferKey);
            GR_DEFINE_STATIC_UNIQUE_KEY(gHull4IndexBufferKey);
            if (caps.usePrimitiveRestart()) {
                fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
                                                          sizeof(kHull4IndicesAsStrips),
                                                          kHull4IndicesAsStrips,
                                                          gHull4IndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kHull4IndicesAsStrips);
            } else {
                fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
                                                          sizeof(kHull4IndicesAsTris),
                                                          kHull4IndicesAsTris,
                                                          gHull4IndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kHull4IndicesAsTris);
            }
            SkASSERT(kAttribIdx_VertexData == this->numAttribs());
            this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType);
            break;
        }
        case RenderPass::kTriangleEdges:
            SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
            break;
        case RenderPass::kTriangleCorners:
        case RenderPass::kQuadraticCorners:
        case RenderPass::kCubicCorners: {
            GR_DEFINE_STATIC_UNIQUE_KEY(gCornerIndexBufferKey);
            if (caps.usePrimitiveRestart()) {
                fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
                                                          sizeof(kCornerIndicesAsStrips),
                                                          kCornerIndicesAsStrips,
                                                          gCornerIndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kCornerIndicesAsStrips);
            } else {
                fIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
                                                          sizeof(kCornerIndicesAsTris),
                                                          kCornerIndicesAsTris,
                                                          gCornerIndexBufferKey);
                fNumIndicesPerInstance = SK_ARRAY_COUNT(kCornerIndicesAsTris);
            }
            if (RenderPass::kTriangleCorners != fRenderPass) {
                fNumIndicesPerInstance = fNumIndicesPerInstance * 2/3;
            }
            break;
        }
    }

#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(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(sizeof(int32_t) == this->getVertexStride());
    }
#endif

    if (caps.usePrimitiveRestart()) {
        this->setWillUsePrimitiveRestart();
        fPrimitiveType = GrPrimitiveType::kTriangleStrip;
    } else {
        fPrimitiveType = GrPrimitiveType::kTriangles;
    }
}

void GrCCCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanceCount,
                                         int baseInstance, SkTArray<GrMesh>* out) const {
    SkASSERT(Impl::kVertexShader == fImpl);
    GrMesh& mesh = out->emplace_back(fPrimitiveType);
    mesh.setIndexedInstanced(fIndexBuffer.get(), fNumIndicesPerInstance, instanceBuffer,
                             instanceCount, baseInstance);
    if (fVertexBuffer) {
        mesh.setVertexData(fVertexBuffer.get(), 0);
    }
}

GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shadr) const {
    switch (fRenderPass) {
        case RenderPass::kTriangleHulls:
            return new VSHullAndEdgeImpl(std::move(shadr), 3);
        case RenderPass::kQuadraticHulls:
        case RenderPass::kCubicHulls:
            return new VSHullAndEdgeImpl(std::move(shadr), 4);
        case RenderPass::kTriangleEdges:
            SK_ABORT("kTriangleEdges RenderPass is not used by VSImpl.");
            return nullptr;
        case RenderPass::kTriangleCorners:
        case RenderPass::kQuadraticCorners:
        case RenderPass::kCubicCorners:
            return new VSCornerImpl(std::move(shadr));
    }
    SK_ABORT("Invalid RenderPass");
    return nullptr;
}
