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

#include "include/core/SkM44.h"
#include "include/effects/SkRuntimeEffect.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkDevice.h"
#include "src/core/SkMatrixPriv.h"
#include "src/core/SkVerticesPriv.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrVertexWriter.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
#include "src/gpu/ops/GrDrawVerticesOp.h"
#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"

namespace {

enum class ColorArrayType {
    kUnused,
    kPremulGrColor,
    kSkColor,
};

enum class LocalCoordsType {
    kUnused,
    kUsePosition,
    kExplicit,
};

static GrVertexAttribType SkVerticesAttributeToGrVertexAttribType(const SkVertices::Attribute& a) {
    switch (a.fType) {
        case SkVertices::Attribute::Type::kFloat:       return kFloat_GrVertexAttribType;
        case SkVertices::Attribute::Type::kFloat2:      return kFloat2_GrVertexAttribType;
        case SkVertices::Attribute::Type::kFloat3:      return kFloat3_GrVertexAttribType;
        case SkVertices::Attribute::Type::kFloat4:      return kFloat4_GrVertexAttribType;
        case SkVertices::Attribute::Type::kByte4_unorm: return kUByte4_norm_GrVertexAttribType;
    }
    SkUNREACHABLE;
}

static GrSLType SkVerticesAttributeToGrSLType(const SkVertices::Attribute& a) {
    switch (a.fType) {
        case SkVertices::Attribute::Type::kFloat:       return kFloat_GrSLType;
        case SkVertices::Attribute::Type::kFloat2:      return kFloat2_GrSLType;
        case SkVertices::Attribute::Type::kFloat3:      return kFloat3_GrSLType;
        case SkVertices::Attribute::Type::kFloat4:      return kFloat4_GrSLType;
        case SkVertices::Attribute::Type::kByte4_unorm: return kHalf4_GrSLType;
    }
    SkUNREACHABLE;
}

static bool AttributeUsesViewMatrix(const SkVertices::Attribute& attr) {
    return (attr.fMarkerID == 0) && (attr.fUsage == SkVertices::Attribute::Usage::kVector ||
                                     attr.fUsage == SkVertices::Attribute::Usage::kNormalVector ||
                                     attr.fUsage == SkVertices::Attribute::Usage::kPosition);
}

// Container for a collection of [uint32_t, Matrix] pairs. For a GrDrawVerticesOp whose custom
// attributes reference some set of IDs, this stores the actual values of those matrices,
// at the time the Op is created.
class MarkedMatrices {
public:
    // For each ID required by 'info', fetch the value of that matrix from 'matrixProvider'.
    // For vectors/normals/positions, we let ID 0 refer to the canvas CTM matrix.
    void gather(const SkVerticesPriv& info, const SkMatrixProvider& matrixProvider) {
        for (int i = 0; i < info.attributeCount(); ++i) {
            uint32_t id = info.attributes()[i].fMarkerID;
            if (id != 0 || AttributeUsesViewMatrix(info.attributes()[i])) {
                if (std::none_of(fMatrices.begin(), fMatrices.end(),
                                 [id](const auto& m) { return m.first == id; })) {
                    SkM44 matrix;
                    // SkCanvas should guarantee that this succeeds.
                    SkAssertResult(matrixProvider.getLocalToMarker(id, &matrix));
                    fMatrices.emplace_back(id, matrix);
                }
            }
        }
    }

    SkM44 get(uint32_t id) const {
        for (const auto& m : fMatrices) {
            if (m.first == id) {
                return m.second;
            }
        }
        SkASSERT(false);
        return SkM44{};
    }

    bool operator==(const MarkedMatrices& that) const { return fMatrices == that.fMatrices; }
    bool operator!=(const MarkedMatrices& that) const { return !(*this == that); }

private:
    // If we expected many MarkerIDs, this should be a hash table. As it is, we're bounded by
    // SkVertices::kMaxCustomAttributes (which is 8). Realistically, we're never going to see
    // more than 1 or 2 unique MarkerIDs, so rely on linear search when inserting and fetching.
    std::vector<std::pair<uint32_t, SkM44>> fMatrices;
};

class VerticesGP : public GrGeometryProcessor {
public:
    static GrGeometryProcessor* Make(SkArenaAlloc* arena,
                                     LocalCoordsType localCoordsType,
                                     ColorArrayType colorArrayType,
                                     const SkPMColor4f& color,
                                     sk_sp<GrColorSpaceXform> colorSpaceXform,
                                     const SkMatrix& viewMatrix,
                                     const SkVertices::Attribute* attrs,
                                     int attrCount,
                                     const MarkedMatrices* customMatrices) {
        return arena->make([&](void* ptr) {
            return new (ptr) VerticesGP(localCoordsType, colorArrayType, color,
                                        std::move(colorSpaceXform), viewMatrix, attrs, attrCount,
                                        customMatrices);
        });
    }

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

