/*
 * 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 "src/gpu/ops/DrawCustomMeshOp.h"

#include "include/core/SkCustomMesh.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkCustomMeshPriv.h"
#include "src/core/SkVerticesPriv.h"
#include "src/gpu/BufferWriter.h"
#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/KeyBuilder.h"
#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
#include "src/sksl/codegen/SkSLPipelineStageCodeGenerator.h"
#include "src/sksl/ir/SkSLProgram.h"

namespace {

GrPrimitiveType primitive_type(SkCustomMesh::Mode mode) {
    switch (mode) {
        case SkCustomMesh::Mode::kTriangles:     return GrPrimitiveType::kTriangles;
        case SkCustomMesh::Mode::kTriangleStrip: return GrPrimitiveType::kTriangleStrip;
    }
    SkUNREACHABLE;
}

class CustomMeshGP : public GrGeometryProcessor {
public:
    static GrGeometryProcessor* Make(SkArenaAlloc* arena,
                                     sk_sp<SkCustomMeshSpecification> spec,
                                     sk_sp<GrColorSpaceXform> colorSpaceXform,
                                     const SkMatrix& viewMatrix,
                                     const std::optional<SkPMColor4f>& color,
                                     bool needsLocalCoords) {
        return arena->make([&](void* ptr) {
            return new (ptr) CustomMeshGP(std::move(spec),
                                          std::move(colorSpaceXform),
                                          viewMatrix,
                                          std::move(color),
                                          needsLocalCoords);
        });
    }

    const char* name() const override { return "CustomMeshGP"; }

    void addToKey(const GrShaderCaps& caps, skgpu::KeyBuilder* b) const override {
        b->add32(SkCustomMeshSpecificationPriv::Hash(*fSpec), "custom mesh spec hash");
        b->add32(ProgramImpl::ComputeMatrixKey(caps, fViewMatrix), "view matrix key");
        if (SkCustomMeshSpecificationPriv::GetColorType(*fSpec) !=
            SkCustomMeshSpecificationPriv::ColorType::kNone) {
            b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()), "colorspace xform key");
        }
    }

    std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override {
        return std::make_unique<Impl>();
    }

private:
    class Impl : public ProgramImpl {
    public:
        void setData(const GrGLSLProgramDataManager& pdman,
                     const GrShaderCaps& shaderCaps,
                     const GrGeometryProcessor& geomProc) override {
            const auto& cmgp = geomProc.cast<CustomMeshGP>();
            SetTransform(pdman, shaderCaps, fViewMatrixUniform, cmgp.fViewMatrix, &fViewMatrix);
            fColorSpaceHelper.setData(pdman, cmgp.fColorSpaceXform.get());
            if (fColorUniform.isValid()) {
                pdman.set4fv(fColorUniform, 1, cmgp.fColor.vec());
            }
        }

    private:
        class MeshCallbacks : public SkSL::PipelineStage::Callbacks {
        public:
            MeshCallbacks(Impl* self,
                          GrGLSLShaderBuilder* builder,
                          const char* mainName,
                          const SkSL::Context& context)
                    : fSelf(self), fBuilder(builder), fMainName(mainName), fContext(context) {}

            std::string declareUniform(const SkSL::VarDeclaration* decl) override {
                SK_ABORT("uniforms not allowed");
            }

            std::string getMangledName(const char* name) override {
                return std::string(fBuilder->getMangledFunctionName(name).c_str());
            }

            std::string getMainName() override { return fMainName; }

            void defineFunction(const char* decl, const char* body, bool isMain) override {
                fBuilder->emitFunction(decl, body);
            }

            void declareFunction(const char* decl) override {
                fBuilder->emitFunctionPrototype(decl);
            }

            void defineStruct(const char* definition) override {
                fBuilder->definitionAppend(definition);
            }

            void declareGlobal(const char* declaration) override {
                fBuilder->definitionAppend(declaration);
            }

            std::string sampleShader(int index, std::string coords) override {
                SK_ABORT("No children allowed.");
            }

            std::string sampleColorFilter(int index, std::string color) override {
                SK_ABORT("No children allowed.");
            }

            std::string sampleBlender(int index, std::string src, std::string dst) override {
                SK_ABORT("No children allowed.");
            }

            std::string toLinearSrgb(std::string color) override {
                SK_ABORT("Color transform intrinsics not allowed.");
            }

            std::string fromLinearSrgb(std::string Color) override {
                SK_ABORT("Color transform intrinsics not allowed.");
            }

            Impl*                 fSelf;
            GrGLSLShaderBuilder*  fBuilder;
            const char*           fMainName;
            const SkSL::Context&  fContext;
        };

        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
            const CustomMeshGP& cmgp = args.fGeomProc.cast<CustomMeshGP>();
            GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
            GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
            GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
            GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;

            ////// VS

            // emit attributes
            varyingHandler->emitAttributes(cmgp);

            // Define the user's vert function.
            SkString userVertName = vertBuilder->getMangledFunctionName("custom_mesh_vs");
            const SkSL::Program* customVS = SkCustomMeshSpecificationPriv::VS(*cmgp.fSpec);
            MeshCallbacks vsCallbacks(this, vertBuilder, userVertName.c_str(), *customVS->fContext);
            SkSL::PipelineStage::ConvertProgram(*customVS,
                                                /*sampleCoords=*/"",
                                                /*inputColor=*/"",
                                                /*destColor=*/"",
                                                &vsCallbacks);

            // Copy the individual attributes into a struct
            vertBuilder->codeAppendf("%s attributes;",
                                     vsCallbacks.getMangledName("Attributes").c_str());
            size_t i = 0;
            SkASSERT(cmgp.vertexAttributes().count() == (int)cmgp.fSpec->attributes().size());
            for (auto attr : cmgp.vertexAttributes()) {
                vertBuilder->codeAppendf("attributes.%s = %s;",
                                         cmgp.fSpec->attributes()[i++].name.c_str(),
                                         attr.name());
            }

            // Call the user's vert function.
            vertBuilder->codeAppendf("%s varyings;",
                                     vsCallbacks.getMangledName("Varyings").c_str());
            vertBuilder->codeAppendf("float2 pos = %s(attributes, varyings);",
                                     userVertName.c_str());

            // Unpack the varyings from the struct into individual varyings.
            std::vector<GrGLSLVarying> varyings;
            varyings.reserve(SkCustomMeshSpecificationPriv::Varyings(*cmgp.fSpec).size());
            for (const auto& v : SkCustomMeshSpecificationPriv::Varyings(*cmgp.fSpec)) {
                varyings.emplace_back(SkCustomMeshSpecificationPriv::VaryingTypeAsSLType(v.type));
                varyingHandler->addVarying(v.name.c_str(), &varyings.back());
                vertBuilder->codeAppendf("%s = varyings.%s;",
                                         varyings.back().vsOut(),
                                         v.name.c_str());
            }

            // Setup position
            WriteOutputPosition(vertBuilder,
                                uniformHandler,
                                *args.fShaderCaps,
                                gpArgs,
                                "pos",
                                cmgp.fViewMatrix,
                                &fViewMatrixUniform);

            ////// FS

            fragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
            fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);

            // Define the user's frag function.
            SkString userFragName = fragBuilder->getMangledFunctionName("custom_mesh_fs");
            const SkSL::Program* customFS = SkCustomMeshSpecificationPriv::FS(*cmgp.fSpec);
            MeshCallbacks fsCallbacks(this, fragBuilder, userFragName.c_str(), *customFS->fContext);
            SkSL::PipelineStage::ConvertProgram(*customFS,
                                                /*sampleCoords=*/"",
                                                /*inputColor=*/"",
                                                /*destColor=*/"",
                                                &fsCallbacks);

            // Pack the varyings into a struct to call the user's frag code.
            fragBuilder->codeAppendf("%s varyings;",
                                     fsCallbacks.getMangledName("Varyings").c_str());
            i = 0;
            for (const auto& varying : SkCustomMeshSpecificationPriv::Varyings(*cmgp.fSpec)) {
                fragBuilder->codeAppendf("varyings.%s = %s;",
                                         varying.name.c_str(),
                                         varyings[i++].vsOut());
            }
            SkCustomMeshSpecificationPriv::ColorType meshColorType =
                    SkCustomMeshSpecificationPriv::GetColorType(*cmgp.fSpec);
            const char* uniformColorName = nullptr;
            if (cmgp.fColor != SK_PMColor4fILLEGAL) {
                fColorUniform = uniformHandler->addUniform(nullptr,
                                                           kFragment_GrShaderFlag,
                                                           SkSLType::kHalf4,
                                                           "color",
                                                           &uniformColorName);
            }
            SkString localCoordAssignment;
            if (SkCustomMeshSpecificationPriv::HasLocalCoords(*cmgp.fSpec) &&
                cmgp.fNeedsLocalCoords) {
                localCoordAssignment = "float2 local =";
            }
            if (meshColorType == SkCustomMeshSpecificationPriv::ColorType::kNone) {
                fragBuilder->codeAppendf("%s %s(varyings);",
                                         localCoordAssignment.c_str(),
                                         userFragName.c_str());
                SkASSERT(uniformColorName);
                fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, uniformColorName);
            } else {
                fColorSpaceHelper.emitCode(uniformHandler,
                                           cmgp.fColorSpaceXform.get(),
                                           kFragment_GrShaderFlag);
                if (meshColorType == SkCustomMeshSpecificationPriv::ColorType::kFloat4) {
                    fragBuilder->codeAppendf("float4 color;");
                } else {
                    SkASSERT(meshColorType == SkCustomMeshSpecificationPriv::ColorType::kHalf4);
                    fragBuilder->codeAppendf("half4 color;");
                }

                fragBuilder->codeAppendf("%s %s(varyings, color);",
                                         localCoordAssignment.c_str(),
                                         userFragName.c_str());
                // We ignore the user's color if analysis told us to emit a specific color. The user
                // color might be float4 and we expect a half4 in the colorspace helper.
                const char* color = uniformColorName ? uniformColorName : "half4(color)";
                SkString xformedColor;
                fragBuilder->appendColorGamutXform(&xformedColor, color, &fColorSpaceHelper);
                fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, xformedColor.c_str());
            }
            if (cmgp.fNeedsLocalCoords) {
                if (SkCustomMeshSpecificationPriv::HasLocalCoords(*cmgp.fSpec)) {
                    gpArgs->fLocalCoordVar = GrShaderVar("local", SkSLType::kFloat2);
                    gpArgs->fLocalCoordShader = kFragment_GrShaderType;
                } else {
                    gpArgs->fLocalCoordVar = GrShaderVar("pos", SkSLType::kFloat2);
                    gpArgs->fLocalCoordShader = kVertex_GrShaderType;
                }
            }
        }

    private:
        SkMatrix fViewMatrix = SkMatrix::InvalidMatrix();

        UniformHandle fViewMatrixUniform;
        UniformHandle fColorUniform;

        GrGLSLColorSpaceXformHelper fColorSpaceHelper;
    };

    CustomMeshGP(sk_sp<SkCustomMeshSpecification>    spec,
                 sk_sp<GrColorSpaceXform>            colorSpaceXform,
                 const SkMatrix&                     viewMatrix,
                 const std::optional<SkPMColor4f>& color,
                 bool                                needsLocalCoords)
            : INHERITED(kVerticesGP_ClassID)
            , fSpec(std::move(spec))
            , fViewMatrix(viewMatrix)
            , fColorSpaceXform(std::move(colorSpaceXform))
            , fNeedsLocalCoords(needsLocalCoords) {
        fColor = color.value_or(SK_PMColor4fILLEGAL);
        for (const auto& srcAttr : fSpec->attributes()) {
            fAttributes.emplace_back(
                    srcAttr.name.c_str(),
                    SkCustomMeshSpecificationPriv::AttrTypeAsVertexAttribType(srcAttr.type),
                    SkCustomMeshSpecificationPriv::AttrTypeAsSLType(srcAttr.type),
                    srcAttr.offset);
        }
        this->setVertexAttributes(fAttributes.data(), fAttributes.size(), fSpec->stride());
    }

    sk_sp<SkCustomMeshSpecification> fSpec;
    std::vector<Attribute>           fAttributes;
    SkMatrix                         fViewMatrix;
    SkPMColor4f                      fColor;
    sk_sp<GrColorSpaceXform>         fColorSpaceXform;
    bool                             fNeedsLocalCoords;

    using INHERITED = GrGeometryProcessor;
};

