/*
 * 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 "include/core/SkMesh.h"

#ifdef SK_ENABLE_SKSL
#include "include/core/SkColorSpace.h"
#include "include/core/SkData.h"
#include "include/private/SkOpts_spi.h"
#include "include/private/SkSLProgramElement.h"
#include "include/private/SkSLProgramKind.h"
#include "include/private/base/SkMath.h"
#include "src/base/SkSafeMath.h"
#include "src/core/SkMeshPriv.h"
#include "src/core/SkRuntimeEffectPriv.h"
#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLBuiltinTypes.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLProgramSettings.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/analysis/SkSLProgramVisitor.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
#include "src/sksl/ir/SkSLFunctionDeclaration.h"
#include "src/sksl/ir/SkSLFunctionDefinition.h"
#include "src/sksl/ir/SkSLProgram.h"
#include "src/sksl/ir/SkSLReturnStatement.h"
#include "src/sksl/ir/SkSLStructDefinition.h"
#include "src/sksl/ir/SkSLType.h"
#include "src/sksl/ir/SkSLVarDeclarations.h"
#include "src/sksl/ir/SkSLVariable.h"
#include "src/sksl/ir/SkSLVariableReference.h"

#if defined(SK_GANESH)
#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrStagingBufferManager.h"
#endif  // defined(SK_GANESH)

#include <locale>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>

using Attribute = SkMeshSpecification::Attribute;
using Varying   = SkMeshSpecification::Varying;

using IndexBuffer  = SkMesh::IndexBuffer;
using VertexBuffer = SkMesh::VertexBuffer;

#define RETURN_FAILURE(...) return Result{nullptr, SkStringPrintf(__VA_ARGS__)}

#define RETURN_ERROR(...) return std::make_tuple(false, SkStringPrintf(__VA_ARGS__))

#define RETURN_SUCCESS return std::make_tuple(true, SkString{})

using Uniform = SkMeshSpecification::Uniform;

static std::vector<Uniform>::iterator find_uniform(std::vector<Uniform>& uniforms,
                                                   std::string_view name) {
    return std::find_if(uniforms.begin(), uniforms.end(),
                        [name](const SkMeshSpecification::Uniform& u) { return u.name == name; });
}

static std::tuple<bool, SkString>
gather_uniforms_and_check_for_main(const SkSL::Program& program,
                                   std::vector<Uniform>* uniforms,
                                   SkMeshSpecification::Uniform::Flags stage,
                                   size_t* offset) {
    bool foundMain = false;
    for (const SkSL::ProgramElement* elem : program.elements()) {
        if (elem->is<SkSL::FunctionDefinition>()) {
            const SkSL::FunctionDefinition& defn = elem->as<SkSL::FunctionDefinition>();
            const SkSL::FunctionDeclaration& decl = defn.declaration();
            if (decl.isMain()) {
                foundMain = true;
            }
        } else if (elem->is<SkSL::GlobalVarDeclaration>()) {
            const SkSL::GlobalVarDeclaration& global = elem->as<SkSL::GlobalVarDeclaration>();
            const SkSL::VarDeclaration& varDecl = global.declaration()->as<SkSL::VarDeclaration>();
            const SkSL::Variable& var = *varDecl.var();
            if (var.modifiers().fFlags & SkSL::Modifiers::kUniform_Flag) {
                auto iter = find_uniform(*uniforms, var.name());
                const auto& context = *program.fContext;
                if (iter == uniforms->end()) {
                    uniforms->push_back(SkRuntimeEffectPriv::VarAsUniform(var, context, offset));
                    uniforms->back().flags |= stage;
                } else {
                    // Check that the two declarations are equivalent
                    size_t ignoredOffset = 0;
                    auto uniform = SkRuntimeEffectPriv::VarAsUniform(var, context, &ignoredOffset);
                    if (uniform.isArray() != iter->isArray() ||
                        uniform.type      != iter->type      ||
                        uniform.count     != iter->count) {
                        return {false, SkStringPrintf("Uniform %.*s declared with different types"
                                                      " in vertex and fragment shaders.",
                                                      (int)iter->name.size(), iter->name.data())};
                    }
                    if (uniform.isColor() != iter->isColor()) {
                        return {false, SkStringPrintf("Uniform %.*s declared with different color"
                                                      " layout in vertex and fragment shaders.",
                                                      (int)iter->name.size(), iter->name.data())};
                    }
                    (*iter).flags |= stage;
                }
            }
        }
    }
    if (!foundMain) {
        return {false, SkString("No main function found.")};
    }
    return {true, {}};
}

using ColorType = SkMeshSpecificationPriv::ColorType;

ColorType get_fs_color_type(const SkSL::Program& fsProgram) {
    for (const SkSL::ProgramElement* elem : fsProgram.elements()) {
        if (elem->is<SkSL::FunctionDefinition>()) {
            const SkSL::FunctionDefinition& defn = elem->as<SkSL::FunctionDefinition>();
            const SkSL::FunctionDeclaration& decl = defn.declaration();
            if (decl.isMain()) {
                SkASSERT(decl.parameters().size() == 1 || decl.parameters().size() == 2);
                if (decl.parameters().size() == 1) {
                    return ColorType::kNone;
                }
                const SkSL::Type& paramType = decl.parameters()[1]->type();
                SkASSERT(paramType.matches(*fsProgram.fContext->fTypes.fHalf4) ||
                         paramType.matches(*fsProgram.fContext->fTypes.fFloat4));
                return paramType.matches(*fsProgram.fContext->fTypes.fHalf4) ? ColorType::kHalf4
                                                                             : ColorType::kFloat4;
            }
        }
    }
    SkUNREACHABLE;
}

// This is a non-exhaustive check for the validity of a variable name. The SkSL compiler will
// actually process the name. We're just guarding against having multiple tokens embedded in the
// name before we put it into a struct definition.
static bool check_name(const SkString& name) {
    if (name.isEmpty()) {
        return false;
    }
    for (size_t i = 0; i < name.size(); ++i) {
        if (name[i] != '_' && !std::isalnum(name[i], std::locale::classic())) {
            return false;
        }
    }
    return true;
}

static size_t attribute_type_size(Attribute::Type type) {
    switch (type) {
        case Attribute::Type::kFloat:         return 4;
        case Attribute::Type::kFloat2:        return 2*4;
        case Attribute::Type::kFloat3:        return 3*4;
        case Attribute::Type::kFloat4:        return 4*4;
        case Attribute::Type::kUByte4_unorm:  return 4;
    }
    SkUNREACHABLE;
}

static const char* attribute_type_string(Attribute::Type type) {
    switch (type) {
        case Attribute::Type::kFloat:         return "float";
        case Attribute::Type::kFloat2:        return "float2";
        case Attribute::Type::kFloat3:        return "float3";
        case Attribute::Type::kFloat4:        return "float4";
        case Attribute::Type::kUByte4_unorm:  return "half4";
    }
    SkUNREACHABLE;
}

static const char* varying_type_string(Varying::Type type) {
    switch (type) {
        case Varying::Type::kFloat:  return "float";
        case Varying::Type::kFloat2: return "float2";
        case Varying::Type::kFloat3: return "float3";
        case Varying::Type::kFloat4: return "float4";
        case Varying::Type::kHalf:   return "half";
        case Varying::Type::kHalf2:  return "half2";
        case Varying::Type::kHalf3:  return "half3";
        case Varying::Type::kHalf4:  return "half4";
    }
    SkUNREACHABLE;
}

std::tuple<bool, SkString>
check_vertex_offsets_and_stride(SkSpan<const Attribute> attributes,
                                size_t                  stride) {
    // Vulkan 1.0 has a minimum maximum attribute count of 2048.
    static_assert(SkMeshSpecification::kMaxStride       <= 2048);
    // ES 2 has a max of 8.
    static_assert(SkMeshSpecification::kMaxAttributes   <= 8);
    // Four bytes alignment is required by Metal.
    static_assert(SkMeshSpecification::kStrideAlignment >= 4);
    static_assert(SkMeshSpecification::kOffsetAlignment >= 4);
    // ES2 has a minimum maximum of 8. We may need one for a broken gl_FragCoord workaround and
    // one for local coords.
    static_assert(SkMeshSpecification::kMaxVaryings     <= 6);

    if (attributes.empty()) {
        RETURN_ERROR("At least 1 attribute is required.");
    }
    if (attributes.size() > SkMeshSpecification::kMaxAttributes) {
        RETURN_ERROR("A maximum of %zu attributes is allowed.",
                     SkMeshSpecification::kMaxAttributes);
    }
    static_assert(SkIsPow2(SkMeshSpecification::kStrideAlignment));
    if (stride == 0 || stride & (SkMeshSpecification::kStrideAlignment - 1)) {
        RETURN_ERROR("Vertex stride must be a non-zero multiple of %zu.",
                     SkMeshSpecification::kStrideAlignment);
    }
    if (stride > SkMeshSpecification::kMaxStride) {
        RETURN_ERROR("Stride cannot exceed %zu.", SkMeshSpecification::kMaxStride);
    }
    for (const auto& a : attributes) {
        if (a.offset & (SkMeshSpecification::kOffsetAlignment - 1)) {
            RETURN_ERROR("Attribute offset must be a multiple of %zu.",
                         SkMeshSpecification::kOffsetAlignment);
        }
        // This equivalent to vertexAttributeAccessBeyondStride==VK_FALSE in
        // VK_KHR_portability_subset. First check is to avoid overflow in second check.
        if (a.offset >= stride || a.offset + attribute_type_size(a.type) > stride) {
            RETURN_ERROR("Attribute offset plus size cannot exceed stride.");
        }
    }
    RETURN_SUCCESS;
}

int check_for_passthrough_local_coords_and_dead_varyings(const SkSL::Program& fsProgram,
                                                         uint32_t* deadVaryingMask) {
    SkASSERT(deadVaryingMask);

    using namespace SkSL;
    static constexpr int kFailed = -2;

    class Visitor final : public SkSL::ProgramVisitor {
    public:
        Visitor(const Context& context) : fContext(context) {}

        void visit(const Program& program) { ProgramVisitor::visit(program); }

        int passthroughFieldIndex() const { return fPassthroughFieldIndex; }

        uint32_t fieldUseMask() const { return fFieldUseMask; }

    protected:
        bool visitProgramElement(const ProgramElement& p) override {
            if (p.is<StructDefinition>()) {
                const auto& def = p.as<StructDefinition>();
                if (def.type().name() == "Varyings") {
                    fVaryingsType = &def.type();
                }
                // No reason to keep looking at this type definition.
                return false;
            }
            if (p.is<FunctionDefinition>() && p.as<FunctionDefinition>().declaration().isMain()) {
                SkASSERT(!fVaryings);
                fVaryings = p.as<FunctionDefinition>().declaration().parameters()[0];

                SkASSERT(fVaryingsType && fVaryingsType->matches(fVaryings->type()));

                fInMain = true;
                bool result = ProgramVisitor::visitProgramElement(p);
                fInMain = false;
                return result;
            }
            return ProgramVisitor::visitProgramElement(p);
        }

        bool visitStatement(const Statement& s) override {
            if (!fInMain) {
                return ProgramVisitor::visitStatement(s);
            }
            // We should only get here if are in main and therefore found the varyings parameter.
            SkASSERT(fVaryings);
            SkASSERT(fVaryingsType);

            if (fPassthroughFieldIndex == kFailed) {
                // We've already determined there are return statements that aren't passthrough
                // or return different fields.
                return ProgramVisitor::visitStatement(s);
            }
            if (!s.is<ReturnStatement>()) {
                return ProgramVisitor::visitStatement(s);
            }

            // We just detect simple cases like "return varyings.foo;"
            const auto& rs = s.as<ReturnStatement>();
            SkASSERT(rs.expression());
            if (!rs.expression()->is<FieldAccess>()) {
                this->passthroughFailed();
                return ProgramVisitor::visitStatement(s);
            }
            const auto& fa = rs.expression()->as<FieldAccess>();
            if (!fa.base()->is<VariableReference>()) {
                this->passthroughFailed();
                return ProgramVisitor::visitStatement(s);
            }
            const auto& baseRef = fa.base()->as<VariableReference>();
            if (baseRef.variable() != fVaryings) {
                this->passthroughFailed();
                return ProgramVisitor::visitStatement(s);
            }
            if (fPassthroughFieldIndex >= 0) {
                // We already found an OK return statement. Check if this one returns the same
                // field.
                if (fa.fieldIndex() != fPassthroughFieldIndex) {
                    this->passthroughFailed();
                    return ProgramVisitor::visitStatement(s);
                }
                // We don't call our base class here because we don't want to hit visitExpression
                // and mark the returned field as used.
                return false;
            }
            const Type::Field& field = fVaryings->type().fields()[fa.fieldIndex()];
            if (!field.fType->matches(*fContext.fTypes.fFloat2)) {
                this->passthroughFailed();
                return ProgramVisitor::visitStatement(s);
            }
            fPassthroughFieldIndex = fa.fieldIndex();
            // We don't call our base class here because we don't want to hit visitExpression and
            // mark the returned field as used.
            return false;
        }

        bool visitExpression(const Expression& e) override {
            // Anything before the Varyings struct is defined doesn't matter.
            if (!fVaryingsType) {
                return false;
            }
            if (!e.is<FieldAccess>()) {
                return ProgramVisitor::visitExpression(e);
            }
            const auto& fa = e.as<FieldAccess>();
            if (!fa.base()->type().matches(*fVaryingsType)) {
                return ProgramVisitor::visitExpression(e);
            }
            fFieldUseMask |= 1 << fa.fieldIndex();
            return false;
        }

    private:
        void passthroughFailed() {
            if (fPassthroughFieldIndex >= 0) {
                fFieldUseMask |= 1 << fPassthroughFieldIndex;
            }
            fPassthroughFieldIndex = kFailed;
        }

        const Context&  fContext;
        const Type*     fVaryingsType          = nullptr;
        const Variable* fVaryings              = nullptr;
        int             fPassthroughFieldIndex = -1;
        bool            fInMain                = false;
        uint32_t        fFieldUseMask          = 0;
    };

    Visitor v(*fsProgram.fContext);
    v.visit(fsProgram);
    *deadVaryingMask = ~v.fieldUseMask();
    return v.passthroughFieldIndex();
}

SkMeshSpecification::Result SkMeshSpecification::Make(SkSpan<const Attribute> attributes,
                                                      size_t vertexStride,
                                                      SkSpan<const Varying> varyings,
                                                      const SkString& vs,
                                                      const SkString& fs) {
    return Make(attributes,
                vertexStride,
                varyings,
                vs,
                fs,
                SkColorSpace::MakeSRGB(),
                kPremul_SkAlphaType);
}

SkMeshSpecification::Result SkMeshSpecification::Make(SkSpan<const Attribute> attributes,
                                                      size_t vertexStride,
                                                      SkSpan<const Varying> varyings,
                                                      const SkString& vs,
                                                      const SkString& fs,
                                                      sk_sp<SkColorSpace> cs) {
    return Make(attributes, vertexStride, varyings, vs, fs, std::move(cs), kPremul_SkAlphaType);
}

SkMeshSpecification::Result SkMeshSpecification::Make(SkSpan<const Attribute> attributes,
                                                      size_t vertexStride,
                                                      SkSpan<const Varying> varyings,
                                                      const SkString& vs,
                                                      const SkString& fs,
                                                      sk_sp<SkColorSpace> cs,
                                                      SkAlphaType at) {
    SkString attributesStruct("struct Attributes {\n");
    for (const auto& a : attributes) {
        attributesStruct.appendf("  %s %s;\n", attribute_type_string(a.type), a.name.c_str());
    }
    attributesStruct.append("};\n");

    bool userProvidedPositionVarying = false;
    for (const auto& v : varyings) {
        if (v.name.equals("position")) {
            if (v.type != Varying::Type::kFloat2) {
                return {nullptr, SkString("Varying \"position\" must have type float2.")};
            }
            userProvidedPositionVarying = true;
        }
    }

    SkSTArray<kMaxVaryings, Varying> tempVaryings;
    if (!userProvidedPositionVarying) {
        // Even though we check the # of varyings in MakeFromSourceWithStructs we check here, too,
        // to avoid overflow with + 1.
        if (varyings.size() > kMaxVaryings - 1) {
            RETURN_FAILURE("A maximum of %zu varyings is allowed.", kMaxVaryings);
        }
        for (const auto& v : varyings) {
            tempVaryings.push_back(v);
        }
        tempVaryings.push_back(Varying{Varying::Type::kFloat2, SkString("position")});
        varyings = tempVaryings;
    }

    SkString varyingStruct("struct Varyings {\n");
    for (const auto& v : varyings) {
        varyingStruct.appendf("  %s %s;\n", varying_type_string(v.type), v.name.c_str());
    }
    varyingStruct.append("};\n");

    SkString fullVS;
    fullVS.append(varyingStruct.c_str());
    fullVS.append(attributesStruct.c_str());
    fullVS.append(vs.c_str());

    SkString fullFS;
    fullFS.append(varyingStruct.c_str());
    fullFS.append(fs.c_str());

    return MakeFromSourceWithStructs(attributes,
                                     vertexStride,
                                     varyings,
                                     fullVS,
                                     fullFS,
                                     std::move(cs),
                                     at);
}

SkMeshSpecification::Result SkMeshSpecification::MakeFromSourceWithStructs(
        SkSpan<const Attribute> attributes,
        size_t                  stride,
        SkSpan<const Varying>   varyings,
        const SkString&         vs,
        const SkString&         fs,
        sk_sp<SkColorSpace>     cs,
        SkAlphaType             at) {
    if (auto [ok, error] = check_vertex_offsets_and_stride(attributes, stride); !ok) {
        return {nullptr, error};
    }

    for (const auto& a : attributes) {
        if (!check_name(a.name)) {
            RETURN_FAILURE("\"%s\" is not a valid attribute name.", a.name.c_str());
        }
    }

    if (varyings.size() > kMaxVaryings) {
        RETURN_FAILURE("A maximum of %zu varyings is allowed.", kMaxVaryings);
    }

    for (const auto& v : varyings) {
        if (!check_name(v.name)) {
            return {nullptr, SkStringPrintf("\"%s\" is not a valid varying name.", v.name.c_str())};
        }
    }

    std::vector<Uniform> uniforms;
    size_t offset = 0;

    SkSL::Compiler compiler(SkSL::ShaderCapsFactory::Standalone());

    // Disable memory pooling; this might slow down compilation slightly, but it will ensure that a
    // long-lived mesh specification doesn't waste memory.
    SkSL::ProgramSettings settings;
    settings.fUseMemoryPool = false;

    // TODO(skia:11209): Add SkCapabilities to the API, check against required version.
    std::unique_ptr<SkSL::Program> vsProgram = compiler.convertProgram(
            SkSL::ProgramKind::kMeshVertex,
            std::string(vs.c_str()),
            settings);
    if (!vsProgram) {
        RETURN_FAILURE("VS: %s", compiler.errorText().c_str());
    }

    if (auto [result, error] = gather_uniforms_and_check_for_main(
                *vsProgram,
                &uniforms,
                SkMeshSpecification::Uniform::Flags::kVertex_Flag,
                &offset);
        !result) {
        return {nullptr, std::move(error)};
    }

    if (SkSL::Analysis::CallsColorTransformIntrinsics(*vsProgram)) {
        RETURN_FAILURE("Color transform intrinsics are not permitted in custom mesh shaders");
    }

    std::unique_ptr<SkSL::Program> fsProgram = compiler.convertProgram(
            SkSL::ProgramKind::kMeshFragment,
            std::string(fs.c_str()),
            settings);

    if (!fsProgram) {
        RETURN_FAILURE("FS: %s", compiler.errorText().c_str());
    }

    if (auto [result, error] = gather_uniforms_and_check_for_main(
                *fsProgram,
                &uniforms,
                SkMeshSpecification::Uniform::Flags::kFragment_Flag,
                &offset);
        !result) {
        return {nullptr, std::move(error)};
    }

    if (SkSL::Analysis::CallsColorTransformIntrinsics(*fsProgram)) {
        RETURN_FAILURE("Color transform intrinsics are not permitted in custom mesh shaders");
    }

    ColorType ct = get_fs_color_type(*fsProgram);

    if (ct == ColorType::kNone) {
        cs = nullptr;
        at = kPremul_SkAlphaType;
    } else {
        if (!cs) {
            return {nullptr, SkString{"Must provide a color space if FS returns a color."}};
        }
        if (at == kUnknown_SkAlphaType) {
            return {nullptr, SkString{"Must provide a valid alpha type if FS returns a color."}};
        }
    }

    uint32_t deadVaryingMask;
    int passthroughLocalCoordsVaryingIndex =
            check_for_passthrough_local_coords_and_dead_varyings(*fsProgram, &deadVaryingMask);

    if (passthroughLocalCoordsVaryingIndex >= 0) {
        SkASSERT(varyings[passthroughLocalCoordsVaryingIndex].type == Varying::Type::kFloat2);
    }

    return {sk_sp<SkMeshSpecification>(new SkMeshSpecification(attributes,
                                                               stride,
                                                               varyings,
                                                               passthroughLocalCoordsVaryingIndex,
                                                               deadVaryingMask,
                                                               std::move(uniforms),
                                                               std::move(vsProgram),
                                                               std::move(fsProgram),
                                                               ct,
                                                               std::move(cs),
                                                               at)),
            /*error=*/{}};
}