    const SkPMColor4f& color() const { return fColor; }
    const SkMatrix& viewMatrix() const { return fViewMatrix; }

    const Attribute& positionAttr() const { return fAttributes[kPositionIndex]; }
    const Attribute& colorAttr() const { return fAttributes[kColorIndex]; }
    const Attribute& localCoordsAttr() const { return fAttributes[kLocalCoordsIndex]; }

    class GLSLProcessor : public GrGLSLGeometryProcessor {
    public:
        GLSLProcessor()
            : fViewMatrix(SkMatrix::InvalidMatrix())
            , fColor(SK_PMColor4fILLEGAL) {}

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

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

            fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
                                       kVertex_GrShaderFlag);

            // Setup pass through color
            fragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
            if (gp.colorAttr().isInitialized()) {
                GrGLSLVarying varying(kHalf4_GrSLType);
                varyingHandler->addVarying("color", &varying);
                vertBuilder->codeAppendf("half4 color = %s;", gp.colorAttr().name());

                // For SkColor, do a red/blue swap, possible color space conversion, and premul
                if (gp.fColorArrayType == ColorArrayType::kSkColor) {
                    vertBuilder->codeAppend("color = color.bgra;");

                    SkString xformedColor;
                    vertBuilder->appendColorGamutXform(&xformedColor, "color", &fColorSpaceHelper);
                    vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());

                    vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
                }

