/*
 * 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 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);
}