SkMeshSpecification::~SkMeshSpecification() = default;

SkMeshSpecification::SkMeshSpecification(
        SkSpan<const Attribute>              attributes,
        size_t                               stride,
        SkSpan<const Varying>                varyings,
        int                                  passthroughLocalCoordsVaryingIndex,
        uint32_t                             deadVaryingMask,
        std::vector<Uniform>                 uniforms,
        std::unique_ptr<const SkSL::Program> vs,
        std::unique_ptr<const SkSL::Program> fs,
        ColorType                            ct,
        sk_sp<SkColorSpace>                  cs,
        SkAlphaType                          at)
        : fAttributes(attributes.begin(), attributes.end())
        , fVaryings(varyings.begin(), varyings.end())
        , fUniforms(std::move(uniforms))
        , fVS(std::move(vs))
        , fFS(std::move(fs))
        , fStride(stride)
        , fPassthroughLocalCoordsVaryingIndex(passthroughLocalCoordsVaryingIndex)
        , fDeadVaryingMask(deadVaryingMask)
        , fColorType(ct)
        , fColorSpace(std::move(cs))
        , fAlphaType(at) {
    fHash = SkOpts::hash_fn(fVS->fSource->c_str(), fVS->fSource->size(), 0);
    fHash = SkOpts::hash_fn(fFS->fSource->c_str(), fFS->fSource->size(), fHash);

    // The attributes and varyings SkSL struct declarations are included in the program source.
    // However, the attribute offsets and types need to be included, the latter because the SkSL
    // struct definition has the GPU type but not the CPU data format.
    for (const auto& a : fAttributes) {
        fHash = SkOpts::hash_fn(&a.offset, sizeof(a.offset), fHash);
        fHash = SkOpts::hash_fn(&a.type,   sizeof(a.type),   fHash);
    }

    fHash = SkOpts::hash_fn(&stride, sizeof(stride), fHash);

    uint64_t csHash = fColorSpace ? fColorSpace->hash() : 0;
    fHash = SkOpts::hash_fn(&csHash, sizeof(csHash), fHash);

    auto atInt = static_cast<uint32_t>(fAlphaType);
    fHash = SkOpts::hash_fn(&atInt, sizeof(atInt), fHash);
}

