1 /*
2 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "tools/gpu/TestOps.h"
9
10 #include "src/core/SkPointPriv.h"
11 #include "src/gpu/BufferWriter.h"
12 #include "src/gpu/KeyBuilder.h"
13 #include "src/gpu/ganesh/GrCaps.h"
14 #include "src/gpu/ganesh/GrGeometryProcessor.h"
15 #include "src/gpu/ganesh/GrMemoryPool.h"
16 #include "src/gpu/ganesh/GrOpFlushState.h"
17 #include "src/gpu/ganesh/GrProgramInfo.h"
18 #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
19 #include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
20 #include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
21 #include "src/gpu/ganesh/ops/GrMeshDrawOp.h"
22 #include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelper.h"
23
24 namespace {
25
26 class GP : public GrGeometryProcessor {
27 public:
GP(const SkMatrix & localMatrix,bool wideColor)28 GP(const SkMatrix& localMatrix, bool wideColor)
29 : GrGeometryProcessor(kTestRectOp_ClassID), fLocalMatrix(localMatrix) {
30 fInColor = MakeColorAttribute("color", wideColor);
31 this->setVertexAttributesWithImplicitOffsets(&fInPosition, 3);
32 }
33
name() const34 const char* name() const override { return "TestRectOp::GP"; }
35
makeProgramImpl(const GrShaderCaps &) const36 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override {
37 class Impl : public ProgramImpl {
38 public:
39 void setData(const GrGLSLProgramDataManager& pdman,
40 const GrShaderCaps& shaderCaps,
41 const GrGeometryProcessor& geomProc) override {
42 const auto& gp = geomProc.cast<GP>();
43 SetTransform(pdman, shaderCaps, fLocalMatrixUni, gp.fLocalMatrix);
44 }
45
46 private:
47 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
48 const auto& gp = args.fGeomProc.cast<GP>();
49 args.fVaryingHandler->emitAttributes(gp);
50 GrGLSLVarying colorVarying(SkSLType::kHalf4);
51 args.fVaryingHandler->addVarying("color", &colorVarying,
52 GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
53 args.fVertBuilder->codeAppendf("%s = %s;", colorVarying.vsOut(), gp.fInColor.name());
54 args.fFragBuilder->codeAppendf("half4 %s = %s;",
55 args.fOutputColor, colorVarying.fsIn());
56 args.fFragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
57 WriteOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
58 WriteLocalCoord(args.fVertBuilder,
59 args.fUniformHandler,
60 *args.fShaderCaps,
61 gpArgs,
62 gp.fInLocalCoords.asShaderVar(),
63 gp.fLocalMatrix,
64 &fLocalMatrixUni);
65 }
66
67 UniformHandle fLocalMatrixUni;
68 };
69
70 return std::make_unique<Impl>();
71 }
72
addToKey(const GrShaderCaps & shaderCaps,skgpu::KeyBuilder * b) const73 void addToKey(const GrShaderCaps& shaderCaps, skgpu::KeyBuilder* b) const override {
74 b->add32(ProgramImpl::ComputeMatrixKey(shaderCaps, fLocalMatrix));
75 }
76
wideColor() const77 bool wideColor() const { return fInColor.cpuType() != kUByte4_norm_GrVertexAttribType; }
78
79 private:
80 Attribute fInPosition = { "inPosition", kFloat2_GrVertexAttribType, SkSLType::kFloat2};
81 Attribute fInLocalCoords = {"inLocalCoords", kFloat2_GrVertexAttribType, SkSLType::kFloat2};
82 Attribute fInColor;
83
84 SkMatrix fLocalMatrix;
85 };
86
87 class TestRectOp final : public GrMeshDrawOp {
88 public:
89 static GrOp::Owner Make(GrRecordingContext*,
90 GrPaint&&,
91 const SkRect& drawRect,
92 const SkRect& localRect,
93 const SkMatrix& localM);
94
name() const95 const char* name() const override { return "TestRectOp"; }
96
fixedFunctionFlags() const97 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
98
99 GrProcessorSet::Analysis finalize(const GrCaps&,
100 const GrAppliedClip*,
101 GrClampType) override;
102
visitProxies(const GrVisitProxyFunc & func) const103 void visitProxies(const GrVisitProxyFunc& func) const override {
104 if (fProgramInfo) {
105 fProgramInfo->visitFPProxies(func);
106 } else {
107 fProcessorSet.visitProxies(func);
108 }
109 }
110
111 private:
112 DEFINE_OP_CLASS_ID
113
114 TestRectOp(const GrCaps*,
115 GrPaint&&,
116 const SkRect& drawRect,
117 const SkRect& localRect,
118 const SkMatrix& localMatrix);
119
programInfo()120 GrProgramInfo* programInfo() override { return fProgramInfo; }
121 void onCreateProgramInfo(const GrCaps*,
122 SkArenaAlloc*,
123 const GrSurfaceProxyView& writeView,
124 bool usesMSAASurface,
125 GrAppliedClip&&,
126 const GrDstProxyView&,
127 GrXferBarrierFlags renderPassXferBarriers,
128 GrLoadOp colorLoadOp) override;
129
130 void onPrepareDraws(GrMeshDrawTarget*) override;
131 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
132
133 SkRect fDrawRect;
134 SkRect fLocalRect;
135 SkPMColor4f fColor;
136 GP fGP;
137 GrProcessorSet fProcessorSet;
138
139 // If this op is prePrepared the created programInfo will be stored here for use in
140 // onExecute. In the prePrepared case it will have been stored in the record-time arena.
141 GrProgramInfo* fProgramInfo = nullptr;
142 GrSimpleMesh* fMesh = nullptr;
143
144 friend class ::GrOp;
145 };
146
Make(GrRecordingContext * context,GrPaint && paint,const SkRect & drawRect,const SkRect & localRect,const SkMatrix & localM)147 GrOp::Owner TestRectOp::Make(GrRecordingContext* context,
148 GrPaint&& paint,
149 const SkRect& drawRect,
150 const SkRect& localRect,
151 const SkMatrix& localM) {
152 const auto* caps = context->priv().caps();
153 return GrOp::Make<TestRectOp>(context, caps, std::move(paint), drawRect, localRect, localM);
154 }
155
finalize(const GrCaps & caps,const GrAppliedClip * clip,GrClampType clampType)156 GrProcessorSet::Analysis TestRectOp::finalize(const GrCaps& caps,
157 const GrAppliedClip* clip,
158 GrClampType clampType) {
159 return fProcessorSet.finalize(GrProcessorAnalysisColor::Opaque::kYes,
160 GrProcessorAnalysisCoverage::kSingleChannel, clip,
161 &GrUserStencilSettings::kUnused, caps, clampType, &fColor);
162 }
163
use_wide_color(const GrPaint & paint,const GrCaps * caps)164 static bool use_wide_color(const GrPaint& paint, const GrCaps* caps) {
165 return !paint.getColor4f().fitsInBytes() && caps->halfFloatVertexAttributeSupport();
166 }
TestRectOp(const GrCaps * caps,GrPaint && paint,const SkRect & drawRect,const SkRect & localRect,const SkMatrix & localMatrix)167 TestRectOp::TestRectOp(const GrCaps* caps,
168 GrPaint&& paint,
169 const SkRect& drawRect,
170 const SkRect& localRect,
171 const SkMatrix& localMatrix)
172 : GrMeshDrawOp(ClassID())
173 , fDrawRect(drawRect)
174 , fLocalRect(localRect)
175 , fColor(paint.getColor4f())
176 , fGP(localMatrix, use_wide_color(paint, caps))
177 , fProcessorSet(std::move(paint)) {
178 this->setBounds(drawRect.makeSorted(), HasAABloat::kNo, IsHairline::kNo);
179 }
180
onCreateProgramInfo(const GrCaps * caps,SkArenaAlloc * arena,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip && appliedClip,const GrDstProxyView & dstProxyView,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)181 void TestRectOp::onCreateProgramInfo(const GrCaps* caps,
182 SkArenaAlloc* arena,
183 const GrSurfaceProxyView& writeView,
184 bool usesMSAASurface,
185 GrAppliedClip&& appliedClip,
186 const GrDstProxyView& dstProxyView,
187 GrXferBarrierFlags renderPassXferBarriers,
188 GrLoadOp colorLoadOp) {
189 fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps,
190 arena,
191 writeView,
192 usesMSAASurface,
193 std::move(appliedClip),
194 dstProxyView,
195 &fGP,
196 std::move(fProcessorSet),
197 GrPrimitiveType::kTriangles,
198 renderPassXferBarriers,
199 colorLoadOp,
200 GrPipeline::InputFlags::kNone);
201 }
202
onPrepareDraws(GrMeshDrawTarget * target)203 void TestRectOp::onPrepareDraws(GrMeshDrawTarget* target) {
204 QuadHelper helper(target, fGP.vertexStride(), 1);
205 skgpu::VertexWriter writer{helper.vertices()};
206 auto pos = skgpu::VertexWriter::TriStripFromRect(fDrawRect);
207 auto local = skgpu::VertexWriter::TriStripFromRect(fLocalRect);
208 skgpu::VertexColor color(fColor, fGP.wideColor());
209 writer.writeQuad(pos, local, color);
210
211 fMesh = helper.mesh();
212 }
213
onExecute(GrOpFlushState * flushState,const SkRect & chainBounds)214 void TestRectOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
215 if (!fProgramInfo) {
216 this->createProgramInfo(flushState);
217 }
218
219 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
220 flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
221 flushState->drawMesh(*fMesh);
222 }
223
224 } // anonymous namespace
225
226 namespace sk_gpu_test::test_ops {
227
MakeRect(GrRecordingContext * context,GrPaint && paint,const SkRect & drawRect,const SkRect & localRect,const SkMatrix & localM)228 GrOp::Owner MakeRect(GrRecordingContext* context,
229 GrPaint&& paint,
230 const SkRect& drawRect,
231 const SkRect& localRect,
232 const SkMatrix& localM) {
233 return TestRectOp::Make(context, std::move(paint), drawRect, localRect, localM);
234 }
235
MakeRect(GrRecordingContext * context,std::unique_ptr<GrFragmentProcessor> fp,const SkRect & drawRect,const SkRect & localRect,const SkMatrix & localM)236 GrOp::Owner MakeRect(GrRecordingContext* context,
237 std::unique_ptr<GrFragmentProcessor> fp,
238 const SkRect& drawRect,
239 const SkRect& localRect,
240 const SkMatrix& localM) {
241 GrPaint paint;
242 paint.setColorFragmentProcessor(std::move(fp));
243 return TestRectOp::Make(context, std::move(paint), drawRect, localRect, localM);
244 }
245
MakeRect(GrRecordingContext * context,GrPaint && paint,const SkRect & rect)246 GrOp::Owner MakeRect(GrRecordingContext* context,
247 GrPaint&& paint,
248 const SkRect& rect) {
249 return TestRectOp::Make(context, std::move(paint), rect, rect, SkMatrix::I());
250 }
251
252 } // namespace sk_gpu_test::test_ops
253