class CustomMeshOp final : public GrMeshDrawOp {
private:
    using Helper = GrSimpleMeshDrawOpHelper;

public:
    DEFINE_OP_CLASS_ID

    CustomMeshOp(GrProcessorSet*,
                 const SkPMColor4f&,
                 SkCustomMesh,
                 GrAAType,
                 sk_sp<GrColorSpaceXform>,
                 const SkMatrixProvider&);

    CustomMeshOp(GrProcessorSet*,
                 const SkPMColor4f&,
                 sk_sp<SkVertices>,
                 const GrPrimitiveType*,
                 GrAAType,
                 sk_sp<GrColorSpaceXform>,
                 const SkMatrixProvider&);

    const char* name() const override { return "CustomMeshOp"; }

    void visitProxies(const GrVisitProxyFunc& func) const override {
        if (fProgramInfo) {
            fProgramInfo->visitFPProxies(func);
        } else {
            fHelper.visitProxies(func);
        }
    }

    FixedFunctionFlags fixedFunctionFlags() const override;

    GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;

private:
    GrProgramInfo* programInfo() override { return fProgramInfo; }

    void onCreateProgramInfo(const GrCaps*,
                             SkArenaAlloc*,
                             const GrSurfaceProxyView& writeView,
                             bool usesMSAASurface,
                             GrAppliedClip&&,
                             const GrDstProxyView&,
                             GrXferBarrierFlags renderPassXferBarriers,
                             GrLoadOp colorLoadOp) override;