size_t SkMeshSpecification::uniformSize() const {
    return fUniforms.empty() ? 0
                             : SkAlign4(fUniforms.back().offset + fUniforms.back().sizeInBytes());
}

const Uniform* SkMeshSpecification::findUniform(std::string_view name) const {
    auto iter = std::find_if(fUniforms.begin(), fUniforms.end(), [name] (const Uniform& u) {
        return u.name == name;
    });
    return iter == fUniforms.end() ? nullptr : &(*iter);
}

const Attribute* SkMeshSpecification::findAttribute(std::string_view name) const {
    auto iter = std::find_if(fAttributes.begin(), fAttributes.end(), [name](const Attribute& a) {
        return name.compare(a.name.c_str()) == 0;
    });
    return iter == fAttributes.end() ? nullptr : &(*iter);
}

const Varying* SkMeshSpecification::findVarying(std::string_view name) const {
    auto iter = std::find_if(fVaryings.begin(), fVaryings.end(), [name](const Varying& v) {
        return name.compare(v.name.c_str()) == 0;
    });
    return iter == fVaryings.end() ? nullptr : &(*iter);
}

//////////////////////////////////////////////////////////////////////////////

SkMesh::SkMesh()  = default;
SkMesh::~SkMesh() = default;

SkMesh::SkMesh(const SkMesh&) = default;
SkMesh::SkMesh(SkMesh&&)      = default;

