1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/ops/DrawVerticesOp.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkM44.h"
11cb93a386Sopenharmony_ci#include "src/core/SkArenaAlloc.h"
12cb93a386Sopenharmony_ci#include "src/core/SkDevice.h"
13cb93a386Sopenharmony_ci#include "src/core/SkMatrixPriv.h"
14cb93a386Sopenharmony_ci#include "src/core/SkVerticesPriv.h"
15cb93a386Sopenharmony_ci#include "src/gpu/BufferWriter.h"
16cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h"
17cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h"
18cb93a386Sopenharmony_ci#include "src/gpu/GrProgramInfo.h"
19cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h"
20cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLColorSpaceXformHelper.h"
21cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
22cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVarying.h"
23cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
24cb93a386Sopenharmony_ci#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_cinamespace skgpu::v1::DrawVerticesOp {
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_cinamespace {
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_cienum class ColorArrayType {
31cb93a386Sopenharmony_ci    kUnused,
32cb93a386Sopenharmony_ci    kPremulGrColor,
33cb93a386Sopenharmony_ci    kSkColor,
34cb93a386Sopenharmony_ci};
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_cienum class LocalCoordsType {
37cb93a386Sopenharmony_ci    kUnused,
38cb93a386Sopenharmony_ci    kUsePosition,
39cb93a386Sopenharmony_ci    kExplicit,
40cb93a386Sopenharmony_ci};
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ciclass VerticesGP : public GrGeometryProcessor {
43cb93a386Sopenharmony_cipublic:
44cb93a386Sopenharmony_ci    static GrGeometryProcessor* Make(SkArenaAlloc* arena,
45cb93a386Sopenharmony_ci                                     LocalCoordsType localCoordsType,
46cb93a386Sopenharmony_ci                                     ColorArrayType colorArrayType,
47cb93a386Sopenharmony_ci                                     const SkPMColor4f& color,
48cb93a386Sopenharmony_ci                                     sk_sp<GrColorSpaceXform> colorSpaceXform,
49cb93a386Sopenharmony_ci                                     const SkMatrix& viewMatrix) {
50cb93a386Sopenharmony_ci        return arena->make([&](void* ptr) {
51cb93a386Sopenharmony_ci            return new (ptr) VerticesGP(localCoordsType, colorArrayType, color,
52cb93a386Sopenharmony_ci                                        std::move(colorSpaceXform), viewMatrix);
53cb93a386Sopenharmony_ci        });
54cb93a386Sopenharmony_ci    }
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci    const char* name() const override { return "VerticesGP"; }
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_ci    SkString getShaderDfxInfo() const override {
59cb93a386Sopenharmony_ci        SkString format;
60cb93a386Sopenharmony_ci        format.printf("ShaderDfx_VerticesGP_%d_%d_%d_%d_%d",
61cb93a386Sopenharmony_ci            fColorArrayType, GrColorSpaceXform::XformKey(fColorSpaceXform.get()),
62cb93a386Sopenharmony_ci            fViewMatrix.isIdentity(), fViewMatrix.isScaleTranslate(), fViewMatrix.hasPerspective());
63cb93a386Sopenharmony_ci        return format;
64cb93a386Sopenharmony_ci    }
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci    const Attribute& positionAttr() const { return fAttributes[kPositionIndex]; }
67cb93a386Sopenharmony_ci    const Attribute& colorAttr() const { return fAttributes[kColorIndex]; }
68cb93a386Sopenharmony_ci    const Attribute& localCoordsAttr() const { return fAttributes[kLocalCoordsIndex]; }
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    void addToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
71cb93a386Sopenharmony_ci        uint32_t key = 0;
72cb93a386Sopenharmony_ci        key |= (fColorArrayType == ColorArrayType::kSkColor) ? 0x1 : 0;
73cb93a386Sopenharmony_ci        key |= ProgramImpl::ComputeMatrixKey(caps, fViewMatrix) << 20;
74cb93a386Sopenharmony_ci        b->add32(key);
75cb93a386Sopenharmony_ci        b->add32(GrColorSpaceXform::XformKey(fColorSpaceXform.get()));
76cb93a386Sopenharmony_ci    }
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ci    std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override {
79cb93a386Sopenharmony_ci        return std::make_unique<Impl>();
80cb93a386Sopenharmony_ci    }
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_ciprivate:
83cb93a386Sopenharmony_ci    class Impl : public ProgramImpl {
84cb93a386Sopenharmony_ci    public:
85cb93a386Sopenharmony_ci        void setData(const GrGLSLProgramDataManager& pdman,
86cb93a386Sopenharmony_ci                     const GrShaderCaps& shaderCaps,
87cb93a386Sopenharmony_ci                     const GrGeometryProcessor& geomProc) override {
88cb93a386Sopenharmony_ci            const VerticesGP& vgp = geomProc.cast<VerticesGP>();
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci            SetTransform(pdman, shaderCaps, fViewMatrixUniform, vgp.fViewMatrix, &fViewMatrix);
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ci            if (!vgp.colorAttr().isInitialized() && vgp.fColor != fColor) {
93cb93a386Sopenharmony_ci                pdman.set4fv(fColorUniform, 1, vgp.fColor.vec());
94cb93a386Sopenharmony_ci                fColor = vgp.fColor;
95cb93a386Sopenharmony_ci            }
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci            fColorSpaceHelper.setData(pdman, vgp.fColorSpaceXform.get());
98cb93a386Sopenharmony_ci        }
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci    private:
101cb93a386Sopenharmony_ci        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
102cb93a386Sopenharmony_ci            const VerticesGP& gp = args.fGeomProc.cast<VerticesGP>();
103cb93a386Sopenharmony_ci            GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
104cb93a386Sopenharmony_ci            GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
105cb93a386Sopenharmony_ci            GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
106cb93a386Sopenharmony_ci            GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ci            // emit attributes
109cb93a386Sopenharmony_ci            varyingHandler->emitAttributes(gp);
110cb93a386Sopenharmony_ci
111cb93a386Sopenharmony_ci            fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
112cb93a386Sopenharmony_ci                                       kVertex_GrShaderFlag);
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci            // Setup pass through color
115cb93a386Sopenharmony_ci            fragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
116cb93a386Sopenharmony_ci            if (gp.colorAttr().isInitialized()) {
117cb93a386Sopenharmony_ci                GrGLSLVarying varying(kHalf4_GrSLType);
118cb93a386Sopenharmony_ci                varyingHandler->addVarying("color", &varying);
119cb93a386Sopenharmony_ci                vertBuilder->codeAppendf("half4 color = %s;", gp.colorAttr().name());
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci                // For SkColor, do a red/blue swap, possible color space conversion, and premul
122cb93a386Sopenharmony_ci                if (gp.fColorArrayType == ColorArrayType::kSkColor) {
123cb93a386Sopenharmony_ci                    vertBuilder->codeAppend("color = color.bgra;");
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ci                    SkString xformedColor;
126cb93a386Sopenharmony_ci                    vertBuilder->appendColorGamutXform(&xformedColor, "color", &fColorSpaceHelper);
127cb93a386Sopenharmony_ci                    vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci                    vertBuilder->codeAppend("color = half4(color.rgb * color.a, color.a);");
130cb93a386Sopenharmony_ci                }
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci                vertBuilder->codeAppendf("%s = color;\n", varying.vsOut());
133cb93a386Sopenharmony_ci                fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
134cb93a386Sopenharmony_ci            } else {
135cb93a386Sopenharmony_ci                this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
136cb93a386Sopenharmony_ci                                        &fColorUniform);
137cb93a386Sopenharmony_ci            }
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci            // Setup position
140cb93a386Sopenharmony_ci            WriteOutputPosition(vertBuilder,
141cb93a386Sopenharmony_ci                                uniformHandler,
142cb93a386Sopenharmony_ci                                *args.fShaderCaps,
143cb93a386Sopenharmony_ci                                gpArgs,
144cb93a386Sopenharmony_ci                                gp.positionAttr().name(),
145cb93a386Sopenharmony_ci                                gp.fViewMatrix,
146cb93a386Sopenharmony_ci                                &fViewMatrixUniform);
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_ci            // emit transforms using either explicit local coords or positions
149cb93a386Sopenharmony_ci            const auto& coordsAttr = gp.localCoordsAttr().isInitialized() ? gp.localCoordsAttr()
150cb93a386Sopenharmony_ci                                                                          : gp.positionAttr();
151cb93a386Sopenharmony_ci            gpArgs->fLocalCoordVar = coordsAttr.asShaderVar();
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci            fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
154cb93a386Sopenharmony_ci        }
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_ci    private:
157cb93a386Sopenharmony_ci        SkMatrix fViewMatrix = SkMatrix::InvalidMatrix();
158cb93a386Sopenharmony_ci        SkPMColor4f fColor   = SK_PMColor4fILLEGAL;
159cb93a386Sopenharmony_ci
160cb93a386Sopenharmony_ci        UniformHandle fViewMatrixUniform;
161cb93a386Sopenharmony_ci        UniformHandle fColorUniform;
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci        GrGLSLColorSpaceXformHelper fColorSpaceHelper;
164cb93a386Sopenharmony_ci    };
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci    VerticesGP(LocalCoordsType localCoordsType,
167cb93a386Sopenharmony_ci               ColorArrayType colorArrayType,
168cb93a386Sopenharmony_ci               const SkPMColor4f& color,
169cb93a386Sopenharmony_ci               sk_sp<GrColorSpaceXform> colorSpaceXform,
170cb93a386Sopenharmony_ci               const SkMatrix& viewMatrix)
171cb93a386Sopenharmony_ci            : INHERITED(kVerticesGP_ClassID)
172cb93a386Sopenharmony_ci            , fColorArrayType(colorArrayType)
173cb93a386Sopenharmony_ci            , fColor(color)
174cb93a386Sopenharmony_ci            , fViewMatrix(viewMatrix)
175cb93a386Sopenharmony_ci            , fColorSpaceXform(std::move(colorSpaceXform)) {
176cb93a386Sopenharmony_ci        constexpr Attribute missingAttr;
177cb93a386Sopenharmony_ci        fAttributes.push_back({"position", kFloat2_GrVertexAttribType, kFloat2_GrSLType});
178cb93a386Sopenharmony_ci        fAttributes.push_back(fColorArrayType != ColorArrayType::kUnused
179cb93a386Sopenharmony_ci                                      ? MakeColorAttribute("inColor", false)
180cb93a386Sopenharmony_ci                                      : missingAttr);
181cb93a386Sopenharmony_ci        fAttributes.push_back(localCoordsType == LocalCoordsType::kExplicit
182cb93a386Sopenharmony_ci                        ? Attribute{"inLocalCoord", kFloat2_GrVertexAttribType, kFloat2_GrSLType}
183cb93a386Sopenharmony_ci                        : missingAttr);
184cb93a386Sopenharmony_ci
185cb93a386Sopenharmony_ci        this->setVertexAttributes(fAttributes.data(), fAttributes.size());
186cb93a386Sopenharmony_ci    }
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ci    enum {
189cb93a386Sopenharmony_ci        kPositionIndex    = 0,
190cb93a386Sopenharmony_ci        kColorIndex       = 1,
191cb93a386Sopenharmony_ci        kLocalCoordsIndex = 2,
192cb93a386Sopenharmony_ci    };
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci    std::vector<Attribute> fAttributes;
195cb93a386Sopenharmony_ci    ColorArrayType fColorArrayType;
196cb93a386Sopenharmony_ci    SkPMColor4f fColor;
197cb93a386Sopenharmony_ci    SkMatrix fViewMatrix;
198cb93a386Sopenharmony_ci    sk_sp<GrColorSpaceXform> fColorSpaceXform;
199cb93a386Sopenharmony_ci
200cb93a386Sopenharmony_ci    using INHERITED = GrGeometryProcessor;
201cb93a386Sopenharmony_ci};
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ciclass DrawVerticesOpImpl final : public GrMeshDrawOp {
204cb93a386Sopenharmony_ciprivate:
205cb93a386Sopenharmony_ci    using Helper = GrSimpleMeshDrawOpHelper;
206cb93a386Sopenharmony_ci
207cb93a386Sopenharmony_cipublic:
208cb93a386Sopenharmony_ci    DEFINE_OP_CLASS_ID
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_ci    DrawVerticesOpImpl(GrProcessorSet*,
211cb93a386Sopenharmony_ci                       const SkPMColor4f&,
212cb93a386Sopenharmony_ci                       sk_sp<SkVertices>,
213cb93a386Sopenharmony_ci                       GrPrimitiveType,
214cb93a386Sopenharmony_ci                       GrAAType,
215cb93a386Sopenharmony_ci                       sk_sp<GrColorSpaceXform>,
216cb93a386Sopenharmony_ci                       const SkMatrixProvider&);
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ci    const char* name() const override { return "DrawVerticesOp"; }
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_ci    void visitProxies(const GrVisitProxyFunc& func) const override {
221cb93a386Sopenharmony_ci        if (fProgramInfo) {
222cb93a386Sopenharmony_ci            fProgramInfo->visitFPProxies(func);
223cb93a386Sopenharmony_ci        } else {
224cb93a386Sopenharmony_ci            fHelper.visitProxies(func);
225cb93a386Sopenharmony_ci        }
226cb93a386Sopenharmony_ci    }
227cb93a386Sopenharmony_ci
228cb93a386Sopenharmony_ci    FixedFunctionFlags fixedFunctionFlags() const override;
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_ci    GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
231cb93a386Sopenharmony_ci
232cb93a386Sopenharmony_ciprivate:
233cb93a386Sopenharmony_ci    GrProgramInfo* programInfo() override { return fProgramInfo; }
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci    void onCreateProgramInfo(const GrCaps*,
236cb93a386Sopenharmony_ci                             SkArenaAlloc*,
237cb93a386Sopenharmony_ci                             const GrSurfaceProxyView& writeView,
238cb93a386Sopenharmony_ci                             bool usesMSAASurface,
239cb93a386Sopenharmony_ci                             GrAppliedClip&&,
240cb93a386Sopenharmony_ci                             const GrDstProxyView&,
241cb93a386Sopenharmony_ci                             GrXferBarrierFlags renderPassXferBarriers,
242cb93a386Sopenharmony_ci                             GrLoadOp colorLoadOp) override;
243cb93a386Sopenharmony_ci
244cb93a386Sopenharmony_ci    void onPrepareDraws(GrMeshDrawTarget*) override;
245cb93a386Sopenharmony_ci    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
246cb93a386Sopenharmony_ci#if GR_TEST_UTILS
247cb93a386Sopenharmony_ci    SkString onDumpInfo() const override;
248cb93a386Sopenharmony_ci#endif
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci    GrGeometryProcessor* makeGP(SkArenaAlloc*);
251cb93a386Sopenharmony_ci
252cb93a386Sopenharmony_ci    GrPrimitiveType primitiveType() const { return fPrimitiveType; }
253cb93a386Sopenharmony_ci    bool combinablePrimitive() const {
254cb93a386Sopenharmony_ci        return GrPrimitiveType::kTriangles == fPrimitiveType ||
255cb93a386Sopenharmony_ci               GrPrimitiveType::kLines == fPrimitiveType ||
256cb93a386Sopenharmony_ci               GrPrimitiveType::kPoints == fPrimitiveType;
257cb93a386Sopenharmony_ci    }
258cb93a386Sopenharmony_ci
259cb93a386Sopenharmony_ci    CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps&) override;
260cb93a386Sopenharmony_ci
261cb93a386Sopenharmony_ci    struct Mesh {
262cb93a386Sopenharmony_ci        SkPMColor4f fColor;  // Used if this->hasPerVertexColors() is false.
263cb93a386Sopenharmony_ci        sk_sp<SkVertices> fVertices;
264cb93a386Sopenharmony_ci        SkMatrix fViewMatrix;
265cb93a386Sopenharmony_ci        bool fIgnoreColors;
266cb93a386Sopenharmony_ci
267cb93a386Sopenharmony_ci        bool hasPerVertexColors() const {
268cb93a386Sopenharmony_ci            return fVertices->priv().hasColors() && !fIgnoreColors;
269cb93a386Sopenharmony_ci        }
270cb93a386Sopenharmony_ci    };
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_ci    bool isIndexed() const {
273cb93a386Sopenharmony_ci        // Consistency enforced in onCombineIfPossible.
274cb93a386Sopenharmony_ci        return fMeshes[0].fVertices->priv().hasIndices();
275cb93a386Sopenharmony_ci    }
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_ci    bool requiresPerVertexColors() const {
278cb93a386Sopenharmony_ci        return fColorArrayType != ColorArrayType::kUnused;
279cb93a386Sopenharmony_ci    }
280cb93a386Sopenharmony_ci
281cb93a386Sopenharmony_ci    bool requiresPerVertexLocalCoords() const {
282cb93a386Sopenharmony_ci        return fLocalCoordsType == LocalCoordsType::kExplicit;
283cb93a386Sopenharmony_ci    }
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci    size_t vertexStride() const {
286cb93a386Sopenharmony_ci        return sizeof(SkPoint) +
287cb93a386Sopenharmony_ci               (this->requiresPerVertexColors() ? sizeof(uint32_t) : 0) +
288cb93a386Sopenharmony_ci               (this->requiresPerVertexLocalCoords() ? sizeof(SkPoint) : 0);
289cb93a386Sopenharmony_ci    }
290cb93a386Sopenharmony_ci
291cb93a386Sopenharmony_ci    Helper fHelper;
292cb93a386Sopenharmony_ci    SkSTArray<1, Mesh, true> fMeshes;
293cb93a386Sopenharmony_ci    // GrPrimitiveType is more expressive than fVertices.mode() so it is used instead and we ignore
294cb93a386Sopenharmony_ci    // the SkVertices mode (though fPrimitiveType may have been inferred from it).
295cb93a386Sopenharmony_ci    GrPrimitiveType fPrimitiveType;
296cb93a386Sopenharmony_ci    int fVertexCount;
297cb93a386Sopenharmony_ci    int fIndexCount;
298cb93a386Sopenharmony_ci    bool fMultipleViewMatrices;
299cb93a386Sopenharmony_ci    LocalCoordsType fLocalCoordsType;
300cb93a386Sopenharmony_ci    ColorArrayType fColorArrayType;
301cb93a386Sopenharmony_ci    sk_sp<GrColorSpaceXform> fColorSpaceXform;
302cb93a386Sopenharmony_ci
303cb93a386Sopenharmony_ci    GrSimpleMesh*  fMesh = nullptr;
304cb93a386Sopenharmony_ci    GrProgramInfo* fProgramInfo = nullptr;
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_ci    using INHERITED = GrMeshDrawOp;
307cb93a386Sopenharmony_ci};
308cb93a386Sopenharmony_ci
309cb93a386Sopenharmony_ciDrawVerticesOpImpl::DrawVerticesOpImpl(GrProcessorSet* processorSet,
310cb93a386Sopenharmony_ci                                       const SkPMColor4f& color,
311cb93a386Sopenharmony_ci                                       sk_sp<SkVertices> vertices,
312cb93a386Sopenharmony_ci                                       GrPrimitiveType primitiveType,
313cb93a386Sopenharmony_ci                                       GrAAType aaType,
314cb93a386Sopenharmony_ci                                       sk_sp<GrColorSpaceXform> colorSpaceXform,
315cb93a386Sopenharmony_ci                                       const SkMatrixProvider& matrixProvider)
316cb93a386Sopenharmony_ci        : INHERITED(ClassID())
317cb93a386Sopenharmony_ci        , fHelper(processorSet, aaType)
318cb93a386Sopenharmony_ci        , fPrimitiveType(primitiveType)
319cb93a386Sopenharmony_ci        , fMultipleViewMatrices(false)
320cb93a386Sopenharmony_ci        , fColorSpaceXform(std::move(colorSpaceXform)) {
321cb93a386Sopenharmony_ci    SkASSERT(vertices);
322cb93a386Sopenharmony_ci
323cb93a386Sopenharmony_ci    SkVerticesPriv info(vertices->priv());
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci    fVertexCount = info.vertexCount();
326cb93a386Sopenharmony_ci    fIndexCount = info.indexCount();
327cb93a386Sopenharmony_ci    fColorArrayType = info.hasColors() ? ColorArrayType::kSkColor
328cb93a386Sopenharmony_ci                                       : ColorArrayType::kUnused;
329cb93a386Sopenharmony_ci    fLocalCoordsType = info.hasTexCoords() ? LocalCoordsType::kExplicit
330cb93a386Sopenharmony_ci                                           : LocalCoordsType::kUsePosition;
331cb93a386Sopenharmony_ci
332cb93a386Sopenharmony_ci    Mesh& mesh = fMeshes.push_back();
333cb93a386Sopenharmony_ci    mesh.fColor = color;
334cb93a386Sopenharmony_ci    mesh.fViewMatrix = matrixProvider.localToDevice();
335cb93a386Sopenharmony_ci    mesh.fVertices = std::move(vertices);
336cb93a386Sopenharmony_ci    mesh.fIgnoreColors = false;
337cb93a386Sopenharmony_ci
338cb93a386Sopenharmony_ci    IsHairline zeroArea;
339cb93a386Sopenharmony_ci    if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) {
340cb93a386Sopenharmony_ci        zeroArea = IsHairline::kYes;
341cb93a386Sopenharmony_ci    } else {
342cb93a386Sopenharmony_ci        zeroArea = IsHairline::kNo;
343cb93a386Sopenharmony_ci    }
344cb93a386Sopenharmony_ci
345cb93a386Sopenharmony_ci    this->setTransformedBounds(mesh.fVertices->bounds(),
346cb93a386Sopenharmony_ci                                mesh.fViewMatrix,
347cb93a386Sopenharmony_ci                                HasAABloat::kNo,
348cb93a386Sopenharmony_ci                                zeroArea);
349cb93a386Sopenharmony_ci}
350cb93a386Sopenharmony_ci
351cb93a386Sopenharmony_ci#if GR_TEST_UTILS
352cb93a386Sopenharmony_ciSkString DrawVerticesOpImpl::onDumpInfo() const {
353cb93a386Sopenharmony_ci    return SkStringPrintf("PrimType: %d, MeshCount %d, VCount: %d, ICount: %d\n%s",
354cb93a386Sopenharmony_ci                          (int)fPrimitiveType, fMeshes.count(), fVertexCount, fIndexCount,
355cb93a386Sopenharmony_ci                          fHelper.dumpInfo().c_str());
356cb93a386Sopenharmony_ci}
357cb93a386Sopenharmony_ci#endif
358cb93a386Sopenharmony_ci
359cb93a386Sopenharmony_ciGrDrawOp::FixedFunctionFlags DrawVerticesOpImpl::fixedFunctionFlags() const {
360cb93a386Sopenharmony_ci    return fHelper.fixedFunctionFlags();
361cb93a386Sopenharmony_ci}
362cb93a386Sopenharmony_ci
363cb93a386Sopenharmony_ciGrProcessorSet::Analysis DrawVerticesOpImpl::finalize(const GrCaps& caps,
364cb93a386Sopenharmony_ci                                                      const GrAppliedClip* clip,
365cb93a386Sopenharmony_ci                                                      GrClampType clampType) {
366cb93a386Sopenharmony_ci    GrProcessorAnalysisColor gpColor;
367cb93a386Sopenharmony_ci    if (this->requiresPerVertexColors()) {
368cb93a386Sopenharmony_ci        gpColor.setToUnknown();
369cb93a386Sopenharmony_ci    } else {
370cb93a386Sopenharmony_ci        gpColor.setToConstant(fMeshes.front().fColor);
371cb93a386Sopenharmony_ci    }
372cb93a386Sopenharmony_ci    auto result = fHelper.finalizeProcessors(caps, clip, clampType,
373cb93a386Sopenharmony_ci                                             GrProcessorAnalysisCoverage::kNone, &gpColor);
374cb93a386Sopenharmony_ci    if (gpColor.isConstant(&fMeshes.front().fColor)) {
375cb93a386Sopenharmony_ci        fMeshes.front().fIgnoreColors = true;
376cb93a386Sopenharmony_ci        fColorArrayType = ColorArrayType::kUnused;
377cb93a386Sopenharmony_ci    }
378cb93a386Sopenharmony_ci    if (!fHelper.usesLocalCoords()) {
379cb93a386Sopenharmony_ci        fLocalCoordsType = LocalCoordsType::kUnused;
380cb93a386Sopenharmony_ci    }
381cb93a386Sopenharmony_ci    return result;
382cb93a386Sopenharmony_ci}
383cb93a386Sopenharmony_ci
384cb93a386Sopenharmony_ciGrGeometryProcessor* DrawVerticesOpImpl::makeGP(SkArenaAlloc* arena) {
385cb93a386Sopenharmony_ci    const SkMatrix& vm = fMultipleViewMatrices ? SkMatrix::I() : fMeshes[0].fViewMatrix;
386cb93a386Sopenharmony_ci
387cb93a386Sopenharmony_ci    sk_sp<GrColorSpaceXform> csxform =
388cb93a386Sopenharmony_ci            (fColorArrayType == ColorArrayType::kSkColor) ? fColorSpaceXform : nullptr;
389cb93a386Sopenharmony_ci
390cb93a386Sopenharmony_ci    auto gp = VerticesGP::Make(arena, fLocalCoordsType, fColorArrayType, fMeshes[0].fColor,
391cb93a386Sopenharmony_ci                               std::move(csxform), vm);
392cb93a386Sopenharmony_ci    SkASSERT(this->vertexStride() == gp->vertexStride());
393cb93a386Sopenharmony_ci    return gp;
394cb93a386Sopenharmony_ci}
395cb93a386Sopenharmony_ci
396cb93a386Sopenharmony_civoid DrawVerticesOpImpl::onCreateProgramInfo(const GrCaps* caps,
397cb93a386Sopenharmony_ci                                             SkArenaAlloc* arena,
398cb93a386Sopenharmony_ci                                             const GrSurfaceProxyView& writeView,
399cb93a386Sopenharmony_ci                                             bool usesMSAASurface,
400cb93a386Sopenharmony_ci                                             GrAppliedClip&& appliedClip,
401cb93a386Sopenharmony_ci                                             const GrDstProxyView& dstProxyView,
402cb93a386Sopenharmony_ci                                             GrXferBarrierFlags renderPassXferBarriers,
403cb93a386Sopenharmony_ci                                             GrLoadOp colorLoadOp) {
404cb93a386Sopenharmony_ci    GrGeometryProcessor* gp = this->makeGP(arena);
405cb93a386Sopenharmony_ci    fProgramInfo = fHelper.createProgramInfo(caps, arena, writeView, usesMSAASurface,
406cb93a386Sopenharmony_ci                                             std::move(appliedClip), dstProxyView, gp,
407cb93a386Sopenharmony_ci                                             this->primitiveType(), renderPassXferBarriers,
408cb93a386Sopenharmony_ci                                             colorLoadOp);
409cb93a386Sopenharmony_ci}
410cb93a386Sopenharmony_ci
411cb93a386Sopenharmony_civoid DrawVerticesOpImpl::onPrepareDraws(GrMeshDrawTarget* target) {
412cb93a386Sopenharmony_ci    // Allocate buffers.
413cb93a386Sopenharmony_ci    size_t vertexStride = this->vertexStride();
414cb93a386Sopenharmony_ci    sk_sp<const GrBuffer> vertexBuffer;
415cb93a386Sopenharmony_ci    int firstVertex = 0;
416cb93a386Sopenharmony_ci    VertexWriter verts{
417cb93a386Sopenharmony_ci            target->makeVertexSpace(vertexStride, fVertexCount, &vertexBuffer, &firstVertex)};
418cb93a386Sopenharmony_ci    if (!verts) {
419cb93a386Sopenharmony_ci        SkDebugf("Could not allocate vertices\n");
420cb93a386Sopenharmony_ci        return;
421cb93a386Sopenharmony_ci    }
422cb93a386Sopenharmony_ci
423cb93a386Sopenharmony_ci    sk_sp<const GrBuffer> indexBuffer;
424cb93a386Sopenharmony_ci    int firstIndex = 0;
425cb93a386Sopenharmony_ci    uint16_t* indices = nullptr;
426cb93a386Sopenharmony_ci    if (this->isIndexed()) {
427cb93a386Sopenharmony_ci        indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
428cb93a386Sopenharmony_ci        if (!indices) {
429cb93a386Sopenharmony_ci            SkDebugf("Could not allocate indices\n");
430cb93a386Sopenharmony_ci            return;
431cb93a386Sopenharmony_ci        }
432cb93a386Sopenharmony_ci    }
433cb93a386Sopenharmony_ci
434cb93a386Sopenharmony_ci    // Copy data into the buffers.
435cb93a386Sopenharmony_ci    bool hasColorAttribute = this->requiresPerVertexColors();
436cb93a386Sopenharmony_ci    bool hasLocalCoordsAttribute = this->requiresPerVertexLocalCoords();
437cb93a386Sopenharmony_ci    int vertexOffset = 0;
438cb93a386Sopenharmony_ci
439cb93a386Sopenharmony_ci    for (const auto& mesh : fMeshes) {
440cb93a386Sopenharmony_ci        SkVerticesPriv info(mesh.fVertices->priv());
441cb93a386Sopenharmony_ci
442cb93a386Sopenharmony_ci        // Copy data into the index buffer.
443cb93a386Sopenharmony_ci        if (indices) {
444cb93a386Sopenharmony_ci            int indexCount = info.indexCount();
445cb93a386Sopenharmony_ci            for (int i = 0; i < indexCount; ++i) {
446cb93a386Sopenharmony_ci                *indices++ = info.indices()[i] + vertexOffset;
447cb93a386Sopenharmony_ci            }
448cb93a386Sopenharmony_ci        }
449cb93a386Sopenharmony_ci
450cb93a386Sopenharmony_ci        // Copy data into the vertex buffer.
451cb93a386Sopenharmony_ci        int vertexCount = info.vertexCount();
452cb93a386Sopenharmony_ci        const SkPoint* positions = info.positions();
453cb93a386Sopenharmony_ci        const SkColor* colors = info.colors();
454cb93a386Sopenharmony_ci        const SkPoint* localCoords = info.texCoords() ? info.texCoords() : positions;
455cb93a386Sopenharmony_ci
456cb93a386Sopenharmony_ci        // TODO4F: Preserve float colors
457cb93a386Sopenharmony_ci        GrColor meshColor = mesh.fColor.toBytes_RGBA();
458cb93a386Sopenharmony_ci
459cb93a386Sopenharmony_ci        SkPoint* posBase = (SkPoint*)verts.ptr();
460cb93a386Sopenharmony_ci
461cb93a386Sopenharmony_ci        for (int i = 0; i < vertexCount; ++i) {
462cb93a386Sopenharmony_ci            verts << positions[i];
463cb93a386Sopenharmony_ci            if (hasColorAttribute) {
464cb93a386Sopenharmony_ci                verts << (mesh.hasPerVertexColors() ? colors[i] : meshColor);
465cb93a386Sopenharmony_ci            }
466cb93a386Sopenharmony_ci            if (hasLocalCoordsAttribute) {
467cb93a386Sopenharmony_ci                verts << localCoords[i];
468cb93a386Sopenharmony_ci            }
469cb93a386Sopenharmony_ci        }
470cb93a386Sopenharmony_ci
471cb93a386Sopenharmony_ci        if (fMultipleViewMatrices) {
472cb93a386Sopenharmony_ci            SkASSERT(!mesh.fViewMatrix.hasPerspective());
473cb93a386Sopenharmony_ci            SkMatrixPriv::MapPointsWithStride(mesh.fViewMatrix, posBase, vertexStride,
474cb93a386Sopenharmony_ci                                              positions, sizeof(SkPoint), vertexCount);
475cb93a386Sopenharmony_ci        }
476cb93a386Sopenharmony_ci
477cb93a386Sopenharmony_ci        vertexOffset += vertexCount;
478cb93a386Sopenharmony_ci    }
479cb93a386Sopenharmony_ci
480cb93a386Sopenharmony_ci    SkASSERT(!fMesh);
481cb93a386Sopenharmony_ci    fMesh = target->allocMesh();
482cb93a386Sopenharmony_ci    if (this->isIndexed()) {
483cb93a386Sopenharmony_ci        fMesh->setIndexed(std::move(indexBuffer), fIndexCount, firstIndex, 0, fVertexCount - 1,
484cb93a386Sopenharmony_ci                         GrPrimitiveRestart::kNo, std::move(vertexBuffer), firstVertex);
485cb93a386Sopenharmony_ci    } else {
486cb93a386Sopenharmony_ci        fMesh->set(std::move(vertexBuffer), fVertexCount, firstVertex);
487cb93a386Sopenharmony_ci    }
488cb93a386Sopenharmony_ci}
489cb93a386Sopenharmony_ci
490cb93a386Sopenharmony_civoid DrawVerticesOpImpl::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
491cb93a386Sopenharmony_ci    if (!fProgramInfo) {
492cb93a386Sopenharmony_ci        this->createProgramInfo(flushState);
493cb93a386Sopenharmony_ci    }
494cb93a386Sopenharmony_ci
495cb93a386Sopenharmony_ci    if (!fProgramInfo || !fMesh) {
496cb93a386Sopenharmony_ci        return;
497cb93a386Sopenharmony_ci    }
498cb93a386Sopenharmony_ci
499cb93a386Sopenharmony_ci    flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
500cb93a386Sopenharmony_ci    flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
501cb93a386Sopenharmony_ci    flushState->drawMesh(*fMesh);
502cb93a386Sopenharmony_ci}
503cb93a386Sopenharmony_ci
504cb93a386Sopenharmony_ciGrOp::CombineResult DrawVerticesOpImpl::onCombineIfPossible(GrOp* t,
505cb93a386Sopenharmony_ci                                                            SkArenaAlloc*,
506cb93a386Sopenharmony_ci                                                            const GrCaps& caps) {
507cb93a386Sopenharmony_ci    auto that = t->cast<DrawVerticesOpImpl>();
508cb93a386Sopenharmony_ci
509cb93a386Sopenharmony_ci    if (!fHelper.isCompatible(that->fHelper, caps, this->bounds(), that->bounds())) {
510cb93a386Sopenharmony_ci        return CombineResult::kCannotCombine;
511cb93a386Sopenharmony_ci    }
512cb93a386Sopenharmony_ci
513cb93a386Sopenharmony_ci    if (!this->combinablePrimitive() || this->primitiveType() != that->primitiveType()) {
514cb93a386Sopenharmony_ci        return CombineResult::kCannotCombine;
515cb93a386Sopenharmony_ci    }
516cb93a386Sopenharmony_ci
517cb93a386Sopenharmony_ci    if (this->isIndexed() != that->isIndexed()) {
518cb93a386Sopenharmony_ci        return CombineResult::kCannotCombine;
519cb93a386Sopenharmony_ci    }
520cb93a386Sopenharmony_ci
521cb93a386Sopenharmony_ci    if (fVertexCount + that->fVertexCount > SkTo<int>(UINT16_MAX)) {
522cb93a386Sopenharmony_ci        return CombineResult::kCannotCombine;
523cb93a386Sopenharmony_ci    }
524cb93a386Sopenharmony_ci
525cb93a386Sopenharmony_ci    // We can't mix draws that use SkColor vertex colors with those that don't. We can mix uniform
526cb93a386Sopenharmony_ci    // color draws with GrColor draws (by expanding the uniform color into vertex color).
527cb93a386Sopenharmony_ci    if ((fColorArrayType == ColorArrayType::kSkColor) !=
528cb93a386Sopenharmony_ci        (that->fColorArrayType == ColorArrayType::kSkColor)) {
529cb93a386Sopenharmony_ci        return CombineResult::kCannotCombine;
530cb93a386Sopenharmony_ci    }
531cb93a386Sopenharmony_ci
532cb93a386Sopenharmony_ci    // If we're acquiring a mesh with a different view matrix, or an op that needed multiple view
533cb93a386Sopenharmony_ci    // matrices, we need multiple view matrices.
534cb93a386Sopenharmony_ci    bool needMultipleViewMatrices =
535cb93a386Sopenharmony_ci            fMultipleViewMatrices || that->fMultipleViewMatrices ||
536cb93a386Sopenharmony_ci            !SkMatrixPriv::CheapEqual(this->fMeshes[0].fViewMatrix, that->fMeshes[0].fViewMatrix);
537cb93a386Sopenharmony_ci
538cb93a386Sopenharmony_ci    // ... but we can't enable multiple view matrices if any of them have perspective, or our other
539cb93a386Sopenharmony_ci    // varyings won't be interpolated correctly.
540cb93a386Sopenharmony_ci    if (needMultipleViewMatrices && (this->fMeshes[0].fViewMatrix.hasPerspective() ||
541cb93a386Sopenharmony_ci                                     that->fMeshes[0].fViewMatrix.hasPerspective())) {
542cb93a386Sopenharmony_ci        return CombineResult::kCannotCombine;
543cb93a386Sopenharmony_ci    } else {
544cb93a386Sopenharmony_ci        fMultipleViewMatrices = needMultipleViewMatrices;
545cb93a386Sopenharmony_ci    }
546cb93a386Sopenharmony_ci
547cb93a386Sopenharmony_ci    // If the other op already required per-vertex colors, the combined mesh does.
548cb93a386Sopenharmony_ci    if (that->fColorArrayType == ColorArrayType::kPremulGrColor) {
549cb93a386Sopenharmony_ci        fColorArrayType = ColorArrayType::kPremulGrColor;
550cb93a386Sopenharmony_ci    }
551cb93a386Sopenharmony_ci
552cb93a386Sopenharmony_ci    // If we combine meshes with different (uniform) colors, switch to per-vertex colors.
553cb93a386Sopenharmony_ci    if (fColorArrayType == ColorArrayType::kUnused) {
554cb93a386Sopenharmony_ci        SkASSERT(that->fColorArrayType == ColorArrayType::kUnused);
555cb93a386Sopenharmony_ci        if (this->fMeshes[0].fColor != that->fMeshes[0].fColor) {
556cb93a386Sopenharmony_ci            fColorArrayType = ColorArrayType::kPremulGrColor;
557cb93a386Sopenharmony_ci        }
558cb93a386Sopenharmony_ci    }
559cb93a386Sopenharmony_ci
560cb93a386Sopenharmony_ci    // NOTE: For SkColor vertex colors, the source color space is always sRGB, and the destination
561cb93a386Sopenharmony_ci    // gamut is determined by the render target context. A mis-match should be impossible.
562cb93a386Sopenharmony_ci    SkASSERT(GrColorSpaceXform::Equals(fColorSpaceXform.get(), that->fColorSpaceXform.get()));
563cb93a386Sopenharmony_ci
564cb93a386Sopenharmony_ci    // If the other op already required explicit local coords the combined mesh does.
565cb93a386Sopenharmony_ci    if (that->fLocalCoordsType == LocalCoordsType::kExplicit) {
566cb93a386Sopenharmony_ci        fLocalCoordsType = LocalCoordsType::kExplicit;
567cb93a386Sopenharmony_ci    }
568cb93a386Sopenharmony_ci
569cb93a386Sopenharmony_ci    // If we were planning to use positions for local coords but now have multiple view matrices,
570cb93a386Sopenharmony_ci    // switch to explicit local coords.
571cb93a386Sopenharmony_ci    if (fLocalCoordsType == LocalCoordsType::kUsePosition && fMultipleViewMatrices) {
572cb93a386Sopenharmony_ci        fLocalCoordsType = LocalCoordsType::kExplicit;
573cb93a386Sopenharmony_ci    }
574cb93a386Sopenharmony_ci
575cb93a386Sopenharmony_ci    fMeshes.push_back_n(that->fMeshes.count(), that->fMeshes.begin());
576cb93a386Sopenharmony_ci    fVertexCount += that->fVertexCount;
577cb93a386Sopenharmony_ci    fIndexCount += that->fIndexCount;
578cb93a386Sopenharmony_ci
579cb93a386Sopenharmony_ci    return CombineResult::kMerged;
580cb93a386Sopenharmony_ci}
581cb93a386Sopenharmony_ci
582cb93a386Sopenharmony_cistatic GrPrimitiveType SkVertexModeToGrPrimitiveType(SkVertices::VertexMode mode) {
583cb93a386Sopenharmony_ci    switch (mode) {
584cb93a386Sopenharmony_ci        case SkVertices::kTriangles_VertexMode:
585cb93a386Sopenharmony_ci            return GrPrimitiveType::kTriangles;
586cb93a386Sopenharmony_ci        case SkVertices::kTriangleStrip_VertexMode:
587cb93a386Sopenharmony_ci            return GrPrimitiveType::kTriangleStrip;
588cb93a386Sopenharmony_ci        case SkVertices::kTriangleFan_VertexMode:
589cb93a386Sopenharmony_ci            break;
590cb93a386Sopenharmony_ci    }
591cb93a386Sopenharmony_ci    SK_ABORT("Invalid mode");
592cb93a386Sopenharmony_ci}
593cb93a386Sopenharmony_ci
594cb93a386Sopenharmony_ci} // anonymous namespace
595cb93a386Sopenharmony_ci
596cb93a386Sopenharmony_ciGrOp::Owner Make(GrRecordingContext* context,
597cb93a386Sopenharmony_ci                 GrPaint&& paint,
598cb93a386Sopenharmony_ci                 sk_sp<SkVertices> vertices,
599cb93a386Sopenharmony_ci                 const SkMatrixProvider& matrixProvider,
600cb93a386Sopenharmony_ci                 GrAAType aaType,
601cb93a386Sopenharmony_ci                 sk_sp<GrColorSpaceXform> colorSpaceXform,
602cb93a386Sopenharmony_ci                 GrPrimitiveType* overridePrimType) {
603cb93a386Sopenharmony_ci    SkASSERT(vertices);
604cb93a386Sopenharmony_ci    GrPrimitiveType primType = overridePrimType
605cb93a386Sopenharmony_ci                                       ? *overridePrimType
606cb93a386Sopenharmony_ci                                       : SkVertexModeToGrPrimitiveType(vertices->priv().mode());
607cb93a386Sopenharmony_ci    return GrSimpleMeshDrawOpHelper::FactoryHelper<DrawVerticesOpImpl>(context,
608cb93a386Sopenharmony_ci                                                                       std::move(paint),
609cb93a386Sopenharmony_ci                                                                       std::move(vertices),
610cb93a386Sopenharmony_ci                                                                       primType,
611cb93a386Sopenharmony_ci                                                                       aaType,
612cb93a386Sopenharmony_ci                                                                       std::move(colorSpaceXform),
613cb93a386Sopenharmony_ci                                                                       matrixProvider);
614cb93a386Sopenharmony_ci}
615cb93a386Sopenharmony_ci
616cb93a386Sopenharmony_ci} // namespace skgpu::v1::DrawVerticesOp
617cb93a386Sopenharmony_ci
618cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
619cb93a386Sopenharmony_ci
620cb93a386Sopenharmony_ci#if GR_TEST_UTILS
621cb93a386Sopenharmony_ci
622cb93a386Sopenharmony_ci#include "src/gpu/GrDrawOpTest.h"
623cb93a386Sopenharmony_ci
624cb93a386Sopenharmony_cistatic uint32_t seed_vertices(GrPrimitiveType type) {
625cb93a386Sopenharmony_ci    switch (type) {
626cb93a386Sopenharmony_ci        case GrPrimitiveType::kTriangles:
627cb93a386Sopenharmony_ci        case GrPrimitiveType::kTriangleStrip:
628cb93a386Sopenharmony_ci            return 3;
629cb93a386Sopenharmony_ci        case GrPrimitiveType::kPoints:
630cb93a386Sopenharmony_ci            return 1;
631cb93a386Sopenharmony_ci        case GrPrimitiveType::kLines:
632cb93a386Sopenharmony_ci        case GrPrimitiveType::kLineStrip:
633cb93a386Sopenharmony_ci            return 2;
634cb93a386Sopenharmony_ci        case GrPrimitiveType::kPatches:
635cb93a386Sopenharmony_ci        case GrPrimitiveType::kPath:
636cb93a386Sopenharmony_ci            SkASSERT(0);
637cb93a386Sopenharmony_ci            return 0;
638cb93a386Sopenharmony_ci    }
639cb93a386Sopenharmony_ci    SK_ABORT("Incomplete switch\n");
640cb93a386Sopenharmony_ci}
641cb93a386Sopenharmony_ci
642cb93a386Sopenharmony_cistatic uint32_t primitive_vertices(GrPrimitiveType type) {
643cb93a386Sopenharmony_ci    switch (type) {
644cb93a386Sopenharmony_ci        case GrPrimitiveType::kTriangles:
645cb93a386Sopenharmony_ci            return 3;
646cb93a386Sopenharmony_ci        case GrPrimitiveType::kLines:
647cb93a386Sopenharmony_ci            return 2;
648cb93a386Sopenharmony_ci        case GrPrimitiveType::kTriangleStrip:
649cb93a386Sopenharmony_ci        case GrPrimitiveType::kPoints:
650cb93a386Sopenharmony_ci        case GrPrimitiveType::kLineStrip:
651cb93a386Sopenharmony_ci            return 1;
652cb93a386Sopenharmony_ci        case GrPrimitiveType::kPatches:
653cb93a386Sopenharmony_ci        case GrPrimitiveType::kPath:
654cb93a386Sopenharmony_ci            SkASSERT(0);
655cb93a386Sopenharmony_ci            return 0;
656cb93a386Sopenharmony_ci    }
657cb93a386Sopenharmony_ci    SK_ABORT("Incomplete switch\n");
658cb93a386Sopenharmony_ci}
659cb93a386Sopenharmony_ci
660cb93a386Sopenharmony_cistatic SkPoint random_point(SkRandom* random, SkScalar min, SkScalar max) {
661cb93a386Sopenharmony_ci    SkPoint p;
662cb93a386Sopenharmony_ci    p.fX = random->nextRangeScalar(min, max);
663cb93a386Sopenharmony_ci    p.fY = random->nextRangeScalar(min, max);
664cb93a386Sopenharmony_ci    return p;
665cb93a386Sopenharmony_ci}
666cb93a386Sopenharmony_ci
667cb93a386Sopenharmony_cistatic void randomize_params(size_t count, size_t maxVertex, SkScalar min, SkScalar max,
668cb93a386Sopenharmony_ci                             SkRandom* random, SkTArray<SkPoint>* positions,
669cb93a386Sopenharmony_ci                             SkTArray<SkPoint>* texCoords, bool hasTexCoords,
670cb93a386Sopenharmony_ci                             SkTArray<uint32_t>* colors, bool hasColors,
671cb93a386Sopenharmony_ci                             SkTArray<uint16_t>* indices, bool hasIndices) {
672cb93a386Sopenharmony_ci    for (uint32_t v = 0; v < count; v++) {
673cb93a386Sopenharmony_ci        positions->push_back(random_point(random, min, max));
674cb93a386Sopenharmony_ci        if (hasTexCoords) {
675cb93a386Sopenharmony_ci            texCoords->push_back(random_point(random, min, max));
676cb93a386Sopenharmony_ci        }
677cb93a386Sopenharmony_ci        if (hasColors) {
678cb93a386Sopenharmony_ci            colors->push_back(GrTest::RandomColor(random));
679cb93a386Sopenharmony_ci        }
680cb93a386Sopenharmony_ci        if (hasIndices) {
681cb93a386Sopenharmony_ci            SkASSERT(maxVertex <= UINT16_MAX);
682cb93a386Sopenharmony_ci            indices->push_back(random->nextULessThan((uint16_t)maxVertex));
683cb93a386Sopenharmony_ci        }
684cb93a386Sopenharmony_ci    }
685cb93a386Sopenharmony_ci}
686cb93a386Sopenharmony_ci
687cb93a386Sopenharmony_ciGR_DRAW_OP_TEST_DEFINE(DrawVerticesOp) {
688cb93a386Sopenharmony_ci    GrPrimitiveType types[] = {
689cb93a386Sopenharmony_ci        GrPrimitiveType::kTriangles,
690cb93a386Sopenharmony_ci        GrPrimitiveType::kTriangleStrip,
691cb93a386Sopenharmony_ci        GrPrimitiveType::kPoints,
692cb93a386Sopenharmony_ci        GrPrimitiveType::kLines,
693cb93a386Sopenharmony_ci        GrPrimitiveType::kLineStrip
694cb93a386Sopenharmony_ci    };
695cb93a386Sopenharmony_ci    auto type = types[random->nextULessThan(SK_ARRAY_COUNT(types))];
696cb93a386Sopenharmony_ci
697cb93a386Sopenharmony_ci    uint32_t primitiveCount = random->nextRangeU(1, 100);
698cb93a386Sopenharmony_ci
699cb93a386Sopenharmony_ci    // TODO make 'sensible' indexbuffers
700cb93a386Sopenharmony_ci    SkTArray<SkPoint> positions;
701cb93a386Sopenharmony_ci    SkTArray<SkPoint> texCoords;
702cb93a386Sopenharmony_ci    SkTArray<uint32_t> colors;
703cb93a386Sopenharmony_ci    SkTArray<uint16_t> indices;
704cb93a386Sopenharmony_ci
705cb93a386Sopenharmony_ci    bool hasTexCoords = random->nextBool();
706cb93a386Sopenharmony_ci    bool hasIndices = random->nextBool();
707cb93a386Sopenharmony_ci    bool hasColors = random->nextBool();
708cb93a386Sopenharmony_ci
709cb93a386Sopenharmony_ci    uint32_t vertexCount = seed_vertices(type) + (primitiveCount - 1) * primitive_vertices(type);
710cb93a386Sopenharmony_ci
711cb93a386Sopenharmony_ci    static const SkScalar kMinVertExtent = -100.f;
712cb93a386Sopenharmony_ci    static const SkScalar kMaxVertExtent = 100.f;
713cb93a386Sopenharmony_ci    randomize_params(seed_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent, random,
714cb93a386Sopenharmony_ci                     &positions, &texCoords, hasTexCoords, &colors, hasColors, &indices,
715cb93a386Sopenharmony_ci                     hasIndices);
716cb93a386Sopenharmony_ci
717cb93a386Sopenharmony_ci    for (uint32_t i = 1; i < primitiveCount; i++) {
718cb93a386Sopenharmony_ci        randomize_params(primitive_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent,
719cb93a386Sopenharmony_ci                         random, &positions, &texCoords, hasTexCoords, &colors, hasColors, &indices,
720cb93a386Sopenharmony_ci                         hasIndices);
721cb93a386Sopenharmony_ci    }
722cb93a386Sopenharmony_ci
723cb93a386Sopenharmony_ci    SkSimpleMatrixProvider matrixProvider(GrTest::TestMatrix(random));
724cb93a386Sopenharmony_ci
725cb93a386Sopenharmony_ci    sk_sp<GrColorSpaceXform> colorSpaceXform = GrTest::TestColorXform(random);
726cb93a386Sopenharmony_ci
727cb93a386Sopenharmony_ci    static constexpr SkVertices::VertexMode kIgnoredMode = SkVertices::kTriangles_VertexMode;
728cb93a386Sopenharmony_ci    sk_sp<SkVertices> vertices = SkVertices::MakeCopy(kIgnoredMode, vertexCount, positions.begin(),
729cb93a386Sopenharmony_ci                                                      texCoords.begin(), colors.begin(),
730cb93a386Sopenharmony_ci                                                      hasIndices ? indices.count() : 0,
731cb93a386Sopenharmony_ci                                                      indices.begin());
732cb93a386Sopenharmony_ci    GrAAType aaType = GrAAType::kNone;
733cb93a386Sopenharmony_ci    if (numSamples > 1 && random->nextBool()) {
734cb93a386Sopenharmony_ci        aaType = GrAAType::kMSAA;
735cb93a386Sopenharmony_ci    }
736cb93a386Sopenharmony_ci    return skgpu::v1::DrawVerticesOp::Make(context,
737cb93a386Sopenharmony_ci                                           std::move(paint),
738cb93a386Sopenharmony_ci                                           std::move(vertices),
739cb93a386Sopenharmony_ci                                           matrixProvider,
740cb93a386Sopenharmony_ci                                           aaType,
741cb93a386Sopenharmony_ci                                           std::move(colorSpaceXform),
742cb93a386Sopenharmony_ci                                           &type);
743cb93a386Sopenharmony_ci}
744cb93a386Sopenharmony_ci
745cb93a386Sopenharmony_ci#endif
746