                vertBuilder->codeAppendf("%s = color;\n", varying.vsOut());
                fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
            } else {
                this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
                                        &fColorUniform);
            }

            // Setup position
            WriteOutputPosition(vertBuilder,
                                uniformHandler,
                                *args.fShaderCaps,
                                gpArgs,
                                gp.positionAttr().name(),
                                gp.viewMatrix(),
                                &fViewMatrixUniform);

            // emit transforms using either explicit local coords or positions
            const auto& coordsAttr = gp.localCoordsAttr().isInitialized() ? gp.localCoordsAttr()
                                                                          : gp.positionAttr();
            gpArgs->fLocalCoordVar = coordsAttr.asShaderVar();

            // Add varyings and globals for all custom attributes
            using Usage = SkVertices::Attribute::Usage;
            for (size_t i = kFirstCustomIndex; i < gp.fAttributes.size(); ++i) {
                const auto& attr(gp.fAttributes[i]);
                const int customIdx = i - kFirstCustomIndex;
                const auto& customAttr(gp.fCustomAttributes[customIdx]);

                GrSLType varyingType = attr.gpuType();
                SkString varyingIn(attr.name());

                UniformHandle matrixHandle;
                if (customAttr.fMarkerID || AttributeUsesViewMatrix(customAttr)) {
                    bool normal = customAttr.fUsage == Usage::kNormalVector;
                    for (const MarkedUniform& matrixUni : fCustomMatrixUniforms) {
                        if (matrixUni.fID == customAttr.fMarkerID && matrixUni.fNormal == normal) {
                            matrixHandle = matrixUni.fUniform;
                            break;
                        }
                    }
                    if (!matrixHandle.isValid()) {
                        SkString uniName = SkStringPrintf("customMatrix_%x%s", customAttr.fMarkerID,
                                                          normal ? "_IT" : "");
                        matrixHandle = uniformHandler->addUniform(
                                nullptr, kVertex_GrShaderFlag,
                                normal ? kFloat3x3_GrSLType : kFloat4x4_GrSLType, uniName.c_str());
                        fCustomMatrixUniforms.push_back(
                                {customAttr.fMarkerID, normal, matrixHandle});
                    }
                }

                switch (customAttr.fUsage) {
                    case Usage::kRaw:
                        break;
                    case Usage::kColor: {
                        // For RGB colors, expand to RGBA with A = 1
                        if (attr.gpuType() == kFloat3_GrSLType) {
                            varyingIn = SkStringPrintf("%s.rgb1", attr.name());
                        }
                        // Convert to half (as expected by the color space transform functions)
                        varyingIn = SkStringPrintf("half4(%s)", varyingIn.c_str());
                        // Transform to destination color space (possible no-op)
                        SkString xformedColor;
                        vertBuilder->appendColorGamutXform(&xformedColor, varyingIn.c_str(),
                                                           &fColorSpaceHelper);
                        // Store the result of the transform in a temporary
                        vertBuilder->codeAppendf(
                                "half4 _tmp_clr_%d = %s;", customIdx, xformedColor.c_str());
                        // Finally, premultiply
                        varyingIn = SkStringPrintf(
                                "half4(_tmp_clr_%d.rgb * _tmp_clr_%d.a, _tmp_clr_%d.a)",
                                customIdx, customIdx, customIdx);
                        varyingType = kHalf4_GrSLType;
                        break;
                    }
                    case Usage::kVector: {
                        if (attr.gpuType() == kFloat2_GrSLType) {
                            varyingIn = SkStringPrintf("%s.xy0", attr.name());
                        }
                        if (matrixHandle.isValid()) {
                            varyingIn = SkStringPrintf("(%s * %s.xyz0).xyz",
                                                       uniformHandler->getUniformCStr(matrixHandle),
                                                       varyingIn.c_str());
                        }
                        varyingIn = SkStringPrintf("normalize(%s)", varyingIn.c_str());
                        varyingType = kFloat3_GrSLType;
                        break;
                    }
                    case Usage::kNormalVector: {
                        if (attr.gpuType() == kFloat2_GrSLType) {
                            varyingIn = SkStringPrintf("%s.xy0", attr.name());
                        }
                        if (matrixHandle.isValid()) {
                            varyingIn = SkStringPrintf("(%s * %s)",
                                                       uniformHandler->getUniformCStr(matrixHandle),
                                                       varyingIn.c_str());
                        }
                        varyingIn = SkStringPrintf("normalize(%s)", varyingIn.c_str());
                        varyingType = kFloat3_GrSLType;
                        break;
                    }
                    case Usage::kPosition: {
                        if (attr.gpuType() == kFloat2_GrSLType) {
                            varyingIn = SkStringPrintf("%s.xy0", attr.name());
                        }
                        if (matrixHandle.isValid()) {
                            vertBuilder->codeAppendf("float4 _tmp_pos_%d = %s * %s.xyz1;",
                                                     customIdx,
                                                     uniformHandler->getUniformCStr(matrixHandle),
                                                     varyingIn.c_str());
                            varyingIn = SkStringPrintf("_tmp_pos_%d.xyz / _tmp_pos_%d.w",
                                                       customIdx, customIdx);
                        }
                        varyingType = kFloat3_GrSLType;
                    }
                }

                GrGLSLVarying varying(varyingType);
                varyingHandler->addVarying(attr.name(), &varying);
                vertBuilder->codeAppendf("%s = %s;", varying.vsOut(), varyingIn.c_str());

                GrShaderVar var(SkStringPrintf("_vtx_attr_%d", customIdx), varyingType);
                fragBuilder->declareGlobal(var);
                fragBuilder->codeAppendf("%s = %s;", var.c_str(), varying.fsIn());
            }

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

        static inline void GenKey(const GrGeometryProcessor& gp,
                                  const GrShaderCaps& shaderCaps,
                                  GrProcessorKeyBuilder* b) {
            const VerticesGP& vgp = gp.cast<VerticesGP>();
            uint32_t key = 0;
            key |= (vgp.fColorArrayType == ColorArrayType::kSkColor) ? 0x1 : 0;
            key |= ComputeMatrixKey(shaderCaps, vgp.viewMatrix()) << 20;
            b->add32(key);
            b->add32(GrColorSpaceXform::XformKey(vgp.fColorSpaceXform.get()));

            uint32_t usageBits = 0;
            for (int i = 0; i < vgp.fCustomAttributeCount; ++i) {
                b->add32(vgp.fCustomAttributes[i].fMarkerID);
                usageBits = (usageBits << 8) | (uint32_t)vgp.fCustomAttributes[i].fUsage;
            }
            b->add32(usageBits);
        }

        void setData(const GrGLSLProgramDataManager& pdman,
                     const GrShaderCaps& shaderCaps,
                     const GrGeometryProcessor& geomProc) override {
            const VerticesGP& vgp = geomProc.cast<VerticesGP>();

            SetTransform(pdman, shaderCaps, fViewMatrixUniform, vgp.viewMatrix(), &fViewMatrix);

            if (!vgp.colorAttr().isInitialized() && vgp.color() != fColor) {
                pdman.set4fv(fColorUniform, 1, vgp.color().vec());
                fColor = vgp.color();
            }

            fColorSpaceHelper.setData(pdman, vgp.fColorSpaceXform.get());

            for (const auto& matrixUni : fCustomMatrixUniforms) {
                SkASSERT(matrixUni.fUniform.isValid());
                SkM44 mtx = vgp.fCustomMatrices->get(matrixUni.fID);
                if (matrixUni.fNormal) {
                    // Get the upper-left 3x3 (rotation + scale):
                    mtx.setCol(3, {0, 0, 0, 1});
                    mtx.setRow(3, {0, 0, 0, 1});
                    // Invert it...
                    SkAssertResult(mtx.invert(&mtx));
                    // We want the inverse transpose, but we're going to feed it as a 3x3 column
                    // major matrix to the uniform. So copy the (not-yet-transposed) values out in
                    // row order.
                    float mtxIT[9] = {mtx.rc(0, 0), mtx.rc(0, 1), mtx.rc(0, 2),
                                      mtx.rc(1, 0), mtx.rc(1, 1), mtx.rc(1, 2),
                                      mtx.rc(2, 0), mtx.rc(2, 1), mtx.rc(2, 2)};
                    pdman.setMatrix3f(matrixUni.fUniform, mtxIT);
                } else {
                    pdman.setSkM44(matrixUni.fUniform, mtx);
                }
            }
        }

    private:
        SkMatrix fViewMatrix;
        SkPMColor4f fColor;
        UniformHandle fViewMatrixUniform;
        UniformHandle fColorUniform;
        GrGLSLColorSpaceXformHelper fColorSpaceHelper;

        struct MarkedUniform {
            uint32_t      fID;
            bool          fNormal;
            UniformHandle fUniform;
        };
        std::vector<MarkedUniform> fCustomMatrixUniforms;

        using INHERITED = GrGLSLGeometryProcessor;
    };

    void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
        GLSLProcessor::GenKey(*this, caps, b);
    }

    GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override {
        return new GLSLProcessor();
    }