SkMesh& SkMesh::operator=(const SkMesh&) = default;
SkMesh& SkMesh::operator=(SkMesh&&)      = default;

sk_sp<IndexBuffer> SkMesh::MakeIndexBuffer(GrDirectContext* dc, const void* data, size_t size) {
    if (!dc) {
        return SkMeshPriv::CpuIndexBuffer::Make(data, size);
    }
#if defined(SK_GANESH)
    return SkMeshPriv::GpuIndexBuffer::Make(dc, data, size);
#else
    return nullptr;
#endif
}

sk_sp<IndexBuffer> SkMesh::CopyIndexBuffer(GrDirectContext* dc, sk_sp<IndexBuffer> src) {
    if (!src) {
        return nullptr;
    }
    auto* ib = static_cast<SkMeshPriv::IB*>(src.get());
    const void* data = ib->peek();
    if (!data) {
        return nullptr;
    }
    return MakeIndexBuffer(dc, data, ib->size());
}

sk_sp<VertexBuffer> SkMesh::MakeVertexBuffer(GrDirectContext* dc, const void* data, size_t size) {
    if (!dc) {
        return SkMeshPriv::CpuVertexBuffer::Make(data, size);
    }
#if defined(SK_GANESH)
    return SkMeshPriv::GpuVertexBuffer::Make(dc, data, size);
#else
    return nullptr;
#endif
}