    void onPrepareDraws(GrMeshDrawTarget*) override;
    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
#if GR_TEST_UTILS
    SkString onDumpInfo() const override;
#endif

    GrGeometryProcessor* makeGP(SkArenaAlloc*);

    CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps&) override;

    /**
     * Built either from a SkCustomMesh or a SkVertices. In the former case the data is owned
     * by Mesh and in the latter it is not. Meshes made from SkVertices can contain a SkMatrix
     * to enable CPU-based transformation but Meshes made from SkCustomMesh cannot.
     */
    class Mesh {
    public:
        Mesh() = delete;
        Mesh(const SkCustomMesh& cm);
        Mesh(sk_sp<SkVertices>, const SkMatrix& viewMatrix);
        Mesh(const Mesh&) = delete;
        Mesh(Mesh&& m);

        Mesh& operator=(const Mesh&) = delete;
        Mesh& operator=(Mesh&&) = delete; // not used by SkSTArray but could be implemented.

        ~Mesh();

        bool isFromVertices() const { return SkToBool(fVertices); }

        void writeVertices(skgpu::VertexWriter& writer,
                           const SkCustomMeshSpecification& spec,
                           bool transform) const;

        int vertexCount() const {
            return this->isFromVertices() ? fVertices->priv().vertexCount() : fCMData.vcount;
        }

        const uint16_t* indices() const {
            return this->isFromVertices() ? fVertices->priv().indices() : fCMData.indices;
        }

        int indexCount() const {
            return this->isFromVertices() ? fVertices->priv().indexCount() : fCMData.icount;
        }

    private:
        struct CMData {
            const char*     vb;
            const uint16_t* indices;
            int             vcount;
            int             icount;
        };

        sk_sp<SkVertices> fVertices;

        union {
            SkMatrix fViewMatrix;
            CMData   fCMData;
        };
    };

    Helper                           fHelper;
    sk_sp<SkCustomMeshSpecification> fSpecification;
    bool                             fIgnoreSpecColor = false;
    GrPrimitiveType                  fPrimitiveType;
    SkSTArray<1, Mesh>               fMeshes;
    sk_sp<GrColorSpaceXform>         fColorSpaceXform;
    SkPMColor4f                      fColor; // Used if no color from spec or analysis overrides.
    SkMatrix                         fViewMatrix;
    int                              fVertexCount;
    int                              fIndexCount;
    GrSimpleMesh*                    fMesh = nullptr;
    GrProgramInfo*                   fProgramInfo = nullptr;

    using INHERITED = GrMeshDrawOp;
};

