/*
 * 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<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.fGP.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
            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
            this->writeOutputPosition(vertBuilder,
                                      uniformHandler,
                                      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("%s = half4(1);", args.fOutputCoverage);
        }

        static inline void GenKey(const GrGeometryProcessor& gp,
                                  const GrShaderCaps&,
                                  GrProcessorKeyBuilder* b) {
            const VerticesGP& vgp = gp.cast<VerticesGP>();
            uint32_t key = 0;
            key |= (vgp.fColorArrayType == ColorArrayType::kSkColor) ? 0x1 : 0;
            key |= ComputeMatrixKey(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 GrPrimitiveProcessor& gp,
                     const CoordTransformRange& transformRange) override {
            const VerticesGP& vgp = gp.cast<VerticesGP>();

            this->setTransform(pdman, fViewMatrixUniform, vgp.viewMatrix(), &fViewMatrix);
            this->setTransformDataHelper(pdman, transformRange);

            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;

        typedef GrGLSLGeometryProcessor INHERITED;
    };

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

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

private:
    friend class ::SkArenaAlloc; // for access to ctor

    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;

    typedef GrGeometryProcessor INHERITED;
};

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

public:
    DEFINE_OP_CLASS_ID

    DrawVerticesOp(const Helper::MakeArgs&, 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);
        }
    }

#ifdef SK_DEBUG
    SkString dumpInfo() const override;
#endif

    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&) override;

    void onPrepareDraws(Target*) override;
    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;

    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, GrRecordingContext::Arenas*, 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;

    typedef GrMeshDrawOp INHERITED;
};

DrawVerticesOp::DrawVerticesOp(const Helper::MakeArgs& helperArgs,
                               const SkPMColor4f& color,
                               sk_sp<SkVertices> vertices,
                               GrPrimitiveType primitiveType,
                               GrAAType aaType,
                               sk_sp<GrColorSpaceXform> colorSpaceXform,
                               const SkMatrixProvider& matrixProvider,
                               const SkRuntimeEffect* effect)
        : INHERITED(ClassID())
        , fHelper(helperArgs, 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);
}

#ifdef SK_DEBUG
SkString DrawVerticesOp::dumpInfo() const {
    SkString string;
    string.appendf("PrimType: %d, MeshCount %d, VCount: %d, ICount: %d\n", (int)fPrimitiveType,
                   fMeshes.count(), fVertexCount, fIndexCount);
    string += fHelper.dumpInfo();
    string += INHERITED::dumpInfo();
    return string;
}
#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) {
    GrGeometryProcessor* gp = this->makeGP(arena);
    fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, std::move(appliedClip),
                                             dstProxyView, gp, this->primitiveType());
}

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, 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->primProc(), nullptr, fProgramInfo->pipeline());
    flushState->drawMesh(*fMesh);
}

GrOp::CombineResult DrawVerticesOp::onCombineIfPossible(GrOp* t, GrRecordingContext::Arenas*,
                                                        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");
}

std::unique_ptr<GrDrawOp> 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
