/*
 * Copyright 2019 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/ganesh/ops/PathInnerTriangulateOp.h"

#include "include/core/SkPathTypes.h"
#include "include/core/SkString.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "include/private/base/SkAlignedStorage.h"
#include "include/private/base/SkOnce.h"
#include "src/base/SkArenaAlloc.h"
#include "src/core/SkSLTypeShared.h"
#include "src/gpu/ResourceKey.h"
#include "src/gpu/ganesh/GrAppliedClip.h"
#include "src/gpu/ganesh/GrEagerVertexAllocator.h"
#include "src/gpu/ganesh/GrGeometryProcessor.h"
#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/GrPipeline.h"
#include "src/gpu/ganesh/GrProcessorAnalysis.h"
#include "src/gpu/ganesh/GrProgramInfo.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrRenderTargetProxy.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrShaderCaps.h"
#include "src/gpu/ganesh/GrShaderVar.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/GrUserStencilSettings.h"
#include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
#include "src/gpu/ganesh/ops/FillPathFlags.h"
#include "src/gpu/ganesh/tessellate/GrPathTessellationShader.h"
#include "src/gpu/ganesh/tessellate/PathTessellator.h"
#include "src/gpu/tessellate/Tessellation.h"

#include <memory>

class GrGLSLVaryingHandler;

namespace skgpu {
class KeyBuilder;
}

using namespace skia_private;

#if !defined(SK_ENABLE_OPTIMIZE_SIZE)

namespace skgpu::ganesh {

namespace {

// Fills an array of convex hulls surrounding 4-point cubic or conic instances. This shader is used
// for the "cover" pass after the curves have been fully stencilled.
class HullShader : public GrPathTessellationShader {
public:
    HullShader(const SkMatrix& viewMatrix, SkPMColor4f color, const GrShaderCaps& shaderCaps)
            : GrPathTessellationShader(kTessellate_HullShader_ClassID,
                                       GrPrimitiveType::kTriangleStrip,
                                       viewMatrix,
                                       color,
                                       PatchAttribs::kNone) {
        fInstanceAttribs.emplace_back("p01", kFloat4_GrVertexAttribType, SkSLType::kFloat4);
        fInstanceAttribs.emplace_back("p23", kFloat4_GrVertexAttribType, SkSLType::kFloat4);
        if (!shaderCaps.fInfinitySupport) {
            // A conic curve is written out with p3=[w,Infinity], but GPUs that don't support
            // infinity can't detect this. On these platforms we also write out an extra float with
            // each patch that explicitly tells the shader what type of curve it is.
            fInstanceAttribs.emplace_back("curveType", kFloat_GrVertexAttribType, SkSLType::kFloat);
        }
        this->setInstanceAttributesWithImplicitOffsets(fInstanceAttribs.data(),
                                                       fInstanceAttribs.size());
        SkASSERT(fInstanceAttribs.size() <= kMaxInstanceAttribCount);

        if (!shaderCaps.fVertexIDSupport) {
            constexpr static Attribute kVertexIdxAttrib("vertexidx", kFloat_GrVertexAttribType,
                                                        SkSLType::kFloat);
            this->setVertexAttributesWithImplicitOffsets(&kVertexIdxAttrib, 1);
        }
    }

private:
    const char* name() const final { return "tessellate_HullShader"; }
    void addToKey(const GrShaderCaps&, KeyBuilder*) const final {}
    std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final;

    constexpr static int kMaxInstanceAttribCount = 3;
    STArray<kMaxInstanceAttribCount, Attribute> fInstanceAttribs;
};

std::unique_ptr<GrGeometryProcessor::ProgramImpl> HullShader::makeProgramImpl(
        const GrShaderCaps&) const {
    class Impl : public GrPathTessellationShader::Impl {
        void emitVertexCode(const GrShaderCaps& shaderCaps,
                            const GrPathTessellationShader&,
                            GrGLSLVertexBuilder* v,
                            GrGLSLVaryingHandler*,
                            GrGPArgs* gpArgs) override {
            if (shaderCaps.fInfinitySupport) {
                v->insertFunction(
                "bool is_conic_curve() { return isinf(p23.w); }"
                "bool is_non_triangular_conic_curve() {"
                    // We consider a conic non-triangular as long as its weight isn't infinity.
                    // NOTE: "isinf == false" works on Mac Radeon GLSL; "!isinf" can get the wrong
                    // answer.
                    "return isinf(p23.z) == false;"
                "}"
                );
            } else {
                v->insertFunction(SkStringPrintf(
                "bool is_conic_curve() { return curveType != %g; }",
                        tess::kCubicCurveType).c_str());
                v->insertFunction(SkStringPrintf(
                "bool is_non_triangular_conic_curve() {"
                    "return curveType == %g;"
                "}", tess::kConicCurveType).c_str());
            }
            v->codeAppend(
            "float2 p0=p01.xy, p1=p01.zw, p2=p23.xy, p3=p23.zw;"
            "if (is_conic_curve()) {"
                // Conics are 3 points, with the weight in p3.
                "float w = p3.x;"
                "p3 = p2;"  // Duplicate the endpoint for shared code that also runs on cubics.
                "if (is_non_triangular_conic_curve()) {"
                    // Convert the points to a trapeziodal hull that circumcscribes the conic.
                    "float2 p1w = p1 * w;"
                    "float T = .51;"  // Bias outward a bit to ensure we cover the outermost samples.
                    "float2 c1 = mix(p0, p1w, T);"
                    "float2 c2 = mix(p2, p1w, T);"
                    "float iw = 1 / mix(1, w, T);"
                    "p2 = c2 * iw;"
                    "p1 = c1 * iw;"
                "}"
            "}"

            // Translate the points to v0..3 where v0=0.
            "float2 v1 = p1 - p0;"
            "float2 v2 = p2 - p0;"
            "float2 v3 = p3 - p0;"

            // Reorder the points so v2 bisects v1 and v3.
            "if (sign(cross_length_2d(v2, v1)) == sign(cross_length_2d(v2, v3))) {"
                "float2 tmp = p2;"
                "if (sign(cross_length_2d(v1, v2)) != sign(cross_length_2d(v1, v3))) {"
                    "p2 = p1;"  // swap(p2, p1)
                    "p1 = tmp;"
                "} else {"
                    "p2 = p3;"  // swap(p2, p3)
                    "p3 = tmp;"
                "}"
            "}"
            );

            if (shaderCaps.fVertexIDSupport) {
                // If we don't have sk_VertexID support then "vertexidx" already came in as a
                // vertex attrib.
                v->codeAppend(
                // sk_VertexID comes in fan order. Convert to strip order.
                "int vertexidx = sk_VertexID;"
                "vertexidx ^= vertexidx >> 1;");
            }

            v->codeAppend(
            // Find the "turn direction" of each corner and net turn direction.
            "float vertexdir = 0;"
            "float netdir = 0;"
            "float2 prev, next;"
            "float dir;"
            "float2 localcoord;"
            "float2 nextcoord;"
            );

            for (int i = 0; i < 4; ++i) {
                v->codeAppendf(
                "prev = p%i - p%i;", i, (i + 3) % 4);
                v->codeAppendf(
                "next = p%i - p%i;", (i + 1) % 4, i);
                v->codeAppendf(
                "dir = sign(cross_length_2d(prev, next));"
                "if (vertexidx == %i) {"
                    "vertexdir = dir;"
                    "localcoord = p%i;"
                    "nextcoord = p%i;"
                "}"
                "netdir += dir;", i, i, (i + 1) % 4);
            }

            v->codeAppend(
            // Remove the non-convex vertex, if any.
            "if (vertexdir != sign(netdir)) {"
                "localcoord = nextcoord;"
            "}"

            "float2 vertexpos = AFFINE_MATRIX * localcoord + TRANSLATE;");
            gpArgs->fLocalCoordVar.set(SkSLType::kFloat2, "localcoord");
            gpArgs->fPositionVar.set(SkSLType::kFloat2, "vertexpos");
        }
    };
    return std::make_unique<Impl>();
}

}  // anonymous namespace

void PathInnerTriangulateOp::visitProxies(const GrVisitProxyFunc& func) const {
    if (fPipelineForFills) {
        fPipelineForFills->visitProxies(func);
    } else {
        fProcessors.visitProxies(func);
    }
}

GrDrawOp::FixedFunctionFlags PathInnerTriangulateOp::fixedFunctionFlags() const {
    auto flags = FixedFunctionFlags::kUsesStencil;
    if (GrAAType::kNone != fAAType) {
        flags |= FixedFunctionFlags::kUsesHWAA;
    }
    return flags;
}

GrProcessorSet::Analysis PathInnerTriangulateOp::finalize(const GrCaps& caps,
                                                          const GrAppliedClip* clip,
                                                          GrClampType clampType) {
    return fProcessors.finalize(fColor, GrProcessorAnalysisCoverage::kNone, clip, nullptr, caps,
                                clampType, &fColor);
}

void PathInnerTriangulateOp::pushFanStencilProgram(const GrTessellationShader::ProgramArgs& args,
                                                   const GrPipeline* pipelineForStencils,
                                                   const GrUserStencilSettings* stencil) {
    SkASSERT(pipelineForStencils);
    auto shader = GrPathTessellationShader::MakeSimpleTriangleShader(args.fArena, fViewMatrix,
                                                                     SK_PMColor4fTRANSPARENT);
    fFanPrograms.push_back(GrTessellationShader::MakeProgram(args, shader, pipelineForStencils,
                                                             stencil)); }

void PathInnerTriangulateOp::pushFanFillProgram(const GrTessellationShader::ProgramArgs& args,
                                                const GrUserStencilSettings* stencil) {
    SkASSERT(fPipelineForFills);
    auto shader = GrPathTessellationShader::MakeSimpleTriangleShader(args.fArena, fViewMatrix,
                                                                     fColor);
    fFanPrograms.push_back(GrTessellationShader::MakeProgram(args, shader, fPipelineForFills,
                                                             stencil));
}

void PathInnerTriangulateOp::prePreparePrograms(const GrTessellationShader::ProgramArgs& args,
                                                GrAppliedClip&& appliedClip) {
    SkASSERT(!fFanTriangulator);
    SkASSERT(!fFanPolys);
    SkASSERT(!fPipelineForFills);
    SkASSERT(!fTessellator);
    SkASSERT(!fStencilCurvesProgram);
    SkASSERT(fFanPrograms.empty());
    SkASSERT(!fCoverHullsProgram);

    if (fPath.countVerbs() <= 0) {
        return;
    }

    // If using wireframe, we have to fall back on a standard Redbook "stencil then cover" algorithm
    // instead of bypassing the stencil buffer to fill the fan directly.
    bool forceRedbookStencilPass =
            (fPathFlags & (FillPathFlags::kStencilOnly | FillPathFlags::kWireframe));
    bool doFill = !(fPathFlags & FillPathFlags::kStencilOnly);

    bool isLinear;
    fFanTriangulator = args.fArena->make<GrInnerFanTriangulator>(fPath, args.fArena);
    fFanPolys = fFanTriangulator->pathToPolys(&fFanBreadcrumbs, &isLinear);

    // Create a pipeline for stencil passes if needed.
    const GrPipeline* pipelineForStencils = nullptr;
    if (forceRedbookStencilPass || !isLinear) {  // Curves always get stencilled.
        auto pipelineFlags = (fPathFlags & FillPathFlags::kWireframe)
                ? GrPipeline::InputFlags::kWireframe
                : GrPipeline::InputFlags::kNone;
        pipelineForStencils = GrPathTessellationShader::MakeStencilOnlyPipeline(
                args, fAAType, appliedClip.hardClip(), pipelineFlags);
    }

    // Create a pipeline for fill passes if needed.
    if (doFill) {
        fPipelineForFills = GrTessellationShader::MakePipeline(args, fAAType,
                                                               std::move(appliedClip),
                                                               std::move(fProcessors));
    }

    // Pass 1: Tessellate the outer curves into the stencil buffer.
    if (!isLinear) {
        fTessellator = PathCurveTessellator::Make(args.fArena,
                                                  args.fCaps->shaderCaps()->fInfinitySupport);
        auto* tessShader = GrPathTessellationShader::Make(*args.fCaps->shaderCaps(),
                                                          args.fArena,
                                                          fViewMatrix,
                                                          SK_PMColor4fTRANSPARENT,
                                                          fTessellator->patchAttribs());
        const GrUserStencilSettings* stencilPathSettings =
                GrPathTessellationShader::StencilPathSettings(GrFillRuleForSkPath(fPath));
        fStencilCurvesProgram = GrTessellationShader::MakeProgram(args,
                                                                  tessShader,
                                                                  pipelineForStencils,
                                                                  stencilPathSettings);
    }

    // Pass 2: Fill the path's inner fan with a stencil test against the curves.
    if (fFanPolys) {
        if (forceRedbookStencilPass) {
            // Use a standard Redbook "stencil then cover" algorithm instead of bypassing the
            // stencil buffer to fill the fan directly.
            const GrUserStencilSettings* stencilPathSettings =
                    GrPathTessellationShader::StencilPathSettings(GrFillRuleForSkPath(fPath));
            this->pushFanStencilProgram(args, pipelineForStencils, stencilPathSettings);
            if (doFill) {
                this->pushFanFillProgram(args,
                                         GrPathTessellationShader::TestAndResetStencilSettings());
            }
        } else if (isLinear) {
            // There are no outer curves! Ignore stencil and fill the path directly.
            SkASSERT(!pipelineForStencils);
            this->pushFanFillProgram(args, &GrUserStencilSettings::kUnused);
        } else if (!fPipelineForFills->hasStencilClip()) {
            // These are a twist on the standard Redbook stencil settings that allow us to fill the
            // inner polygon directly to the final render target. By the time these programs
            // execute, the outer curves will already be stencilled in. So if the stencil value is
            // zero, then it means the sample in question is not affected by any curves and we can
            // fill it in directly. If the stencil value is nonzero, then we don't fill and instead
            // continue the standard Redbook counting process.
            constexpr static GrUserStencilSettings kFillOrIncrDecrStencil(
                GrUserStencilSettings::StaticInitSeparate<
                    0x0000,                       0x0000,
                    GrUserStencilTest::kEqual,    GrUserStencilTest::kEqual,
                    0xffff,                       0xffff,
                    GrUserStencilOp::kKeep,       GrUserStencilOp::kKeep,
                    GrUserStencilOp::kIncWrap,    GrUserStencilOp::kDecWrap,
                    0xffff,                       0xffff>());

            constexpr static GrUserStencilSettings kFillOrInvertStencil(
                GrUserStencilSettings::StaticInit<
                    0x0000,
                    GrUserStencilTest::kEqual,
                    0xffff,
                    GrUserStencilOp::kKeep,
                    // "Zero" instead of "Invert" because the fan only touches any given pixel once.
                    GrUserStencilOp::kZero,
                    0xffff>());

            auto* stencil = (fPath.getFillType() == SkPathFillType::kWinding)
                    ? &kFillOrIncrDecrStencil
                    : &kFillOrInvertStencil;
            this->pushFanFillProgram(args, stencil);
        } else {
            // This is the same idea as above, but we use two passes instead of one because there is
            // a stencil clip. The stencil test isn't expressive enough to do the above tests and
            // also check the clip bit in a single pass.
            constexpr static GrUserStencilSettings kFillIfZeroAndInClip(
                GrUserStencilSettings::StaticInit<
                    0x0000,
                    GrUserStencilTest::kEqualIfInClip,
                    0xffff,
                    GrUserStencilOp::kKeep,
                    GrUserStencilOp::kKeep,
                    0xffff>());

            constexpr static GrUserStencilSettings kIncrDecrStencilIfNonzero(
                GrUserStencilSettings::StaticInitSeparate<
                    0x0000,                         0x0000,
                    // No need to check the clip because the previous stencil pass will have only
                    // written to samples already inside the clip.
                    GrUserStencilTest::kNotEqual,   GrUserStencilTest::kNotEqual,
                    0xffff,                         0xffff,
                    GrUserStencilOp::kIncWrap,      GrUserStencilOp::kDecWrap,
                    GrUserStencilOp::kKeep,         GrUserStencilOp::kKeep,
                    0xffff,                         0xffff>());

            constexpr static GrUserStencilSettings kInvertStencilIfNonZero(
                GrUserStencilSettings::StaticInit<
                    0x0000,
                    // No need to check the clip because the previous stencil pass will have only
                    // written to samples already inside the clip.
                    GrUserStencilTest::kNotEqual,
                    0xffff,
                    // "Zero" instead of "Invert" because the fan only touches any given pixel once.
                    GrUserStencilOp::kZero,
                    GrUserStencilOp::kKeep,
                    0xffff>());

            // Pass 2a: Directly fill fan samples whose stencil values (from curves) are zero.
            this->pushFanFillProgram(args, &kFillIfZeroAndInClip);

            // Pass 2b: Redbook counting on fan samples whose stencil values (from curves) != 0.
            auto* stencil = (fPath.getFillType() == SkPathFillType::kWinding)
                    ? &kIncrDecrStencilIfNonzero
                    : &kInvertStencilIfNonZero;
            this->pushFanStencilProgram(args, pipelineForStencils, stencil);
        }
    }

    // Pass 3: Draw convex hulls around each curve.
    if (doFill && !isLinear) {
        // By the time this program executes, every pixel will be filled in except the ones touched
        // by curves. We issue a final cover pass over the curves by drawing their convex hulls.
        // This will fill in any remaining samples and reset the stencil values back to zero.
        SkASSERT(fTessellator);
        auto* hullShader = args.fArena->make<HullShader>(fViewMatrix, fColor,
                                                         *args.fCaps->shaderCaps());
        fCoverHullsProgram = GrTessellationShader::MakeProgram(
                args, hullShader, fPipelineForFills,
                GrPathTessellationShader::TestAndResetStencilSettings());
    }
}

void PathInnerTriangulateOp::onPrePrepare(GrRecordingContext* context,
                                          const GrSurfaceProxyView& writeView,
                                          GrAppliedClip* clip,
                                          const GrDstProxyView& dstProxyView,
                                          GrXferBarrierFlags renderPassXferBarriers,
                                          GrLoadOp colorLoadOp) {
    // DMSAA is not supported on DDL.
    bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;
    this->prePreparePrograms({context->priv().recordTimeAllocator(), writeView, usesMSAASurface,
                             &dstProxyView, renderPassXferBarriers, colorLoadOp,
                             context->priv().caps()},
                             (clip) ? std::move(*clip) : GrAppliedClip::Disabled());
    if (fStencilCurvesProgram) {
        context->priv().recordProgramInfo(fStencilCurvesProgram);
    }
    for (const GrProgramInfo* fanProgram : fFanPrograms) {
        context->priv().recordProgramInfo(fanProgram);
    }
    if (fCoverHullsProgram) {
        context->priv().recordProgramInfo(fCoverHullsProgram);
    }
}

SKGPU_DECLARE_STATIC_UNIQUE_KEY(gHullVertexBufferKey);

void PathInnerTriangulateOp::onPrepare(GrOpFlushState* flushState) {
    const GrCaps& caps = flushState->caps();

    if (!fFanTriangulator) {
        this->prePreparePrograms({flushState->allocator(), flushState->writeView(),
                                 flushState->usesMSAASurface(), &flushState->dstProxyView(),
                                 flushState->renderPassBarriers(), flushState->colorLoadOp(),
                                 &caps}, flushState->detachAppliedClip());
        if (!fFanTriangulator) {
            return;
        }
    }

    if (fFanPolys) {
        GrEagerDynamicVertexAllocator alloc(flushState, &fFanBuffer, &fBaseFanVertex);
        fFanVertexCount = fFanTriangulator->polysToTriangles(fFanPolys, &alloc, &fFanBreadcrumbs);
    }

    if (fTessellator) {
        auto tessShader = &fStencilCurvesProgram->geomProc().cast<GrPathTessellationShader>();
        fTessellator->prepareWithTriangles(flushState,
                                           tessShader->viewMatrix(),
                                           &fFanBreadcrumbs,
                                           {SkMatrix::I(), fPath, SK_PMColor4fTRANSPARENT},
                                           fPath.countVerbs());
    }

    if (!caps.shaderCaps()->fVertexIDSupport) {
        constexpr static float kStripOrderIDs[4] = {0, 1, 3, 2};

        SKGPU_DEFINE_STATIC_UNIQUE_KEY(gHullVertexBufferKey);

        fHullVertexBufferIfNoIDSupport = flushState->resourceProvider()->findOrMakeStaticBuffer(
                GrGpuBufferType::kVertex, sizeof(kStripOrderIDs), kStripOrderIDs,
                gHullVertexBufferKey);
    }
}

void PathInnerTriangulateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
    if (fCoverHullsProgram &&
        fCoverHullsProgram->geomProc().hasVertexAttributes() &&
        !fHullVertexBufferIfNoIDSupport) {
        return;
    }

    if (fStencilCurvesProgram) {
        SkASSERT(fTessellator);
        flushState->bindPipelineAndScissorClip(*fStencilCurvesProgram, this->bounds());
        fTessellator->draw(flushState);
    }

    // Allocation of the fan vertex buffer may have failed but we already pushed back fan programs.
    if (fFanBuffer) {
        for (const GrProgramInfo* fanProgram : fFanPrograms) {
            flushState->bindPipelineAndScissorClip(*fanProgram, this->bounds());
            flushState->bindTextures(fanProgram->geomProc(), nullptr, fanProgram->pipeline());
            flushState->bindBuffers(nullptr, nullptr, fFanBuffer);
            flushState->draw(fFanVertexCount, fBaseFanVertex);
        }
    }

    if (fCoverHullsProgram) {
        SkASSERT(fTessellator);
        flushState->bindPipelineAndScissorClip(*fCoverHullsProgram, this->bounds());
        flushState->bindTextures(fCoverHullsProgram->geomProc(), nullptr, *fPipelineForFills);
        fTessellator->drawHullInstances(flushState, fHullVertexBufferIfNoIDSupport);
    }
}

}  // namespace skgpu::ganesh

#endif // SK_ENABLE_OPTIMIZE_SIZE