CustomMeshOp::Mesh::Mesh(const SkCustomMesh& cm) {
    fCMData.vb       = SkCopyCustomMeshVB(cm).release();
    fCMData.indices  = SkCopyCustomMeshIB(cm).release();
    fCMData.vcount   = cm.vcount;
    fCMData.icount   = cm.icount;
}

CustomMeshOp::Mesh::Mesh(sk_sp<SkVertices> vertices, const SkMatrix& viewMatrix)
        : fVertices(std::move(vertices)), fViewMatrix(viewMatrix) {
    SkASSERT(fVertices);
}

CustomMeshOp::Mesh::Mesh(Mesh&& m) {
    fVertices = std::move(m.fVertices);
    if (fVertices) {
        fViewMatrix = m.fViewMatrix;
    } else {
        fCMData = m.fCMData;
    }
    m.fCMData.vb      = nullptr;
    m.fCMData.indices = nullptr;
}

CustomMeshOp::Mesh::~Mesh() {
    if (!this->isFromVertices()) {
        delete[] fCMData.indices;
        delete[] fCMData.vb;
    }
}

void CustomMeshOp::Mesh::writeVertices(skgpu::VertexWriter& writer,
                                       const SkCustomMeshSpecification& spec,
                                       bool transform) const {
    SkASSERT(!transform || this->isFromVertices());
    if (this->isFromVertices()) {
        int vertexCount = fVertices->priv().vertexCount();
        for (int i = 0; i < vertexCount; ++i) {
            SkPoint pos = fVertices->priv().positions()[i];
            if (transform) {
                SkASSERT(!fViewMatrix.hasPerspective());
                fViewMatrix.mapPoints(&pos, 1);
            }
            writer << pos;
            if (SkCustomMeshSpecificationPriv::HasColors(spec)) {
                SkASSERT(fVertices->priv().hasColors());
                writer << fVertices->priv().colors()[i];
            }
            if (SkCustomMeshSpecificationPriv::HasLocalCoords(spec)) {
                SkASSERT(fVertices->priv().hasTexCoords());
                writer << fVertices->priv().texCoords()[i];
            }
        }
    } else {
        writer << skgpu::VertexWriter::Array(fCMData.vb, spec.stride()*fCMData.vcount);
    }
}