sk_sp<VertexBuffer> SkMesh::CopyVertexBuffer(GrDirectContext* dc, sk_sp<VertexBuffer> src) {
    if (!src) {
        return nullptr;
    }
    auto* vb = static_cast<SkMeshPriv::VB*>(src.get());
    const void* data = vb->peek();
    if (!data) {
        return nullptr;
    }
    return MakeVertexBuffer(dc, data, vb->size());
}

SkMesh::Result SkMesh::Make(sk_sp<SkMeshSpecification> spec,
                            Mode mode,
                            sk_sp<VertexBuffer> vb,
                            size_t vertexCount,
                            size_t vertexOffset,
                            sk_sp<const SkData> uniforms,
                            const SkRect& bounds) {
    SkMesh mesh;
    mesh.fSpec     = std::move(spec);
    mesh.fMode     = mode;
    mesh.fVB       = std::move(vb);
    mesh.fUniforms = std::move(uniforms);
    mesh.fVCount   = vertexCount;
    mesh.fVOffset  = vertexOffset;
    mesh.fBounds   = bounds;
    auto [valid, msg] = mesh.validate();
    if (!valid) {
        mesh = {};
    }
    return {std::move(mesh), std::move(msg)};
}

SkMesh::Result SkMesh::MakeIndexed(sk_sp<SkMeshSpecification> spec,
                                   Mode mode,
                                   sk_sp<VertexBuffer> vb,
                                   size_t vertexCount,
                                   size_t vertexOffset,
                                   sk_sp<IndexBuffer> ib,
                                   size_t indexCount,
                                   size_t indexOffset,
                                   sk_sp<const SkData> uniforms,
                                   const SkRect& bounds) {
    if (!ib) {
        // We check this before calling validate to disambiguate from a non-indexed mesh where
        // IB is expected to be null.
        return {{}, SkString{"An index buffer is required."}};
    }
    SkMesh mesh;
    mesh.fSpec     = std::move(spec);
    mesh.fMode     = mode;
    mesh.fVB       = std::move(vb);
    mesh.fVCount   = vertexCount;
    mesh.fVOffset  = vertexOffset;
    mesh.fIB       = std::move(ib);
    mesh.fUniforms = std::move(uniforms);
    mesh.fICount   = indexCount;
    mesh.fIOffset  = indexOffset;
    mesh.fBounds   = bounds;
    auto [valid, msg] = mesh.validate();
    if (!valid) {
        mesh = {};
    }
    return {std::move(mesh), std::move(msg)};
}

