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