1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCanvasPriv.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/KeyBuilder.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrBuffer.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCanvas.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGeometryProcessor.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuBuffer.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrOpFlushState.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProcessor.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProcessorSet.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProgramInfo.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderVar.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceDrawContext.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrDrawOp.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrOp.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/ProxyUtils.h"
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
33*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker class GrAppliedClip;
36*c8dee2aaSAndroid Build Coastguard Worker class GrGLSLProgramDataManager;
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker namespace {
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker enum class AttrMode {
41*c8dee2aaSAndroid Build Coastguard Worker kAuto,
42*c8dee2aaSAndroid Build Coastguard Worker kManual,
43*c8dee2aaSAndroid Build Coastguard Worker kWacky
44*c8dee2aaSAndroid Build Coastguard Worker };
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker class AttributeTestProcessor : public GrGeometryProcessor {
47*c8dee2aaSAndroid Build Coastguard Worker public:
Make(SkArenaAlloc * arena,AttrMode mode)48*c8dee2aaSAndroid Build Coastguard Worker static GrGeometryProcessor* Make(SkArenaAlloc* arena, AttrMode mode) {
49*c8dee2aaSAndroid Build Coastguard Worker return arena->make([&](void* ptr) { return new (ptr) AttributeTestProcessor(mode); });
50*c8dee2aaSAndroid Build Coastguard Worker }
51*c8dee2aaSAndroid Build Coastguard Worker
name() const52*c8dee2aaSAndroid Build Coastguard Worker const char* name() const final { return "AttributeTestProcessor"; }
53*c8dee2aaSAndroid Build Coastguard Worker
addToKey(const GrShaderCaps &,skgpu::KeyBuilder * b) const54*c8dee2aaSAndroid Build Coastguard Worker void addToKey(const GrShaderCaps&, skgpu::KeyBuilder* b) const final {
55*c8dee2aaSAndroid Build Coastguard Worker b->add32(static_cast<uint32_t>(fMode));
56*c8dee2aaSAndroid Build Coastguard Worker }
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final;
59*c8dee2aaSAndroid Build Coastguard Worker
60*c8dee2aaSAndroid Build Coastguard Worker private:
AttributeTestProcessor(AttrMode mode)61*c8dee2aaSAndroid Build Coastguard Worker AttributeTestProcessor(AttrMode mode)
62*c8dee2aaSAndroid Build Coastguard Worker : GrGeometryProcessor(kAttributeTestProcessor_ClassID), fMode(mode) {
63*c8dee2aaSAndroid Build Coastguard Worker switch (fMode) {
64*c8dee2aaSAndroid Build Coastguard Worker case AttrMode::kAuto:
65*c8dee2aaSAndroid Build Coastguard Worker fAttributes.emplace_back("pos", kFloat2_GrVertexAttribType, SkSLType::kFloat2);
66*c8dee2aaSAndroid Build Coastguard Worker fAttributes.emplace_back("color", kUByte4_norm_GrVertexAttribType,
67*c8dee2aaSAndroid Build Coastguard Worker SkSLType::kHalf4);
68*c8dee2aaSAndroid Build Coastguard Worker this->setVertexAttributesWithImplicitOffsets(fAttributes.data(),
69*c8dee2aaSAndroid Build Coastguard Worker fAttributes.size());
70*c8dee2aaSAndroid Build Coastguard Worker break;
71*c8dee2aaSAndroid Build Coastguard Worker case AttrMode::kManual:
72*c8dee2aaSAndroid Build Coastguard Worker // Same result as kAuto but with explicitly specified offsets and stride.
73*c8dee2aaSAndroid Build Coastguard Worker fAttributes.emplace_back("pos", kFloat2_GrVertexAttribType, SkSLType::kFloat2, 0);
74*c8dee2aaSAndroid Build Coastguard Worker fAttributes.emplace_back("color", kUByte4_norm_GrVertexAttribType,
75*c8dee2aaSAndroid Build Coastguard Worker SkSLType::kHalf4, 8);
76*c8dee2aaSAndroid Build Coastguard Worker this->setVertexAttributes(fAttributes.data(), fAttributes.size(), 12);
77*c8dee2aaSAndroid Build Coastguard Worker break;
78*c8dee2aaSAndroid Build Coastguard Worker case AttrMode::kWacky:
79*c8dee2aaSAndroid Build Coastguard Worker // 0 thru 7 : float2 aliased to "pos0" and "pos1"
80*c8dee2aaSAndroid Build Coastguard Worker // 8 thru 11: pad
81*c8dee2aaSAndroid Build Coastguard Worker // 12 thru 15: unorm4 "color"
82*c8dee2aaSAndroid Build Coastguard Worker // 16 thru 19: pad
83*c8dee2aaSAndroid Build Coastguard Worker fAttributes.emplace_back("pos0", kFloat2_GrVertexAttribType, SkSLType::kFloat2, 0);
84*c8dee2aaSAndroid Build Coastguard Worker fAttributes.emplace_back("pos1", kFloat2_GrVertexAttribType, SkSLType::kFloat2, 0);
85*c8dee2aaSAndroid Build Coastguard Worker fAttributes.emplace_back("color", kUByte4_norm_GrVertexAttribType,
86*c8dee2aaSAndroid Build Coastguard Worker SkSLType::kHalf4, 12);
87*c8dee2aaSAndroid Build Coastguard Worker this->setVertexAttributes(fAttributes.data(), fAttributes.size(), 20);
88*c8dee2aaSAndroid Build Coastguard Worker break;
89*c8dee2aaSAndroid Build Coastguard Worker }
90*c8dee2aaSAndroid Build Coastguard Worker }
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker const AttrMode fMode;
93*c8dee2aaSAndroid Build Coastguard Worker
94*c8dee2aaSAndroid Build Coastguard Worker std::vector<Attribute> fAttributes;
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrGeometryProcessor;
97*c8dee2aaSAndroid Build Coastguard Worker };
98*c8dee2aaSAndroid Build Coastguard Worker
makeProgramImpl(const GrShaderCaps &) const99*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrGeometryProcessor::ProgramImpl> AttributeTestProcessor::makeProgramImpl(
100*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps&) const {
101*c8dee2aaSAndroid Build Coastguard Worker class Impl : public ProgramImpl {
102*c8dee2aaSAndroid Build Coastguard Worker public:
103*c8dee2aaSAndroid Build Coastguard Worker void setData(const GrGLSLProgramDataManager&,
104*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps&,
105*c8dee2aaSAndroid Build Coastguard Worker const GrGeometryProcessor&) override {}
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker private:
108*c8dee2aaSAndroid Build Coastguard Worker void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
109*c8dee2aaSAndroid Build Coastguard Worker const AttributeTestProcessor& proc = args.fGeomProc.cast<AttributeTestProcessor>();
110*c8dee2aaSAndroid Build Coastguard Worker args.fVaryingHandler->emitAttributes(proc);
111*c8dee2aaSAndroid Build Coastguard Worker if (proc.fMode == AttrMode::kWacky) {
112*c8dee2aaSAndroid Build Coastguard Worker args.fVertBuilder->codeAppend("float2 pos = pos0 + pos1;");
113*c8dee2aaSAndroid Build Coastguard Worker }
114*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
115*c8dee2aaSAndroid Build Coastguard Worker args.fVaryingHandler->addPassThroughAttribute(GrShaderVar("color", SkSLType::kHalf4),
116*c8dee2aaSAndroid Build Coastguard Worker args.fOutputColor);
117*c8dee2aaSAndroid Build Coastguard Worker gpArgs->fPositionVar.set(SkSLType::kFloat2, "pos");
118*c8dee2aaSAndroid Build Coastguard Worker args.fFragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
119*c8dee2aaSAndroid Build Coastguard Worker }
120*c8dee2aaSAndroid Build Coastguard Worker };
121*c8dee2aaSAndroid Build Coastguard Worker
122*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<Impl>();
123*c8dee2aaSAndroid Build Coastguard Worker }
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker class AttributeTestOp : public GrDrawOp {
126*c8dee2aaSAndroid Build Coastguard Worker public:
127*c8dee2aaSAndroid Build Coastguard Worker DEFINE_OP_CLASS_ID
128*c8dee2aaSAndroid Build Coastguard Worker
Make(GrRecordingContext * context,AttrMode mode,const SkRect & r)129*c8dee2aaSAndroid Build Coastguard Worker static GrOp::Owner Make(GrRecordingContext* context, AttrMode mode, const SkRect& r) {
130*c8dee2aaSAndroid Build Coastguard Worker return GrOp::Make<AttributeTestOp>(context, mode, r);
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker private:
AttributeTestOp(AttrMode mode,SkRect rect)134*c8dee2aaSAndroid Build Coastguard Worker AttributeTestOp(AttrMode mode, SkRect rect) : GrDrawOp(ClassID()), fMode(mode), fRect(rect) {
135*c8dee2aaSAndroid Build Coastguard Worker this->setBounds(fRect, HasAABloat::kNo, IsHairline::kNo);
136*c8dee2aaSAndroid Build Coastguard Worker }
137*c8dee2aaSAndroid Build Coastguard Worker
name() const138*c8dee2aaSAndroid Build Coastguard Worker const char* name() const override { return "AttributeTestOp"; }
fixedFunctionFlags() const139*c8dee2aaSAndroid Build Coastguard Worker FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
finalize(const GrCaps &,const GrAppliedClip *,GrClampType)140*c8dee2aaSAndroid Build Coastguard Worker GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override {
141*c8dee2aaSAndroid Build Coastguard Worker return GrProcessorSet::EmptySetAnalysis();
142*c8dee2aaSAndroid Build Coastguard Worker }
143*c8dee2aaSAndroid Build Coastguard Worker
createProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp) const144*c8dee2aaSAndroid Build Coastguard Worker GrProgramInfo* createProgramInfo(const GrCaps* caps,
145*c8dee2aaSAndroid Build Coastguard Worker SkArenaAlloc* arena,
146*c8dee2aaSAndroid Build Coastguard Worker const GrSurfaceProxyView& writeView,
147*c8dee2aaSAndroid Build Coastguard Worker bool usesMSAASurface,
148*c8dee2aaSAndroid Build Coastguard Worker GrAppliedClip&& appliedClip,
149*c8dee2aaSAndroid Build Coastguard Worker const GrDstProxyView& dstProxyView,
150*c8dee2aaSAndroid Build Coastguard Worker GrXferBarrierFlags renderPassXferBarriers,
151*c8dee2aaSAndroid Build Coastguard Worker GrLoadOp colorLoadOp) const {
152*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor* geomProc = AttributeTestProcessor::Make(arena, fMode);
153*c8dee2aaSAndroid Build Coastguard Worker
154*c8dee2aaSAndroid Build Coastguard Worker return sk_gpu_test::CreateProgramInfo(caps,
155*c8dee2aaSAndroid Build Coastguard Worker arena,
156*c8dee2aaSAndroid Build Coastguard Worker writeView,
157*c8dee2aaSAndroid Build Coastguard Worker usesMSAASurface,
158*c8dee2aaSAndroid Build Coastguard Worker std::move(appliedClip),
159*c8dee2aaSAndroid Build Coastguard Worker dstProxyView,
160*c8dee2aaSAndroid Build Coastguard Worker geomProc,
161*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode::kSrcOver,
162*c8dee2aaSAndroid Build Coastguard Worker GrPrimitiveType::kTriangleStrip,
163*c8dee2aaSAndroid Build Coastguard Worker renderPassXferBarriers,
164*c8dee2aaSAndroid Build Coastguard Worker colorLoadOp);
165*c8dee2aaSAndroid Build Coastguard Worker }
166*c8dee2aaSAndroid Build Coastguard Worker
createProgramInfo(GrOpFlushState * flushState) const167*c8dee2aaSAndroid Build Coastguard Worker GrProgramInfo* createProgramInfo(GrOpFlushState* flushState) const {
168*c8dee2aaSAndroid Build Coastguard Worker return this->createProgramInfo(&flushState->caps(),
169*c8dee2aaSAndroid Build Coastguard Worker flushState->allocator(),
170*c8dee2aaSAndroid Build Coastguard Worker flushState->writeView(),
171*c8dee2aaSAndroid Build Coastguard Worker flushState->usesMSAASurface(),
172*c8dee2aaSAndroid Build Coastguard Worker flushState->detachAppliedClip(),
173*c8dee2aaSAndroid Build Coastguard Worker flushState->dstProxyView(),
174*c8dee2aaSAndroid Build Coastguard Worker flushState->renderPassBarriers(),
175*c8dee2aaSAndroid Build Coastguard Worker flushState->colorLoadOp());
176*c8dee2aaSAndroid Build Coastguard Worker }
177*c8dee2aaSAndroid Build Coastguard Worker
onPrePrepare(GrRecordingContext * context,const GrSurfaceProxyView & writeView,GrAppliedClip * clip,const GrDstProxyView & dstProxyView,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)178*c8dee2aaSAndroid Build Coastguard Worker void onPrePrepare(GrRecordingContext* context,
179*c8dee2aaSAndroid Build Coastguard Worker const GrSurfaceProxyView& writeView,
180*c8dee2aaSAndroid Build Coastguard Worker GrAppliedClip* clip,
181*c8dee2aaSAndroid Build Coastguard Worker const GrDstProxyView& dstProxyView,
182*c8dee2aaSAndroid Build Coastguard Worker GrXferBarrierFlags renderPassXferBarriers,
183*c8dee2aaSAndroid Build Coastguard Worker GrLoadOp colorLoadOp) final {
184*c8dee2aaSAndroid Build Coastguard Worker SkArenaAlloc* arena = context->priv().recordTimeAllocator();
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker // DMSAA is not supported on DDL.
187*c8dee2aaSAndroid Build Coastguard Worker bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;
188*c8dee2aaSAndroid Build Coastguard Worker
189*c8dee2aaSAndroid Build Coastguard Worker // This is equivalent to a GrOpFlushState::detachAppliedClip
190*c8dee2aaSAndroid Build Coastguard Worker GrAppliedClip appliedClip = clip ? std::move(*clip) : GrAppliedClip::Disabled();
191*c8dee2aaSAndroid Build Coastguard Worker
192*c8dee2aaSAndroid Build Coastguard Worker fProgramInfo = this->createProgramInfo(context->priv().caps(),
193*c8dee2aaSAndroid Build Coastguard Worker arena,
194*c8dee2aaSAndroid Build Coastguard Worker writeView,
195*c8dee2aaSAndroid Build Coastguard Worker usesMSAASurface,
196*c8dee2aaSAndroid Build Coastguard Worker std::move(appliedClip),
197*c8dee2aaSAndroid Build Coastguard Worker dstProxyView,
198*c8dee2aaSAndroid Build Coastguard Worker renderPassXferBarriers,
199*c8dee2aaSAndroid Build Coastguard Worker colorLoadOp);
200*c8dee2aaSAndroid Build Coastguard Worker
201*c8dee2aaSAndroid Build Coastguard Worker context->priv().recordProgramInfo(fProgramInfo);
202*c8dee2aaSAndroid Build Coastguard Worker }
203*c8dee2aaSAndroid Build Coastguard Worker
makeVB(GrOpFlushState * flushState,const SkRect rect)204*c8dee2aaSAndroid Build Coastguard Worker template <typename V> void makeVB(GrOpFlushState* flushState, const SkRect rect) {
205*c8dee2aaSAndroid Build Coastguard Worker V v[4];
206*c8dee2aaSAndroid Build Coastguard Worker v[0].p = {rect.left() , rect.top() };
207*c8dee2aaSAndroid Build Coastguard Worker v[1].p = {rect.right(), rect.top() };
208*c8dee2aaSAndroid Build Coastguard Worker v[2].p = {rect.left() , rect.bottom()};
209*c8dee2aaSAndroid Build Coastguard Worker v[3].p = {rect.right(), rect.bottom()};
210*c8dee2aaSAndroid Build Coastguard Worker v[0].color = SK_ColorRED;
211*c8dee2aaSAndroid Build Coastguard Worker v[1].color = SK_ColorGREEN;
212*c8dee2aaSAndroid Build Coastguard Worker v[2].color = SK_ColorYELLOW;
213*c8dee2aaSAndroid Build Coastguard Worker v[3].color = SK_ColorMAGENTA;
214*c8dee2aaSAndroid Build Coastguard Worker fVertexBuffer = flushState->resourceProvider()->createBuffer(v,
215*c8dee2aaSAndroid Build Coastguard Worker sizeof(v),
216*c8dee2aaSAndroid Build Coastguard Worker GrGpuBufferType::kVertex,
217*c8dee2aaSAndroid Build Coastguard Worker kStatic_GrAccessPattern);
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker
onPrepare(GrOpFlushState * flushState)220*c8dee2aaSAndroid Build Coastguard Worker void onPrepare(GrOpFlushState* flushState) override {
221*c8dee2aaSAndroid Build Coastguard Worker if (fMode == AttrMode::kWacky) {
222*c8dee2aaSAndroid Build Coastguard Worker struct V {
223*c8dee2aaSAndroid Build Coastguard Worker SkPoint p;
224*c8dee2aaSAndroid Build Coastguard Worker uint32_t pad0;
225*c8dee2aaSAndroid Build Coastguard Worker uint32_t color;
226*c8dee2aaSAndroid Build Coastguard Worker uint32_t pad1;
227*c8dee2aaSAndroid Build Coastguard Worker };
228*c8dee2aaSAndroid Build Coastguard Worker SkRect rect {fRect.fLeft/2.f, fRect.fTop/2.f, fRect.fRight/2.f, fRect.fBottom/2.f};
229*c8dee2aaSAndroid Build Coastguard Worker this->makeVB<V>(flushState, rect);
230*c8dee2aaSAndroid Build Coastguard Worker } else {
231*c8dee2aaSAndroid Build Coastguard Worker struct V {
232*c8dee2aaSAndroid Build Coastguard Worker SkPoint p;
233*c8dee2aaSAndroid Build Coastguard Worker uint32_t color;
234*c8dee2aaSAndroid Build Coastguard Worker };
235*c8dee2aaSAndroid Build Coastguard Worker this->makeVB<V>(flushState, fRect);
236*c8dee2aaSAndroid Build Coastguard Worker }
237*c8dee2aaSAndroid Build Coastguard Worker }
238*c8dee2aaSAndroid Build Coastguard Worker
onExecute(GrOpFlushState * flushState,const SkRect & chainBounds)239*c8dee2aaSAndroid Build Coastguard Worker void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
240*c8dee2aaSAndroid Build Coastguard Worker if (!fVertexBuffer) {
241*c8dee2aaSAndroid Build Coastguard Worker return;
242*c8dee2aaSAndroid Build Coastguard Worker }
243*c8dee2aaSAndroid Build Coastguard Worker
244*c8dee2aaSAndroid Build Coastguard Worker if (!fProgramInfo) {
245*c8dee2aaSAndroid Build Coastguard Worker fProgramInfo = this->createProgramInfo(flushState);
246*c8dee2aaSAndroid Build Coastguard Worker }
247*c8dee2aaSAndroid Build Coastguard Worker
248*c8dee2aaSAndroid Build Coastguard Worker flushState->bindPipeline(*fProgramInfo, fRect);
249*c8dee2aaSAndroid Build Coastguard Worker flushState->bindBuffers(nullptr, nullptr, std::move(fVertexBuffer));
250*c8dee2aaSAndroid Build Coastguard Worker flushState->draw(4, 0);
251*c8dee2aaSAndroid Build Coastguard Worker }
252*c8dee2aaSAndroid Build Coastguard Worker
253*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrBuffer> fVertexBuffer;
254*c8dee2aaSAndroid Build Coastguard Worker const AttrMode fMode;
255*c8dee2aaSAndroid Build Coastguard Worker const SkRect fRect;
256*c8dee2aaSAndroid Build Coastguard Worker
257*c8dee2aaSAndroid Build Coastguard Worker // The program info (and both the GrPipeline and GrGeometryProcessor it relies on), when
258*c8dee2aaSAndroid Build Coastguard Worker // allocated, are allocated in either the ddl-record-time or flush-time arena. It is the
259*c8dee2aaSAndroid Build Coastguard Worker // arena's job to free up their memory so we just have a bare programInfo pointer here. We
260*c8dee2aaSAndroid Build Coastguard Worker // don't even store the GrPipeline and GrGeometryProcessor pointers here bc they are
261*c8dee2aaSAndroid Build Coastguard Worker // guaranteed to have the same lifetime as the program info.
262*c8dee2aaSAndroid Build Coastguard Worker GrProgramInfo* fProgramInfo = nullptr;
263*c8dee2aaSAndroid Build Coastguard Worker
264*c8dee2aaSAndroid Build Coastguard Worker friend class ::GrOp; // for ctor
265*c8dee2aaSAndroid Build Coastguard Worker
266*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GrDrawOp;
267*c8dee2aaSAndroid Build Coastguard Worker };
268*c8dee2aaSAndroid Build Coastguard Worker
269*c8dee2aaSAndroid Build Coastguard Worker } // namespace
270*c8dee2aaSAndroid Build Coastguard Worker
271*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
272*c8dee2aaSAndroid Build Coastguard Worker
273*c8dee2aaSAndroid Build Coastguard Worker /**
274*c8dee2aaSAndroid Build Coastguard Worker * This is a GPU-backend specific test that exercises explicit and implicit attribute offsets and
275*c8dee2aaSAndroid Build Coastguard Worker * strides.
276*c8dee2aaSAndroid Build Coastguard Worker */
277*c8dee2aaSAndroid Build Coastguard Worker class AttributesGM : public GpuGM {
getName() const278*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("attributes"); }
getISize()279*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return {120, 340}; }
280*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(GrRecordingContext*, SkCanvas*, SkString* errorMsg) override;
281*c8dee2aaSAndroid Build Coastguard Worker };
282*c8dee2aaSAndroid Build Coastguard Worker
onDraw(GrRecordingContext * rc,SkCanvas * canvas,SkString * errorMsg)283*c8dee2aaSAndroid Build Coastguard Worker DrawResult AttributesGM::onDraw(GrRecordingContext* rc, SkCanvas* canvas, SkString* errorMsg) {
284*c8dee2aaSAndroid Build Coastguard Worker auto sdc = skgpu::ganesh::TopDeviceSurfaceDrawContext(canvas);
285*c8dee2aaSAndroid Build Coastguard Worker if (!sdc) {
286*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = kErrorMsg_DrawSkippedGpuOnly;
287*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip;
288*c8dee2aaSAndroid Build Coastguard Worker }
289*c8dee2aaSAndroid Build Coastguard Worker
290*c8dee2aaSAndroid Build Coastguard Worker sdc->clear(SK_PMColor4fBLACK);
291*c8dee2aaSAndroid Build Coastguard Worker
292*c8dee2aaSAndroid Build Coastguard Worker // Draw the test directly to the frame buffer.
293*c8dee2aaSAndroid Build Coastguard Worker auto r = SkRect::MakeXYWH(10, 10, 100, 100);
294*c8dee2aaSAndroid Build Coastguard Worker for (AttrMode m : {AttrMode::kAuto, AttrMode::kManual, AttrMode::kWacky}) {
295*c8dee2aaSAndroid Build Coastguard Worker sdc->addDrawOp(AttributeTestOp::Make(rc, m, r));
296*c8dee2aaSAndroid Build Coastguard Worker r.offset(0, 110);
297*c8dee2aaSAndroid Build Coastguard Worker }
298*c8dee2aaSAndroid Build Coastguard Worker
299*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
300*c8dee2aaSAndroid Build Coastguard Worker }
301*c8dee2aaSAndroid Build Coastguard Worker
302*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////////
303*c8dee2aaSAndroid Build Coastguard Worker
304*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new AttributesGM(); )
305*c8dee2aaSAndroid Build Coastguard Worker
306*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm
307