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

#include "experimental/graphite/src/Renderer.h"

#include "experimental/graphite/src/DrawWriter.h"
#include "experimental/graphite/src/UniformManager.h"
#include "experimental/graphite/src/geom/Shape.h"
#include "experimental/graphite/src/geom/Transform_graphite.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkRect.h"
#include "src/core/SkUniformData.h"
#include "src/gpu/BufferWriter.h"
#include "src/gpu/tessellate/MiddleOutPolygonTriangulator.h"

namespace skgpu {

namespace {

// TODO: These settings are actually shared by tessellating path renderers, so will be exposed later

// Returns the stencil settings to use for a standard Redbook "stencil" pass.
constexpr DepthStencilSettings fillrule_settings(bool evenOdd) {
    // Increments clockwise triangles and decrements counterclockwise. Used for "winding" fill.
    constexpr DepthStencilSettings::Face kIncCW = {
        /*stencilFail=*/   StencilOp::kKeep,
        /*depthFail=*/     StencilOp::kKeep,
        /*dsPass=*/        StencilOp::kIncWrap,
        /*stencilCompare=*/CompareOp::kAlways,
        /*readMask=*/      0xffffffff,
        /*writeMask=*/     0xffffffff
    };
    constexpr DepthStencilSettings::Face kDecCCW = {
        /*stencilFail=*/   StencilOp::kKeep,
        /*depthFail=*/     StencilOp::kKeep,
        /*dsPass=*/        StencilOp::kDecWrap,
        /*stencilCompare=*/CompareOp::kAlways,
        /*readMask=*/      0xffffffff,
        /*writeMask=*/     0xffffffff
    };

    // Toggles the bottom stencil bit. Used for "even-odd" fill.
    constexpr DepthStencilSettings::Face kToggle = {
        /*stencilFail=*/   StencilOp::kKeep,
        /*depthFail=*/     StencilOp::kKeep,
        /*dsPass=*/        StencilOp::kInvert,
        /*stencilCompare=*/CompareOp::kAlways,
        /*readMask=*/      0xffffffff,
        /*writeMask=*/     0x00000001
    };

    // Always use ref = 0, disable depths, but still use greater depth test.
    constexpr DepthStencilSettings kWindingFill = {
        /*frontStencil=*/kIncCW,
        /*backStencil=*/ kDecCCW,
        /*refValue=*/    0,
        /*stencilTest=*/ true,
        /*depthCompare=*/CompareOp::kAlways, // kGreater once steps know the right depth value
        /*depthTest=*/   true,
        /*depthWrite=*/  false
    };
    constexpr DepthStencilSettings kEvenOddFill = {
        /*frontStencil=*/kToggle,
        /*backStencil=*/ kToggle,
        /*refValue=*/    0,
        /*stencilTest=*/ true,
        /*depthCompare=*/CompareOp::kAlways, // kGreater once steps know the right depth value
        /*depthTest=*/   true,
        /*depthWrite=*/  false
    };

    return evenOdd ? kEvenOddFill : kWindingFill;
}

// Returns the stencil settings to use for a standard Redbook "fill" pass. Allows non-zero
// stencil values to pass and write a color, and resets the stencil value back to zero; discards
// immediately on stencil values of zero (or does the inverse of these operations when the path
// requires filling everything else).
constexpr DepthStencilSettings cover_settings(bool inverse) {
    // Resets non-zero bits to 0, passes when not zero. We set depthFail to kZero because if we
    // encounter that case, the kNotEqual=0 stencil test passed, so it does need to be set back to 0
    // and the dsPass op won't be run. In practice, since the stencil steps will fail the same depth
    // test, the stencil value will likely not be non-zero, but best to be explicit.
    constexpr DepthStencilSettings::Face kNormal = {
        /*stencilFail=*/   StencilOp::kKeep,
        /*depthFail=*/     StencilOp::kZero,
        /*dsPass=*/        StencilOp::kZero,
        /*stencilCompare=*/CompareOp::kNotEqual,
        /*readMask=*/      0xffffffff,
        /*writeMask=*/     0xffffffff
    };

    // Resets non-zero bits to 0, passes when zero
    constexpr DepthStencilSettings::Face kInverted = {
        /*stencilFail=*/   StencilOp::kZero,
        /*depthFail=*/     StencilOp::kKeep,
        /*dsPass=*/        StencilOp::kKeep,
        /*stencilCompare=*/CompareOp::kEqual,
        /*readMask=*/      0xffffffff,
        /*writeMask=*/     0xffffffff
    };

    // Always use ref = 0, enabled depth writes, and greater depth test, both
    // front and back use the same stencil settings.
    constexpr DepthStencilSettings kNormalDSS = {
        /*frontStencil=*/kNormal,
        /*frontStencil=*/kNormal,
        /*refValue=*/    0,
        /*stencilTest=*/ true,
        /*depthCompare=*/CompareOp::kAlways, // kGreater once steps know the right depth value
        /*depthTest=*/   true,
        /*depthWrite=*/  true
    };
    constexpr DepthStencilSettings kInvertedDSS = {
        /*frontStencil=*/kInverted,
        /*backStencil=*/ kInverted,
        /*refValue=*/    0,
        /*stencilTest=*/ true,
        /*depthCompare=*/CompareOp::kAlways, // kGreater once steps know the right depth value
        /*depthTest=*/   true,
        /*depthWrite=*/  true
    };
    return inverse ? kInvertedDSS : kNormalDSS;
}

class StencilFanRenderStep final : public RenderStep {
public:
    StencilFanRenderStep(bool evenOdd)
            : RenderStep(Flags::kRequiresMSAA,
                         /*uniforms=*/{},
                         PrimitiveType::kTriangles,
                         fillrule_settings(evenOdd),
                         /*vertexAttrs=*/{{"position",
                                           VertexAttribType::kFloat3,
                                           SkSLType::kFloat3}},
                         /*instanceAttrs=*/{}) {}

