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

#ifndef GrStrokeTessellationShader_DEFINED
#define GrStrokeTessellationShader_DEFINED

#include "src/gpu/tessellate/shaders/GrTessellationShader.h"

#include "include/core/SkStrokeRec.h"
#include "src/gpu/GrVx.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/tessellate/GrTessellationPathRenderer.h"

// Tessellates a batch of stroke patches directly to the canvas. Tessellated stroking works by
// creating stroke-width, orthogonal edges at set locations along the curve and then connecting them
// with a quad strip. These orthogonal edges come from two different sets: "parametric edges" and
// "radial edges". Parametric edges are spaced evenly in the parametric sense, and radial edges
// divide the curve's _rotation_ into even steps. The tessellation shader evaluates both sets of
// edges and sorts them into a single quad strip. With this combined set of edges we can stroke any
// curve, regardless of curvature.
class GrStrokeTessellationShader : public GrTessellationShader {
public:
    // Are we using hardware tessellation or indirect draws?
    enum class Mode : int8_t {
        kHardwareTessellation,
        kLog2Indirect,
        kFixedCount
    };

    enum class ShaderFlags : uint8_t {
        kNone          = 0,
        kWideColor     = 1 << 0,
        kDynamicStroke = 1 << 1,  // Each patch or instance has its own stroke width and join type.
        kDynamicColor  = 1 << 2,  // Each patch or instance has its own color.
    };

    GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(ShaderFlags);

    // Returns the fixed number of edges that are always emitted with the given join type. If the
    // join is round, the caller needs to account for the additional radial edges on their own.
    // Specifically, each join always emits:
    //
    //   * Two colocated edges at the beginning (a full-width edge to seam with the preceding stroke
    //     and a half-width edge to begin the join).
    //
    //   * An extra edge in the middle for miter joins, or else a variable number of radial edges
    //     for round joins (the caller is responsible for counting radial edges from round joins).
    //
    //   * A half-width edge at the end of the join that will be colocated with the first
    //     (full-width) edge of the stroke.
    //
    constexpr static int NumFixedEdgesInJoin(SkPaint::Join joinType) {
        switch (joinType) {
            case SkPaint::kMiter_Join:
                return 4;
            case SkPaint::kRound_Join:
                // The caller is responsible for counting the variable number of middle, radial
                // segments on round joins.
                [[fallthrough]];
            case SkPaint::kBevel_Join:
                return 3;
        }
        SkUNREACHABLE;
    }

    // We encode all of a join's information in a single float value:
    //
    //     Negative => Round Join
    //     Zero     => Bevel Join
    //     Positive => Miter join, and the value is also the miter limit
    //
    static float GetJoinType(const SkStrokeRec& stroke) {
        switch (stroke.getJoin()) {
            case SkPaint::kRound_Join: return -1;
            case SkPaint::kBevel_Join: return 0;
            case SkPaint::kMiter_Join: SkASSERT(stroke.getMiter() >= 0); return stroke.getMiter();
        }
        SkUNREACHABLE;
    }

    // This struct gets written out to each patch or instance if kDynamicStroke is enabled.
    struct DynamicStroke {
        static bool StrokesHaveEqualDynamicState(const SkStrokeRec& a, const SkStrokeRec& b) {
            return a.getWidth() == b.getWidth() && a.getJoin() == b.getJoin() &&
                   (a.getJoin() != SkPaint::kMiter_Join || a.getMiter() == b.getMiter());
        }
        void set(const SkStrokeRec& stroke) {
            fRadius = stroke.getWidth() * .5f;
            fJoinType = GetJoinType(stroke);
        }
        float fRadius;
        float fJoinType;  // See GetJoinType().
    };

