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

#ifndef PathTessellateOp_DEFINED
#define PathTessellateOp_DEFINED

#include "src/gpu/ganesh/ops/GrDrawOp.h"
#include "src/gpu/ganesh/tessellate/GrTessellationShader.h"
#include "src/gpu/ganesh/tessellate/PathTessellator.h"
#include "src/gpu/tessellate/Tessellation.h"

namespace skgpu::v1 {

// Tessellates a path directly to the color buffer, using one single render pass. This currently
// only works for convex paths.
class PathTessellateOp final : public GrDrawOp {
private:
    DEFINE_OP_CLASS_ID

    using PatchAttribs = PathTessellator::PatchAttribs;
    using PathDrawList = PathTessellator::PathDrawList;

    PathTessellateOp(SkArenaAlloc* arena,
                     GrAAType aaType,
                     const GrUserStencilSettings* stencil,
                     const SkMatrix& viewMatrix,
                     const SkPath& path,
                     GrPaint&& paint,
                     const SkRect& drawBounds)
            : GrDrawOp(ClassID())
            , fAAType(aaType)
            , fStencil(stencil)
            , fTotalCombinedPathVerbCnt(path.countVerbs())
            , fPathDrawList(arena->make<PathDrawList>(SkMatrix::I(), path, paint.getColor4f()))
            , fPathDrawTail(&fPathDrawList->fNext)
            , fProcessors(std::move(paint))
            , fShaderMatrix(viewMatrix) {
        SkASSERT(!path.isInverseFillType());
        if (!this->headDraw().fColor.fitsInBytes()) {
            fPatchAttribs |= PatchAttribs::kWideColorIfEnabled;
        }
        this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
    }

    PathDrawList& headDraw() { return *fPathDrawList; }

    void prepareTessellator(const GrTessellationShader::ProgramArgs&, GrAppliedClip&& clip);

    // GrDrawOp overrides.
    const char* name() const override { return "PathTessellateOp"; }
    bool usesMSAA() const override { return fAAType == GrAAType::kMSAA; }
    void visitProxies(const GrVisitProxyFunc&) const override;
    GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
    bool usesStencil() const override { return !fStencil->isUnused(); }
    CombineResult onCombineIfPossible(GrOp*, SkArenaAlloc*, const GrCaps&) override;
    void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
                      const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override;
    void onPrepare(GrOpFlushState*) override;
    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;

    const GrAAType fAAType;
    const GrUserStencilSettings* const fStencil;
    int fTotalCombinedPathVerbCnt;
    PatchAttribs fPatchAttribs = PatchAttribs::kNone;
    PathDrawList* const fPathDrawList;
    PathDrawList** fPathDrawTail;
    GrProcessorSet fProcessors;
    SkMatrix fShaderMatrix;

    // Decided during prepareTessellator.
    PathTessellator* fTessellator = nullptr;
    const GrProgramInfo* fTessellationProgram = nullptr;

    friend class GrOp;  // For ctor.
};

} // namespace skgpu::v1

#endif // PathTessellateOp_DEFINED