    ~StencilFanRenderStep() override {}

    const char* name() const override { return "stencil-fan"; }

    const char* vertexSkSL() const override {
        return "     float4 devPosition = float4(position.xy, 0.0, position.z);\n";
    }

    void writeVertices(DrawWriter* writer,
                       const SkIRect& bounds,
                       const Transform& localToDevice,
                       const Shape& shape) const override {
        // TODO: Have Shape provide a path-like iterator so we don't actually have to convert non
        // paths to SkPath just to iterate their pts/verbs
        SkPath path = shape.asPath();
        DrawWriter::Vertices verts{*writer};
        for (PathMiddleOutFanIter it(path); !it.done();) {
            for (auto [p0, p1, p2] : it.nextStack()) {
                // TODO: PathMiddleOutFanIter should use SkV2 instead of SkPoint?
                SkV2 p[3] = {{p0.fX, p0.fY}, {p1.fX, p1.fY}, {p2.fX, p2.fY}};
                SkV4 devPoints[3];
                localToDevice.mapPoints(p, devPoints, 3);

                // TODO: Support reserving maxTrianglesInFans*3 vertices outside the loop, with
                // automatic returns of unused verts.
                verts.append(3) << devPoints[0].x << devPoints[0].y << devPoints[0].w  // p0
                                << devPoints[1].x << devPoints[1].y << devPoints[1].w  // p1
                                << devPoints[2].x << devPoints[2].y << devPoints[2].w; // p2
            }
        }
    }

    sk_sp<SkUniformData> writeUniforms(Layout layout,
                                       const SkIRect&,
                                       const Transform&,
                                       const Shape&) const override {
        // Control points are pre-transformed to device space on the CPU, so no uniforms needed.
        return nullptr;
    }
};

// TODO: Hand off to csmartdalton, this should roughly correspond to the fStencilPathProgram stage
// of skgpu::v1::PathStencilCoverOp using the PathCurveTessellator
/*
class StencilCurvesRenderStep : public RenderStep {
public:
    StencilCurvesRenderStep() {}

    ~StencilCurvesRenderStep() override {}

    const char* name()            const override { return "stencil-curves"; }
    bool        requiresStencil() const override { return true;  }
    bool        requiresMSAA()    const override { return true;  }
    bool        performsShading() const override { return false; }

private:
};
*/

// TODO: Hand off to csmartdalton, this should roughly correspond to the fCoverBBoxProgram stage
// of skgpu::v1::PathStencilCoverOp.
class FillBoundsRenderStep final : public RenderStep {
public:
    // TODO: Will need to add kRequiresStencil when we support specifying stencil settings and
    // the Renderer includes the stenciling step first.
    FillBoundsRenderStep(bool inverseFill)
            : RenderStep(Flags::kPerformsShading,
                         /*uniforms=*/{},
                         PrimitiveType::kTriangles,
                         cover_settings(inverseFill),
                         /*vertexAttrs=*/{{"position",
                                           VertexAttribType::kFloat3,
                                           SkSLType::kFloat3}},
                         /*instanceAttrs=*/{})
            , fInverseFill(inverseFill) {}