private:
    VerticesGP(LocalCoordsType localCoordsType,
               ColorArrayType colorArrayType,
               const SkPMColor4f& color,
               sk_sp<GrColorSpaceXform> colorSpaceXform,
               const SkMatrix& viewMatrix,
               const SkVertices::Attribute* attrs,
               int attrCount,
               const MarkedMatrices* customMatrices)
            : INHERITED(kVerticesGP_ClassID)
            , fColorArrayType(colorArrayType)
            , fColor(color)
            , fViewMatrix(viewMatrix)
            , fColorSpaceXform(std::move(colorSpaceXform))
            , fCustomAttributes(attrs)
            , fCustomAttributeCount(attrCount)
            , fCustomMatrices(customMatrices) {
        constexpr Attribute missingAttr;
        fAttributes.push_back({"position", kFloat2_GrVertexAttribType, kFloat2_GrSLType});
        fAttributes.push_back(fColorArrayType != ColorArrayType::kUnused
                                      ? MakeColorAttribute("inColor", false)
                                      : missingAttr);
        fAttributes.push_back(localCoordsType == LocalCoordsType::kExplicit
                        ? Attribute{"inLocalCoord", kFloat2_GrVertexAttribType, kFloat2_GrSLType}
                        : missingAttr);

        for (int i = 0; i < attrCount; ++i) {
            // Attributes store char*, so allocate long-lived storage for the (dynamic) names
            fAttrNames.push_back(SkStringPrintf("_vtx_attr%d", i));
            fAttributes.push_back({fAttrNames.back().c_str(),
                                   SkVerticesAttributeToGrVertexAttribType(attrs[i]),
                                   SkVerticesAttributeToGrSLType(attrs[i])});
        }

        this->setVertexAttributes(fAttributes.data(), fAttributes.size());
    }

    enum {
        kPositionIndex    = 0,
        kColorIndex       = 1,
        kLocalCoordsIndex = 2,
        kFirstCustomIndex = 3,
    };

    std::vector<SkString> fAttrNames;
    std::vector<Attribute> fAttributes;
    ColorArrayType fColorArrayType;
    SkPMColor4f fColor;
    SkMatrix fViewMatrix;
    sk_sp<GrColorSpaceXform> fColorSpaceXform;

    const SkVertices::Attribute* fCustomAttributes;
    int                          fCustomAttributeCount;
    const MarkedMatrices*        fCustomMatrices;

    using INHERITED = GrGeometryProcessor;
};

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