CustomMeshOp::CustomMeshOp(GrProcessorSet*          processorSet,
                           const SkPMColor4f&       color,
                           SkCustomMesh             cm,
                           GrAAType                 aaType,
                           sk_sp<GrColorSpaceXform> colorSpaceXform,
                           const SkMatrixProvider&  matrixProvider)
        : INHERITED(ClassID())
        , fHelper(processorSet, aaType)
        , fPrimitiveType(primitive_type(cm.mode))
        , fColorSpaceXform(std::move(colorSpaceXform))
        , fColor(color)
        , fViewMatrix(matrixProvider.localToDevice()) {
    fMeshes.emplace_back(cm);

    fSpecification = std::move(cm.spec);

    fVertexCount = fMeshes.back().vertexCount();
    fIndexCount  = fMeshes.back().indexCount();

    this->setTransformedBounds(cm.bounds, fViewMatrix, HasAABloat::kNo, IsHairline::kNo);
}

static sk_sp<SkCustomMeshSpecification> make_vertices_spec(bool hasColors, bool hasTex) {
    using Attribute = SkCustomMeshSpecification::Attribute;
    using Varying   = SkCustomMeshSpecification::Varying;
    std::vector<Attribute> attributes;
    attributes.reserve(3);
    attributes.push_back({Attribute::Type::kFloat2, 0, SkString{"pos"}});
    size_t size = 8;

    std::vector<Varying> varyings;
    attributes.reserve(2);

    SkString vs("float2 main(Attributes a, out Varyings v) {\n");
    SkString fs(hasTex ? "float2 " : "void ");

    if (hasColors) {
        attributes.push_back({Attribute::Type::kUByte4_unorm, size, SkString{"color"}});
        varyings.push_back({Varying::Type::kHalf4, SkString{"color"}});
        vs += "v.color = a.color;\n";
        // Using float4 for the output color to work around skbug.com/12761
        fs += "main(Varyings v, out float4 color) {\n"
              "color = float4(v.color.bgr*v.color.a, v.color.a);\n";
        size += 4;
    } else {
        fs += "main(Varyings v) {\n";
    }

    if (hasTex) {
        attributes.push_back({Attribute::Type::kFloat2, size, SkString{"tex"}});
        varyings.push_back({Varying::Type::kFloat2, SkString{"tex"}});
        vs += "v.tex = a.tex;\n";
        fs += "return v.tex;\n";
        size += 8;
    }
    vs += "return a.pos;\n}";
    fs += "}";
    auto [spec, error] = SkCustomMeshSpecification::Make(
            SkMakeSpan(attributes),
            size,
            SkMakeSpan(varyings),
            vs,
            fs);
    SkASSERT(spec);
    return spec;
}