bool SkMesh::isValid() const {
    bool valid = SkToBool(fSpec);
    SkASSERT(valid == std::get<0>(this->validate()));
    return valid;
}

static size_t min_vcount_for_mode(SkMesh::Mode mode) {
    switch (mode) {
        case SkMesh::Mode::kTriangles:     return 3;
        case SkMesh::Mode::kTriangleStrip: return 3;
    }
    SkUNREACHABLE;
}

std::tuple<bool, SkString> SkMesh::validate() const {
#define FAIL_MESH_VALIDATE(...)  return std::make_tuple(false, SkStringPrintf(__VA_ARGS__))
    if (!fSpec) {
        FAIL_MESH_VALIDATE("SkMeshSpecification is required.");
    }

    if (!fVB) {
        FAIL_MESH_VALIDATE("A vertex buffer is required.");
    }

    auto vb = static_cast<SkMeshPriv::VB*>(fVB.get());
    auto ib = static_cast<SkMeshPriv::IB*>(fIB.get());

    SkSafeMath sm;
    size_t vsize = sm.mul(fSpec->stride(), fVCount);
    if (sm.add(vsize, fVOffset) > vb->size()) {
        FAIL_MESH_VALIDATE("The vertex buffer offset and vertex count reads beyond the end of the"
                           " vertex buffer.");
    }

    if (fVOffset%fSpec->stride() != 0) {
        FAIL_MESH_VALIDATE("The vertex offset (%zu) must be a multiple of the vertex stride (%zu).",
                           fVOffset,
                           fSpec->stride());
    }

    if (size_t uniformSize = fSpec->uniformSize()) {
        if (!fUniforms || fUniforms->size() < uniformSize) {
            FAIL_MESH_VALIDATE("The uniform data is %zu bytes but must be at least %zu.",
                               fUniforms->size(),
                               uniformSize);
        }
    }

    auto modeToStr = [](Mode m) {
        switch (m) {
            case Mode::kTriangles:     return "triangles";
            case Mode::kTriangleStrip: return "triangle-strip";
        }
        SkUNREACHABLE;
    };
    if (ib) {
        if (fICount < min_vcount_for_mode(fMode)) {
            FAIL_MESH_VALIDATE("%s mode requires at least %zu indices but index count is %zu.",
                               modeToStr(fMode),
                               min_vcount_for_mode(fMode),
                               fICount);
        }
        size_t isize = sm.mul(sizeof(uint16_t), fICount);
        if (sm.add(isize, fIOffset) > ib->size()) {
            FAIL_MESH_VALIDATE("The index buffer offset and index count reads beyond the end of the"
                               " index buffer.");

        }
        // If we allow 32 bit indices then this should enforce 4 byte alignment in that case.
        if (!SkIsAlign2(fIOffset)) {
            FAIL_MESH_VALIDATE("The index offset must be a multiple of 2.");
        }
    } else {
        if (fVCount < min_vcount_for_mode(fMode)) {
            FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.",
                               modeToStr(fMode),
                               min_vcount_for_mode(fMode),
                               fICount);
        }
        SkASSERT(!fICount);
        SkASSERT(!fIOffset);
    }

    if (!sm.ok()) {
        FAIL_MESH_VALIDATE("Overflow");
    }
