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

#include "src/gpu/tessellate/GrFillPathShader.h"

#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"

class GrFillPathShader::Impl : public GrGLSLGeometryProcessor {
public:
    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
        auto& shader = args.fGeomProc.cast<GrFillPathShader>();

        const char* viewMatrix;
        fViewMatrixUniform = args.fUniformHandler->addUniform(
                nullptr, kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix);

        args.fVaryingHandler->emitAttributes(shader);

        args.fVertBuilder->codeAppend("float2 localcoord, vertexpos;");
        shader.emitVertexCode(this, args.fVertBuilder, viewMatrix, args.fUniformHandler);

        gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
        gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");

        const char* color;
        fColorUniform = args.fUniformHandler->addUniform(
                nullptr, kFragment_GrShaderFlag, kHalf4_GrSLType, "color", &color);

        args.fFragBuilder->codeAppendf("half4 %s = %s;", args.fOutputColor, color);
        args.fFragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
    }

    void setData(const GrGLSLProgramDataManager& pdman,
                 const GrShaderCaps&,
                 const GrGeometryProcessor& geomProc) override {
        const GrFillPathShader& shader = geomProc.cast<GrFillPathShader>();
        pdman.setSkMatrix(fViewMatrixUniform, shader.viewMatrix());

        const SkPMColor4f& color = shader.fColor;
        pdman.set4f(fColorUniform, color.fR, color.fG, color.fB, color.fA);

        if (fPathBoundsUniform.isValid()) {
            const SkRect& b = geomProc.cast<GrFillBoundingBoxShader>().pathBounds();
            pdman.set4f(fPathBoundsUniform, b.left(), b.top(), b.right(), b.bottom());
        }
    }

    GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
    GrGLSLUniformHandler::UniformHandle fColorUniform;
    GrGLSLUniformHandler::UniformHandle fPathBoundsUniform;
};

GrGLSLGeometryProcessor* GrFillPathShader::createGLSLInstance(const GrShaderCaps&) const {
    return new Impl;
}

void GrFillTriangleShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, const char* viewMatrix,
                                          GrGLSLUniformHandler* uniformHandler) const {
    v->codeAppendf(R"(
    localcoord = input_point;
    vertexpos = (%s * float3(localcoord, 1)).xy;)", viewMatrix);
}

void GrFillCubicHullShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, const char* viewMatrix,
                                           GrGLSLUniformHandler* uniformHandler) const {
    v->codeAppend(R"(
    float4x2 P = float4x2(input_points_0_1, input_points_2_3);
    if (isinf(P[3].y)) {
        // This curve is actually a conic. Convert the control points to a trapeziodal hull
        // that circumcscribes the conic.
        float w = P[3].x;
        float2 p1w = P[1] * w;
        float T = .51;  // Bias outward a bit to ensure we cover the outermost samples.
        float2 c1 = mix(P[0], p1w, T);
        float2 c2 = mix(P[2], p1w, T);
        float iw = 1 / mix(1, w, T);
        P = float4x2(P[0], c1 * iw, c2 * iw, P[2]);
    }

    // Translate the points to v0..3 where v0=0.
    float2 v1 = P[1] - P[0], v2 = P[2] - P[0], v3 = P[3] - P[0];

    // Reorder the points so v2 bisects v1 and v3.
    if (sign(determinant(float2x2(v2,v1))) == sign(determinant(float2x2(v2,v3)))) {
        float2 tmp = P[2];
        if (sign(determinant(float2x2(v1,v2))) != sign(determinant(float2x2(v1,v3)))) {
            P[2] = P[1];  // swap(P2, P1)
            P[1] = tmp;
        } else {
            P[2] = P[3];  // swap(P2, P3)
            P[3] = tmp;
        }
    }

    // sk_VertexID comes in fan order. Convert to strip order.
    int vertexidx = sk_VertexID;
    vertexidx ^= vertexidx >> 1;

    // Find the "turn direction" of each corner and net turn direction.
    float vertexdir = 0;
    float netdir = 0;
    for (int i = 0; i < 4; ++i) {
        float2 prev = P[i] - P[(i + 3) & 3], next = P[(i + 1) & 3] - P[i];
        float dir = sign(determinant(float2x2(prev, next)));
        if (i == vertexidx) {
            vertexdir = dir;
        }
        netdir += dir;
    }

    // Remove the non-convex vertex, if any.
    if (vertexdir != sign(netdir)) {
        vertexidx = (vertexidx + 1) & 3;
    }

    localcoord = P[vertexidx];)");

    v->codeAppendf("vertexpos = (%s * float3(localcoord, 1)).xy;", viewMatrix);
}

void GrFillBoundingBoxShader::emitVertexCode(Impl* impl, GrGLSLVertexBuilder* v,
                                             const char* viewMatrix,
                                             GrGLSLUniformHandler* uniformHandler) const {
    const char* pathBounds;
    impl->fPathBoundsUniform = uniformHandler->addUniform(
            nullptr, kVertex_GrShaderFlag, kFloat4_GrSLType, "path_bounds", &pathBounds);

    v->codeAppendf(R"(
    // Use sk_VertexID and uniforms (instead of vertex data) to find vertex positions.
    float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1);
    localcoord = mix(%s.xy, %s.zw, T);
    vertexpos = (%s * float3(localcoord, 1)).xy;

    // Outset to avoid possible T-junctions with extreme edges of the path.
    float2x2 M2 = float2x2(%s);
    float2 devoutset = .25 * sign(M2 * (T - .5));
    localcoord += inverse(M2) * devoutset;
    vertexpos += devoutset;)", pathBounds, pathBounds, viewMatrix, viewMatrix);
}