public:
    DEFINE_OP_CLASS_ID

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

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

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

    FixedFunctionFlags fixedFunctionFlags() const override;

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

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

    void onCreateProgramInfo(const GrCaps*,
                             SkArenaAlloc*,
                             const GrSurfaceProxyView& writeView,
                             GrAppliedClip&&,
                             const GrXferProcessor::DstProxyView&,
                             GrXferBarrierFlags renderPassXferBarriers,
                             GrLoadOp colorLoadOp) override;

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

    GrGeometryProcessor* makeGP(SkArenaAlloc*);

    GrPrimitiveType primitiveType() const { return fPrimitiveType; }
    bool combinablePrimitive() const {
        return GrPrimitiveType::kTriangles == fPrimitiveType ||
               GrPrimitiveType::kLines == fPrimitiveType ||
               GrPrimitiveType::kPoints == fPrimitiveType;
    }

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

    struct Mesh {
        SkPMColor4f fColor;  // Used if this->hasPerVertexColors() is false.
        sk_sp<SkVertices> fVertices;
        SkMatrix fViewMatrix;
        bool fIgnoreColors;

        bool hasPerVertexColors() const {
            return fVertices->priv().hasColors() && !fIgnoreColors;
        }
    };

    bool isIndexed() const {
        // Consistency enforced in onCombineIfPossible.
        return fMeshes[0].fVertices->priv().hasIndices();
    }

    bool requiresPerVertexColors() const {
        return fColorArrayType != ColorArrayType::kUnused;
    }

    bool requiresPerVertexLocalCoords() const {
        return fLocalCoordsType == LocalCoordsType::kExplicit;
    }

    size_t vertexStride() const {
        return sizeof(SkPoint) +
               (this->requiresPerVertexColors() ? sizeof(uint32_t) : 0) +
               (this->requiresPerVertexLocalCoords() ? sizeof(SkPoint) : 0) +
               fMeshes[0].fVertices->priv().customDataSize();
    }

    Helper fHelper;
    SkSTArray<1, Mesh, true> fMeshes;
    // GrPrimitiveType is more expressive than fVertices.mode() so it is used instead and we ignore
    // the SkVertices mode (though fPrimitiveType may have been inferred from it).
    GrPrimitiveType fPrimitiveType;
    int fVertexCount;
    int fIndexCount;
    bool fMultipleViewMatrices;
    LocalCoordsType fLocalCoordsType;
    ColorArrayType fColorArrayType;
    sk_sp<GrColorSpaceXform> fColorSpaceXform;
    MarkedMatrices fCustomMatrices;

    GrSimpleMesh*  fMesh = nullptr;
    GrProgramInfo* fProgramInfo = nullptr;

    using INHERITED = GrMeshDrawOp;
};

DrawVerticesOp::DrawVerticesOp(GrProcessorSet* processorSet,
                               const SkPMColor4f& color,
                               sk_sp<SkVertices> vertices,
                               GrPrimitiveType primitiveType,
                               GrAAType aaType,
                               sk_sp<GrColorSpaceXform> colorSpaceXform,
                               const SkMatrixProvider& matrixProvider,
                               const SkRuntimeEffect* effect)
        : INHERITED(ClassID())
        , fHelper(processorSet, aaType)
        , fPrimitiveType(primitiveType)
        , fMultipleViewMatrices(false)
        , fColorSpaceXform(std::move(colorSpaceXform)) {
    SkASSERT(vertices);

    SkVerticesPriv info(vertices->priv());

    fVertexCount = info.vertexCount();
    fIndexCount = info.indexCount();
    fColorArrayType = info.hasColors() ? ColorArrayType::kSkColor
                                       : ColorArrayType::kUnused;
    fLocalCoordsType = info.hasTexCoords() ? LocalCoordsType::kExplicit
                                           : LocalCoordsType::kUsePosition;
    fCustomMatrices.gather(info, matrixProvider);

    Mesh& mesh = fMeshes.push_back();
    mesh.fColor = color;
    mesh.fViewMatrix = matrixProvider.localToDevice();
    mesh.fVertices = std::move(vertices);
    mesh.fIgnoreColors = false;

    IsHairline zeroArea;
    if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) {
        zeroArea = IsHairline::kYes;
    } else {
        zeroArea = IsHairline::kNo;
    }

    this->setTransformedBounds(mesh.fVertices->bounds(),
                                mesh.fViewMatrix,
                                HasAABloat::kNo,
                                zeroArea);
}

#if GR_TEST_UTILS
SkString DrawVerticesOp::onDumpInfo() const {
    return SkStringPrintf("PrimType: %d, MeshCount %d, VCount: %d, ICount: %d\n%s",
                          (int)fPrimitiveType, fMeshes.count(), fVertexCount, fIndexCount,
                          fHelper.dumpInfo().c_str());
}
#endif

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

GrProcessorSet::Analysis DrawVerticesOp::finalize(
        const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
        GrClampType clampType) {
    GrProcessorAnalysisColor gpColor;
    if (this->requiresPerVertexColors()) {
        gpColor.setToUnknown();
    } else {
        gpColor.setToConstant(fMeshes.front().fColor);
    }
    auto result = fHelper.finalizeProcessors(caps, clip, hasMixedSampledCoverage, clampType,
                                             GrProcessorAnalysisCoverage::kNone, &gpColor);
    if (gpColor.isConstant(&fMeshes.front().fColor)) {
        fMeshes.front().fIgnoreColors = true;
        fColorArrayType = ColorArrayType::kUnused;
    }
    if (!fHelper.usesLocalCoords()) {
        fLocalCoordsType = LocalCoordsType::kUnused;
    }
    return result;
}