CustomMeshOp::CustomMeshOp(GrProcessorSet*          processorSet,
                           const SkPMColor4f&       color,
                           sk_sp<SkVertices>        vertices,
                           const GrPrimitiveType*   overridePrimitiveType,
                           GrAAType                 aaType,
                           sk_sp<GrColorSpaceXform> colorSpaceXform,
                           const SkMatrixProvider&  matrixProvider)
        : INHERITED(ClassID())
        , fHelper(processorSet, aaType)
        , fColorSpaceXform(std::move(colorSpaceXform))
        , fColor(color)
        , fViewMatrix(matrixProvider.localToDevice()) {
    int attrs = (vertices->priv().hasColors()    ? 0b01 : 0b00) |
                (vertices->priv().hasTexCoords() ? 0b10 : 0b00);
    switch (attrs) {
        case 0b00: {
            static const auto kSpec = make_vertices_spec(false, false);
            fSpecification = kSpec;
            break;
        }
        case 0b01: {
            static const auto kSpec = make_vertices_spec(true, false);
            fSpecification = kSpec;
            break;
        }
        case 0b10: {
            static const auto kSpec = make_vertices_spec(false, true);
            fSpecification = kSpec;
            break;
        }
        case 0b11: {
            static const auto kSpec = make_vertices_spec(true, true);
            fSpecification = kSpec;
            break;
        }
    }
    SkASSERT(fSpecification);

    if (overridePrimitiveType) {
        fPrimitiveType = *overridePrimitiveType;
    } else {
        switch (vertices->priv().mode()) {
            case SkVertices::kTriangles_VertexMode:
                fPrimitiveType = GrPrimitiveType::kTriangles;
                break;
            case SkVertices::kTriangleStrip_VertexMode:
                fPrimitiveType = GrPrimitiveType::kTriangleStrip;
                break;
            case SkVertices::kTriangleFan_VertexMode:
                SkUNREACHABLE;
        }
    }

    IsHairline isHairline = IsHairline::kNo;
    if (GrIsPrimTypeLines(fPrimitiveType) || fPrimitiveType == GrPrimitiveType::kPoints) {
        isHairline = IsHairline::kYes;
    }
    this->setTransformedBounds(vertices->bounds(), fViewMatrix, HasAABloat::kNo, isHairline);

    fMeshes.emplace_back(std::move(vertices), fViewMatrix);

    fVertexCount = fMeshes.back().vertexCount();
    fIndexCount  = fMeshes.back().indexCount();
}

#if GR_TEST_UTILS
SkString CustomMeshOp::onDumpInfo() const { return {}; }
#endif

GrDrawOp::FixedFunctionFlags CustomMeshOp::fixedFunctionFlags() const {
    return fHelper.fixedFunctionFlags();
}

GrProcessorSet::Analysis CustomMeshOp::finalize(const GrCaps& caps,
                                                const GrAppliedClip* clip,
                                                GrClampType clampType) {
    GrProcessorAnalysisColor gpColor;
    gpColor.setToUnknown();
    auto result = fHelper.finalizeProcessors(caps,
                                             clip,
                                             clampType,
                                             GrProcessorAnalysisCoverage::kNone,
                                             &gpColor);
    if (gpColor.isConstant(&fColor)) {
        fIgnoreSpecColor = true;
    }
    return result;
}