    // 'viewMatrix' is applied to the geometry post tessellation. It cannot have perspective.
    GrStrokeTessellationShader(Mode mode, ShaderFlags shaderFlags, const SkMatrix& viewMatrix,
                               const SkStrokeRec& stroke, SkPMColor4f color,
                               int8_t maxParametricSegments_log2)
            : GrTessellationShader(kTessellate_GrStrokeTessellationShader_ClassID,
                                   (mode == Mode::kHardwareTessellation)
                                           ? GrPrimitiveType::kPatches
                                           : GrPrimitiveType::kTriangleStrip,
                                   (mode == Mode::kHardwareTessellation) ? 1 : 0, viewMatrix, color)
            , fMode(mode)
            , fShaderFlags(shaderFlags)
            , fStroke(stroke)
            , fMaxParametricSegments_log2(maxParametricSegments_log2) {
        if (fMode == Mode::kHardwareTessellation) {
            // A join calculates its starting angle using prevCtrlPtAttr.
            fAttribs.emplace_back("prevCtrlPtAttr", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
            // pts 0..3 define the stroke as a cubic bezier. If p3.y is infinity, then it's a conic
            // with w=p3.x.
            //
            // If p0 == prevCtrlPtAttr, then no join is emitted.
            //
            // pts=[p0, p3, p3, p3] is a reserved pattern that means this patch is a join only,
            // whose start and end tangents are (p0 - inputPrevCtrlPt) and (p3 - p0).
            //
            // pts=[p0, p0, p0, p3] is a reserved pattern that means this patch is a "bowtie", or
            // double-sided round join, anchored on p0 and rotating from (p0 - prevCtrlPtAttr) to
            // (p3 - p0).
            fAttribs.emplace_back("pts01Attr", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
            fAttribs.emplace_back("pts23Attr", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
        } else {
            // pts 0..3 define the stroke as a cubic bezier. If p3.y is infinity, then it's a conic
            // with w=p3.x.
            //
            // An empty stroke (p0==p1==p2==p3) is a special case that denotes a circle, or
            // 180-degree point stroke.
            fAttribs.emplace_back("pts01Attr", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
            fAttribs.emplace_back("pts23Attr", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
            if (fMode == Mode::kLog2Indirect) {
                // argsAttr.xy contains the lastControlPoint for setting up the join.
                //
                // "argsAttr.z=numTotalEdges" tells the shader the literal number of edges in the
                // triangle strip being rendered (i.e., it should be vertexCount/2). If
                // numTotalEdges is negative and the join type is "kRound", it also instructs the
                // shader to only allocate one segment the preceding round join.
                fAttribs.emplace_back("argsAttr", kFloat3_GrVertexAttribType, kFloat3_GrSLType);
            } else {
                SkASSERT(fMode == Mode::kFixedCount);
                // argsAttr contains the lastControlPoint for setting up the join.
                fAttribs.emplace_back("argsAttr", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
            }
        }
        if (fShaderFlags & ShaderFlags::kDynamicStroke) {
            fAttribs.emplace_back("dynamicStrokeAttr", kFloat2_GrVertexAttribType,
                                  kFloat2_GrSLType);
        }
        if (fShaderFlags & ShaderFlags::kDynamicColor) {
            fAttribs.emplace_back("dynamicColorAttr",
                                  (fShaderFlags & ShaderFlags::kWideColor)
                                          ? kFloat4_GrVertexAttribType
                                          : kUByte4_norm_GrVertexAttribType,
                                  kHalf4_GrSLType);
        }
        if (fMode == Mode::kHardwareTessellation) {
            this->setVertexAttributes(fAttribs.data(), fAttribs.count());
        } else {
            this->setInstanceAttributes(fAttribs.data(), fAttribs.count());
        }
        SkASSERT(fAttribs.count() <= kMaxAttribCount);
    }

    Mode mode() const { return fMode; }
    ShaderFlags flags() const { return fShaderFlags; }
    bool hasDynamicStroke() const { return fShaderFlags & ShaderFlags::kDynamicStroke; }
    bool hasDynamicColor() const { return fShaderFlags & ShaderFlags::kDynamicColor; }
    const SkStrokeRec& stroke() const { return fStroke;}
    int8_t maxParametricSegments_log2() const { return fMaxParametricSegments_log2; }
    float fixedCountNumTotalEdges() const { return fFixedCountNumTotalEdges;}

    // Used by GrFixedCountTessellator to configure the uniform value that tells the shader how many
    // total edges are in the triangle strip.
    void setFixedCountNumTotalEdges(int value) {
        SkASSERT(fMode == Mode::kFixedCount);
        fFixedCountNumTotalEdges = value;
    }

private:
    const char* name() const override {
        switch (fMode) {
            case Mode::kHardwareTessellation:
                return "GrStrokeTessellationShader_HardwareImpl";
            case Mode::kLog2Indirect:
            case Mode::kFixedCount:
                return "GrStrokeTessellationShader_InstancedImpl";
        }
        SkUNREACHABLE;
    }
    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override;
    GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const final;

    const Mode fMode;
    const ShaderFlags fShaderFlags;
    const SkStrokeRec fStroke;
    const int8_t fMaxParametricSegments_log2;

    constexpr static int kMaxAttribCount = 5;
    SkSTArray<kMaxAttribCount, Attribute> fAttribs;

    // This is a uniform value used when fMode is kFixedCount that tells the shader how many total
    // edges are in the triangle strip.
    float fFixedCountNumTotalEdges = 0;

    class Impl;
    class HardwareImpl;
    class InstancedImpl;
};

GR_MAKE_BITFIELD_CLASS_OPS(GrStrokeTessellationShader::ShaderFlags);

// This common base class emits shader code for our parametric/radial stroke tessellation algorithm
// described above. The subclass emits its own specific setup code before calling into
// emitTessellationCode and emitFragment code.
class GrStrokeTessellationShader::Impl : public GrGLSLGeometryProcessor {
protected:
    // float atan2(float2 v) { ...
    //
    // The built-in atan() is undefined when x==0. This method relieves that restriction, but also
    // can return values larger than 2*PI. This shouldn't matter for our purposes.
    static const char* kAtan2Fn;

    // float cosine_between_vectors(float2 a, float2 b) { ...
    //
    // Returns dot(a, b) / (length(a) * length(b)).
    static const char* kCosineBetweenVectorsFn;

    // float miter_extent(float cosTheta, float miterLimit) { ...
    //
    // Extends the middle radius to either the miter point, or the bevel edge if we surpassed the
    // miter limit and need to revert to a bevel join.
    static const char* kMiterExtentFn;

    // float num_radial_segments_per_radian(float parametricPrecision, float strokeRadius) { ...
    //
    // Returns the number of radial segments required for each radian of rotation, in order for the
    // curve to appear "smooth" as defined by the parametricPrecision.
    static const char* kNumRadialSegmentsPerRadianFn;

    // float<N> unchecked_mix(float<N> a, float<N> b, float<N> T) { ...
    //
    // Unlike mix(), this does not return b when t==1. But it otherwise seems to get better
    // precision than "a*(1 - t) + b*t" for things like chopping cubics on exact cusp points.
    // We override this result anyway when t==1 so it shouldn't be a problem.
    static const char* kUncheckedMixFn;

    // Emits code that calculates the vertex position and any other inputs to the fragment shader.
    // The subclass is responsible to define the following symbols before calling this method:
    //
    //     // Functions.
    //     float2 unchecked_mix(float2, float2, float);
    //     float unchecked_mix(float, float, float);
    //
    //     // Values provided by either uniforms or attribs.
    //     float4x2 P;
    //     float w;
    //     float STROKE_RADIUS;
    //     float 2x2 AFFINE_MATRIX;
    //     float2 TRANSLATE;
    //
    //     // Values calculated by the specific subclass.
    //     float combinedEdgeID;
    //     bool isFinalEdge;
    //     float numParametricSegments;
    //     float radsPerSegment;
    //     float2 tan0;
    //     float2 tan1;
    //     float angle0;
    //     float strokeOutset;
    //
    void emitTessellationCode(const GrStrokeTessellationShader& shader, SkString* code,
                              GrGPArgs* gpArgs, const GrShaderCaps& shaderCaps) const;

    // Emits all necessary fragment code. If using dynamic color, the impl is responsible to set up
    // a half4 varying for color and provide its name in 'fDynamicColorName'.
    void emitFragmentCode(const GrStrokeTessellationShader&, const EmitArgs&);

    void setData(const GrGLSLProgramDataManager& pdman, const GrShaderCaps&,
                 const GrGeometryProcessor&) final;

    GrGLSLUniformHandler::UniformHandle fTessControlArgsUniform;
    GrGLSLUniformHandler::UniformHandle fTranslateUniform;
    GrGLSLUniformHandler::UniformHandle fAffineMatrixUniform;
    GrGLSLUniformHandler::UniformHandle fEdgeCountUniform;
    GrGLSLUniformHandler::UniformHandle fColorUniform;
    SkString fDynamicColorName;
};

class GrStrokeTessellationShader::InstancedImpl : public GrStrokeTessellationShader::Impl {
    void onEmitCode(EmitArgs&, GrGPArgs*) override;
};

class GrStrokeTessellationShader::HardwareImpl : public GrStrokeTessellationShader::Impl {
    void onEmitCode(EmitArgs&, GrGPArgs*) override;
    SkString getTessControlShaderGLSL(const GrGeometryProcessor&,
                                      const char* versionAndExtensionDecls,
                                      const GrGLSLUniformHandler&,
                                      const GrShaderCaps&) const override;
    SkString getTessEvaluationShaderGLSL(const GrGeometryProcessor&,
                                         const char* versionAndExtensionDecls,
                                         const GrGLSLUniformHandler&,
                                         const GrShaderCaps&) const override;
};

#endif