GrGeometryProcessor* DrawVerticesOp::makeGP(SkArenaAlloc* arena) {
    const SkMatrix& vm = fMultipleViewMatrices ? SkMatrix::I() : fMeshes[0].fViewMatrix;

    SkVerticesPriv info(fMeshes[0].fVertices->priv());

    sk_sp<GrColorSpaceXform> csxform = (fColorArrayType == ColorArrayType::kSkColor ||
                                        info.hasUsage(SkVertices::Attribute::Usage::kColor))
                                               ? fColorSpaceXform
                                               : nullptr;

    auto gp = VerticesGP::Make(arena, fLocalCoordsType, fColorArrayType, fMeshes[0].fColor,
                               std::move(csxform), vm, info.attributes(), info.attributeCount(),
                               &fCustomMatrices);
    SkASSERT(this->vertexStride() == gp->vertexStride());
    return gp;
}

void DrawVerticesOp::onCreateProgramInfo(const GrCaps* caps,
                                         SkArenaAlloc* arena,
                                         const GrSurfaceProxyView& writeView,
                                         GrAppliedClip&& appliedClip,
                                         const GrXferProcessor::DstProxyView& dstProxyView,
                                         GrXferBarrierFlags renderPassXferBarriers,
                                         GrLoadOp colorLoadOp) {
    GrGeometryProcessor* gp = this->makeGP(arena);
    fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
                                             dstProxyView, gp, this->primitiveType(),
                                             renderPassXferBarriers, colorLoadOp);
}

void DrawVerticesOp::onPrepareDraws(Target* target) {
    // Allocate buffers.
    size_t vertexStride = this->vertexStride();
    sk_sp<const GrBuffer> vertexBuffer;
    int firstVertex = 0;
    GrVertexWriter verts{
            target->makeVertexSpace(vertexStride, fVertexCount, &vertexBuffer, &firstVertex)};
    if (!verts.fPtr) {
        SkDebugf("Could not allocate vertices\n");
        return;
    }

    sk_sp<const GrBuffer> indexBuffer;
    int firstIndex = 0;
    uint16_t* indices = nullptr;
    if (this->isIndexed()) {
        indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
        if (!indices) {
            SkDebugf("Could not allocate indices\n");
            return;
        }
    }

    // Copy data into the buffers.
    bool hasColorAttribute = this->requiresPerVertexColors();
    bool hasLocalCoordsAttribute = this->requiresPerVertexLocalCoords();
    int vertexOffset = 0;

    for (const auto& mesh : fMeshes) {
        SkVerticesPriv info(mesh.fVertices->priv());

        // Copy data into the index buffer.
        if (indices) {
            int indexCount = info.indexCount();
            for (int i = 0; i < indexCount; ++i) {
                *indices++ = info.indices()[i] + vertexOffset;
            }
        }

        // Copy data into the vertex buffer.
        int vertexCount = info.vertexCount();
        const SkPoint* positions = info.positions();
        const SkColor* colors = info.colors();
        const SkPoint* localCoords = info.texCoords() ? info.texCoords() : positions;
        const void* custom = info.customData();
        size_t customDataSize = info.customDataSize();

        // TODO4F: Preserve float colors
        GrColor meshColor = mesh.fColor.toBytes_RGBA();

        SkPoint* posBase = (SkPoint*)verts.fPtr;

        for (int i = 0; i < vertexCount; ++i) {
            verts.write(positions[i]);
            if (hasColorAttribute) {
                verts.write(mesh.hasPerVertexColors() ? colors[i] : meshColor);
            }
            if (hasLocalCoordsAttribute) {
                verts.write(localCoords[i]);
            }
            if (customDataSize) {
                verts.writeRaw(custom, customDataSize);
                custom = SkTAddOffset<const void>(custom, customDataSize);
            }
        }

        if (fMultipleViewMatrices) {
            SkASSERT(!mesh.fViewMatrix.hasPerspective());
            SkMatrixPriv::MapPointsWithStride(mesh.fViewMatrix, posBase, vertexStride,
                                              positions, sizeof(SkPoint), vertexCount);
        }

        vertexOffset += vertexCount;
    }

    SkASSERT(!fMesh);
    fMesh = target->allocMesh();
    if (this->isIndexed()) {
        fMesh->setIndexed(std::move(indexBuffer), fIndexCount, firstIndex, 0, fVertexCount - 1,
                         GrPrimitiveRestart::kNo, std::move(vertexBuffer), firstVertex);
    } else {
        fMesh->set(std::move(vertexBuffer), fVertexCount, firstVertex);
    }
}