GrGeometryProcessor* CustomMeshOp::makeGP(SkArenaAlloc* arena) {
    std::optional<SkPMColor4f> color;
    if (fIgnoreSpecColor || !SkCustomMeshSpecificationPriv::HasColors(*fSpecification)) {
        color.emplace(fColor);
    }
    // Check if we're pre-transforming the vertices on the CPU.
    const SkMatrix& vm = fViewMatrix == SkMatrix::InvalidMatrix() ? SkMatrix::I() : fViewMatrix;
    return CustomMeshGP::Make(arena,
                              fSpecification,
                              fColorSpaceXform,
                              vm,
                              color,
                              fHelper.usesLocalCoords());
}

void CustomMeshOp::onCreateProgramInfo(const GrCaps* caps,
                                       SkArenaAlloc* arena,
                                       const GrSurfaceProxyView& writeView,
                                       bool usesMSAASurface,
                                       GrAppliedClip&& appliedClip,
                                       const GrDstProxyView& dstProxyView,
                                       GrXferBarrierFlags renderPassXferBarriers,
                                       GrLoadOp colorLoadOp) {
    fProgramInfo = fHelper.createProgramInfo(caps,
                                             arena,
                                             writeView,
                                             usesMSAASurface,
                                             std::move(appliedClip),
                                             dstProxyView,
                                             this->makeGP(arena),
                                             fPrimitiveType,
                                             renderPassXferBarriers,
                                             colorLoadOp);
}

void CustomMeshOp::onPrepareDraws(GrMeshDrawTarget* target) {
    size_t vertexStride = fSpecification->stride();
    sk_sp<const GrBuffer> vertexBuffer;
    int firstVertex = 0;
    skgpu::VertexWriter verts = target->makeVertexWriter(vertexStride,
                                                         fVertexCount,
                                                         &vertexBuffer,
                                                         &firstVertex);
    if (!verts) {
        SkDebugf("Could not allocate vertices.\n");
        return;
    }

    bool transform = fViewMatrix == SkMatrix::InvalidMatrix();
    for (const auto& m : fMeshes) {
        m.writeVertices(verts, *fSpecification, transform);
    }

    sk_sp<const GrBuffer> indexBuffer;
    int firstIndex = 0;
    uint16_t* indices = nullptr;
    if (fIndexCount) {
        indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
        if (!indices) {
            SkDebugf("Could not allocate indices.\n");
            return;
        }
        // We can just copy the first mesh's indices. Subsequent meshes need their indices adjusted.
        std::copy_n(fMeshes[0].indices(), fMeshes[0].indexCount(), indices);
        int voffset = fMeshes[0].vertexCount();
        int ioffset = fMeshes[0].indexCount();
        for (size_t m = 1; m < fMeshes.size(); ++m) {
            for (int i = 0; i < fMeshes[m].indexCount(); ++i) {
                indices[ioffset++] = fMeshes[m].indices()[i] + voffset;
            }
            voffset += fMeshes[m].vertexCount();
        }
        SkASSERT(voffset == fVertexCount);
        SkASSERT(ioffset == fIndexCount);
    }

    SkASSERT(!fMesh);
    fMesh = target->allocMesh();

    if (indices) {
        fMesh->setIndexed(std::move(indexBuffer),
                          fIndexCount,
                          firstIndex,
                          /*minIndexValue=*/0,
                          fVertexCount,
                          GrPrimitiveRestart::kNo,
                          std::move(vertexBuffer),
                          firstVertex);
    } else {
        fMesh->set(std::move(vertexBuffer), fVertexCount, firstVertex);
    }
}

void CustomMeshOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
    if (!fProgramInfo) {
        this->createProgramInfo(flushState);
    }

    if (!fProgramInfo || !fMesh) {
        return;
    }

    flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
    flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
    flushState->drawMesh(*fMesh);
}