#undef FAIL_MESH_VALIDATE
    return {true, {}};
}

//////////////////////////////////////////////////////////////////////////////

static inline bool check_update(const void* data, size_t offset, size_t size, size_t bufferSize) {
    SkSafeMath sm;
    return data                                &&
           size                                &&
           SkIsAlign4(offset)                  &&
           SkIsAlign4(size)                    &&
           sm.add(offset, size) <= bufferSize  &&
           sm.ok();
}

bool SkMesh::IndexBuffer::update(GrDirectContext* dc,
                                 const void* data,
                                 size_t offset,
                                 size_t size) {
    return check_update(data, offset, size, this->size()) && this->onUpdate(dc, data, offset, size);
}

bool SkMesh::VertexBuffer::update(GrDirectContext* dc,
                                  const void* data,
                                  size_t offset,
                                  size_t size) {
    return check_update(data, offset, size, this->size()) && this->onUpdate(dc, data, offset, size);
}

#if defined(SK_GANESH)
bool SkMeshPriv::UpdateGpuBuffer(GrDirectContext* dc,
                                 sk_sp<GrGpuBuffer> buffer,
                                 const void* data,
                                 size_t offset,
                                 size_t size) {
    if (!dc || dc != buffer->getContext()) {
        return false;
    }
    SkASSERT(!dc->abandoned()); // If dc is abandoned then buffer->getContext() should be null.

    if (!dc->priv().caps()->transferFromBufferToBufferSupport()) {
        auto ownedData = SkData::MakeWithCopy(data, size);
        dc->priv().drawingManager()->newBufferUpdateTask(std::move(ownedData),
                                                         std::move(buffer),
                                                         offset);
        return true;
    }

    sk_sp<GrGpuBuffer> tempBuffer;
    size_t tempOffset = 0;
    if (auto* sbm = dc->priv().getGpu()->stagingBufferManager()) {
        auto alignment = dc->priv().caps()->transferFromBufferToBufferAlignment();
        auto [sliceBuffer, sliceOffset, ptr] = sbm->allocateStagingBufferSlice(size, alignment);
        if (sliceBuffer) {
            std::memcpy(ptr, data, size);
            tempBuffer.reset(SkRef(sliceBuffer));
            tempOffset = sliceOffset;
        }
    }

    if (!tempBuffer) {
        tempBuffer = dc->priv().resourceProvider()->createBuffer(size,
                                                                 GrGpuBufferType::kXferCpuToGpu,
                                                                 kDynamic_GrAccessPattern,
                                                                 GrResourceProvider::ZeroInit::kNo);
        if (!tempBuffer) {
            return false;
        }
        if (!tempBuffer->updateData(data, 0, size, /*preserve=*/false)) {
            return false;
        }
    }

    dc->priv().drawingManager()->newBufferTransferTask(std::move(tempBuffer),
                                                       tempOffset,
                                                       std::move(buffer),
                                                       offset,
                                                       size);

    return true;
}
#endif  // defined(SK_GANESH)

#endif  // SK_ENABLE_SKSL