    ~FillBoundsRenderStep() override {}

    const char* name() const override { return "fill-bounds"; }

    const char* vertexSkSL() const override {
        return "     float4 devPosition = float4(position.xy, 0.0, position.z);\n";
    }

    void writeVertices(DrawWriter* writer,
                       const SkIRect& bounds,
                       const Transform& localToDevice,
                       const Shape& shape) const override {
        SkV4 devPoints[4]; // ordered TL, TR, BR, BL

        if (fInverseFill) {
            // TODO: When we handle local coords, we'd need to map these corners by the inverse.
            devPoints[0] = {(float) bounds.fLeft,  (float) bounds.fTop,    0.f, 1.f};
            devPoints[1] = {(float) bounds.fRight, (float) bounds.fTop,    0.f, 1.f};
            devPoints[2] = {(float) bounds.fRight, (float) bounds.fBottom, 0.f, 1.f};
            devPoints[3] = {(float) bounds.fLeft,  (float) bounds.fBottom, 0.f, 1.f};
        } else {
            localToDevice.mapPoints(shape.bounds(), devPoints);
        }

        DrawWriter::Vertices verts{*writer};
        verts.append(6) << devPoints[0].x << devPoints[0].y << devPoints[0].w // TL
                        << devPoints[3].x << devPoints[3].y << devPoints[3].w // BL
                        << devPoints[1].x << devPoints[1].y << devPoints[1].w // TR
                        << devPoints[1].x << devPoints[1].y << devPoints[1].w // TR
                        << devPoints[3].x << devPoints[3].y << devPoints[3].w // BL
                        << devPoints[2].x << devPoints[2].y << devPoints[2].w;// BR
    }

    sk_sp<SkUniformData> writeUniforms(Layout layout,
                                       const SkIRect&,
                                       const Transform& localToDevice,
                                       const Shape&) const override {
        // Positions are pre-transformed on the CPU so no uniforms needed
        return nullptr;
    }

private:
    const bool fInverseFill;
};

} // anonymous namespace

const Renderer& Renderer::StencilAndFillPath(SkPathFillType fillType) {
    // Because each fill type uses a different stencil settings, there is one Renderer per type.
    // However, at each stage (stencil vs. cover), there are only two RenderSteps to branch on.
    static const StencilFanRenderStep kWindingStencilFan{false};
    static const StencilFanRenderStep kEvenOddStencilFan{true};
    static const FillBoundsRenderStep kFill{false};
    static const FillBoundsRenderStep kInverseFill{true};

    // TODO: Uncomment and include the curve stenciling steps to draw curved paths
    static const Renderer kWindingRenderer{"stencil-and-fill[winding]",
                                           &kWindingStencilFan,
                                           /*&kWindingStencilCurves,*/
                                           &kFill};
    static const Renderer kInverseWindingRenderer{"stencil-and-fill[inverse-winding]",
                                                  &kWindingStencilFan,
                                                  /*&kWindingStencilCurves,*/
                                                  &kInverseFill};
    static const Renderer kEvenOddRenderer{"stencil-and-fill[evenodd]",
                                           &kEvenOddStencilFan,
                                           /*&kEvenOddStencilCurves,*/
                                           &kFill};
    static const Renderer kInverseEvenOddRenderer{"stencil-and-fill[inverse-evenodd]",
                                                  &kEvenOddStencilFan,
                                                  /*&kEvenOddStencilCurves,*/
                                                  &kInverseFill};

    switch(fillType) {
        case SkPathFillType::kWinding: return kWindingRenderer;
        case SkPathFillType::kEvenOdd: return kEvenOddRenderer;
        case SkPathFillType::kInverseWinding: return kInverseWindingRenderer;
        case SkPathFillType::kInverseEvenOdd: return kInverseEvenOddRenderer;
    }
    SkUNREACHABLE;
}

} // namespace skgpu