GrOp::CombineResult CustomMeshOp::onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps) {
    auto that = t->cast<CustomMeshOp>();

    // Check for a combinable primitive type.
    if (!(fPrimitiveType == GrPrimitiveType::kTriangles ||
          fPrimitiveType == GrPrimitiveType::kLines     ||
          fPrimitiveType == GrPrimitiveType::kPoints)) {
        return CombineResult::kCannotCombine;
    }

    if (fPrimitiveType != that->fPrimitiveType) {
        return CombineResult::kCannotCombine;
    }

    if (SkToBool(fIndexCount) != SkToBool(that->fIndexCount)) {
        return CombineResult::kCannotCombine;
    }
    if (SkToBool(fIndexCount) && fVertexCount + that->fVertexCount > SkToInt(UINT16_MAX)) {
        return CombineResult::kCannotCombine;
    }

    if (SkCustomMeshSpecificationPriv::Hash(*this->fSpecification) !=
        SkCustomMeshSpecificationPriv::Hash(*that->fSpecification)) {
        return CombineResult::kCannotCombine;
    }

    if (!SkCustomMeshSpecificationPriv::HasColors(*fSpecification) && fColor != that->fColor) {
        return CombineResult::kCannotCombine;
    }

    if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
        return CombineResult::kCannotCombine;
    }

    if (fViewMatrix != that->fViewMatrix) {
        if (!fMeshes[0].isFromVertices() || !that->fMeshes[0].isFromVertices()) {
            // We don't know how to CPU transform actual custom meshes on CPU.
            return CombineResult::kCannotCombine;
        }
        // If we use local coords and the local coords come from positions then we can't pre-
        // transform the positions on the CPU.
        if (fHelper.usesLocalCoords() &&
            !SkCustomMeshSpecificationPriv::HasLocalCoords(*fSpecification)) {
            return CombineResult::kCannotCombine;
        }
        // We only support two-component position attributes. This means we would not get
        // perspective-correct interpolation of attributes if we transform on the CPU.
        if ((this->fViewMatrix.isFinite() && this->fViewMatrix.hasPerspective()) ||
            (that->fViewMatrix.isFinite() && that->fViewMatrix.hasPerspective())) {
            return CombineResult::kCannotCombine;
        }
        // This is how we record that we must CPU-transform the vertices.
        fViewMatrix = SkMatrix::InvalidMatrix();
    }

    // NOTE: The source color space is part of the spec, and the destination gamut is determined by
    // the render target context. A mis-match should be impossible.
    SkASSERT(GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get()));

    fMeshes.move_back_n(that->fMeshes.count(), that->fMeshes.begin());
    fVertexCount += that->fVertexCount;
    fIndexCount  += that->fIndexCount;
    return CombineResult::kMerged;
}

}  // anonymous namespace

namespace skgpu::v1::DrawCustomMeshOp {

GrOp::Owner Make(GrRecordingContext* context,
                 GrPaint&& paint,
                 SkCustomMesh cm,
                 const SkMatrixProvider& matrixProvider,
                 GrAAType aaType,
                 sk_sp<GrColorSpaceXform> colorSpaceXform) {
    return GrSimpleMeshDrawOpHelper::FactoryHelper<CustomMeshOp>(context,
                                                                 std::move(paint),
                                                                 std::move(cm),
                                                                 aaType,
                                                                 std::move(colorSpaceXform),
                                                                 matrixProvider);
}

GrOp::Owner Make(GrRecordingContext* context,
                 GrPaint&& paint,
                 sk_sp<SkVertices> vertices,
                 const GrPrimitiveType* overridePrimitiveType,
                 const SkMatrixProvider& matrixProvider,
                 GrAAType aaType,
                 sk_sp<GrColorSpaceXform> colorSpaceXform) {
    return GrSimpleMeshDrawOpHelper::FactoryHelper<CustomMeshOp>(context,
                                                                 std::move(paint),
                                                                 std::move(vertices),
                                                                 overridePrimitiveType,
                                                                 aaType,
                                                                 std::move(colorSpaceXform),
                                                                 matrixProvider);
}

}  // namespace skgpu::v1::DrawCustomMeshOp