void DrawVerticesOp::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 DrawVerticesOp::onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps)
{
    DrawVerticesOp* that = t->cast<DrawVerticesOp>();

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

    if (!this->combinablePrimitive() || this->primitiveType() != that->primitiveType()) {
        return CombineResult::kCannotCombine;
    }

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

    if (fVertexCount + that->fVertexCount > SkTo<int>(UINT16_MAX)) {
        return CombineResult::kCannotCombine;
    }

    SkVerticesPriv vThis(this->fMeshes[0].fVertices->priv()),
                   vThat(that->fMeshes[0].fVertices->priv());
    if (vThis.attributeCount() != vThat.attributeCount() ||
        !std::equal(vThis.attributes(), vThis.attributes() + vThis.attributeCount(),
                    vThat.attributes())) {
        return CombineResult::kCannotCombine;
    }

    // We can't batch draws if any of the custom matrices have changed.
    if (this->fCustomMatrices != that->fCustomMatrices) {
        return CombineResult::kCannotCombine;
    }

    // We can't mix draws that use SkColor vertex colors with those that don't. We can mix uniform
    // color draws with GrColor draws (by expanding the uniform color into vertex color).
    if ((fColorArrayType == ColorArrayType::kSkColor) !=
        (that->fColorArrayType == ColorArrayType::kSkColor)) {
        return CombineResult::kCannotCombine;
    }

    // If we're acquiring a mesh with a different view matrix, or an op that needed multiple view
    // matrices, we need multiple view matrices.
    bool needMultipleViewMatrices =
            fMultipleViewMatrices || that->fMultipleViewMatrices ||
            !SkMatrixPriv::CheapEqual(this->fMeshes[0].fViewMatrix, that->fMeshes[0].fViewMatrix);

    // ... but we can't enable multiple view matrices if any of them have perspective, or our other
    // varyings won't be interpolated correctly.
    if (needMultipleViewMatrices && (this->fMeshes[0].fViewMatrix.hasPerspective() ||
                                     that->fMeshes[0].fViewMatrix.hasPerspective())) {
        return CombineResult::kCannotCombine;
    } else {
        fMultipleViewMatrices = needMultipleViewMatrices;
    }

    // If the other op already required per-vertex colors, the combined mesh does.
    if (that->fColorArrayType == ColorArrayType::kPremulGrColor) {
        fColorArrayType = ColorArrayType::kPremulGrColor;
    }

    // If we combine meshes with different (uniform) colors, switch to per-vertex colors.
    if (fColorArrayType == ColorArrayType::kUnused) {
        SkASSERT(that->fColorArrayType == ColorArrayType::kUnused);
        if (this->fMeshes[0].fColor != that->fMeshes[0].fColor) {
            fColorArrayType = ColorArrayType::kPremulGrColor;
        }
    }

    // NOTE: For SkColor vertex colors, the source color space is always sRGB, 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()));

    // If the other op already required explicit local coords the combined mesh does.
    if (that->fLocalCoordsType == LocalCoordsType::kExplicit) {
        fLocalCoordsType = LocalCoordsType::kExplicit;
    }

    // If we were planning to use positions for local coords but now have multiple view matrices,
    // switch to explicit local coords.
    if (fLocalCoordsType == LocalCoordsType::kUsePosition && fMultipleViewMatrices) {
        fLocalCoordsType = LocalCoordsType::kExplicit;
    }

    fMeshes.push_back_n(that->fMeshes.count(), that->fMeshes.begin());
    fVertexCount += that->fVertexCount;
    fIndexCount += that->fIndexCount;

    return CombineResult::kMerged;
}

} // anonymous namespace

static GrPrimitiveType SkVertexModeToGrPrimitiveType(SkVertices::VertexMode mode) {
    switch (mode) {
        case SkVertices::kTriangles_VertexMode:
            return GrPrimitiveType::kTriangles;
        case SkVertices::kTriangleStrip_VertexMode:
            return GrPrimitiveType::kTriangleStrip;
        case SkVertices::kTriangleFan_VertexMode:
            break;
    }
    SK_ABORT("Invalid mode");
}

GrOp::Owner GrDrawVerticesOp::Make(GrRecordingContext* context,
                                   GrPaint&& paint,
                                   sk_sp<SkVertices> vertices,
                                   const SkMatrixProvider& matrixProvider,
                                   GrAAType aaType,
                                   sk_sp<GrColorSpaceXform> colorSpaceXform,
                                   GrPrimitiveType* overridePrimType,
                                   const SkRuntimeEffect* effect) {
    SkASSERT(vertices);
    GrPrimitiveType primType = overridePrimType
                                       ? *overridePrimType
                                       : SkVertexModeToGrPrimitiveType(vertices->priv().mode());
    return GrSimpleMeshDrawOpHelper::FactoryHelper<DrawVerticesOp>(
            context, std::move(paint), std::move(vertices), primType, aaType,
            std::move(colorSpaceXform), matrixProvider, effect);
}

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

#if GR_TEST_UTILS

#include "src/gpu/GrDrawOpTest.h"

static uint32_t seed_vertices(GrPrimitiveType type) {
    switch (type) {
        case GrPrimitiveType::kTriangles:
        case GrPrimitiveType::kTriangleStrip:
            return 3;
        case GrPrimitiveType::kPoints:
            return 1;
        case GrPrimitiveType::kLines:
        case GrPrimitiveType::kLineStrip:
            return 2;
        case GrPrimitiveType::kPatches:
        case GrPrimitiveType::kPath:
            SkASSERT(0);
            return 0;
    }
    SK_ABORT("Incomplete switch\n");
}

static uint32_t primitive_vertices(GrPrimitiveType type) {
    switch (type) {
        case GrPrimitiveType::kTriangles:
            return 3;
        case GrPrimitiveType::kLines:
            return 2;
        case GrPrimitiveType::kTriangleStrip:
        case GrPrimitiveType::kPoints:
        case GrPrimitiveType::kLineStrip:
            return 1;
        case GrPrimitiveType::kPatches:
        case GrPrimitiveType::kPath:
            SkASSERT(0);
            return 0;
    }
    SK_ABORT("Incomplete switch\n");
}

static SkPoint random_point(SkRandom* random, SkScalar min, SkScalar max) {
    SkPoint p;
    p.fX = random->nextRangeScalar(min, max);
    p.fY = random->nextRangeScalar(min, max);
    return p;
}

static void randomize_params(size_t count, size_t maxVertex, SkScalar min, SkScalar max,
                             SkRandom* random, SkTArray<SkPoint>* positions,
                             SkTArray<SkPoint>* texCoords, bool hasTexCoords,
                             SkTArray<uint32_t>* colors, bool hasColors,
                             SkTArray<uint16_t>* indices, bool hasIndices) {
    for (uint32_t v = 0; v < count; v++) {
        positions->push_back(random_point(random, min, max));
        if (hasTexCoords) {
            texCoords->push_back(random_point(random, min, max));
        }
        if (hasColors) {
            colors->push_back(GrRandomColor(random));
        }
        if (hasIndices) {
            SkASSERT(maxVertex <= UINT16_MAX);
            indices->push_back(random->nextULessThan((uint16_t)maxVertex));
        }
    }
}

GR_DRAW_OP_TEST_DEFINE(DrawVerticesOp) {
    GrPrimitiveType types[] = {
        GrPrimitiveType::kTriangles,
        GrPrimitiveType::kTriangleStrip,
        GrPrimitiveType::kPoints,
        GrPrimitiveType::kLines,
        GrPrimitiveType::kLineStrip
    };
    auto type = types[random->nextULessThan(SK_ARRAY_COUNT(types))];

    uint32_t primitiveCount = random->nextRangeU(1, 100);

    // TODO make 'sensible' indexbuffers
    SkTArray<SkPoint> positions;
    SkTArray<SkPoint> texCoords;
    SkTArray<uint32_t> colors;
    SkTArray<uint16_t> indices;

    bool hasTexCoords = random->nextBool();
    bool hasIndices = random->nextBool();
    bool hasColors = random->nextBool();

    uint32_t vertexCount = seed_vertices(type) + (primitiveCount - 1) * primitive_vertices(type);

    static const SkScalar kMinVertExtent = -100.f;
    static const SkScalar kMaxVertExtent = 100.f;
    randomize_params(seed_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent, random,
                     &positions, &texCoords, hasTexCoords, &colors, hasColors, &indices,
                     hasIndices);

    for (uint32_t i = 1; i < primitiveCount; i++) {
        randomize_params(primitive_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent,
                         random, &positions, &texCoords, hasTexCoords, &colors, hasColors, &indices,
                         hasIndices);
    }

    SkSimpleMatrixProvider matrixProvider(GrTest::TestMatrix(random));

    sk_sp<GrColorSpaceXform> colorSpaceXform = GrTest::TestColorXform(random);

    static constexpr SkVertices::VertexMode kIgnoredMode = SkVertices::kTriangles_VertexMode;
    sk_sp<SkVertices> vertices = SkVertices::MakeCopy(kIgnoredMode, vertexCount, positions.begin(),
                                                      texCoords.begin(), colors.begin(),
                                                      hasIndices ? indices.count() : 0,
                                                      indices.begin());
    GrAAType aaType = GrAAType::kNone;
    if (numSamples > 1 && random->nextBool()) {
        aaType = GrAAType::kMSAA;
    }
    return GrDrawVerticesOp::Make(context, std::move(paint), std::move(vertices), matrixProvider,
                                  aaType, std::move(colorSpaceXform), &type, nullptr);
}

#endif
