1 /*
2 * Copyright 2013 Google Inc.
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 "src/gpu/GrShaderCaps.h"
9 #include "src/gpu/effects/GrBezierEffect.h"
10 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
11 #include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
12 #include "src/gpu/glsl/GrGLSLProgramDataManager.h"
13 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
14 #include "src/gpu/glsl/GrGLSLUtil.h"
15 #include "src/gpu/glsl/GrGLSLVarying.h"
16 #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
17
18 class GrGLConicEffect : public GrGLSLGeometryProcessor {
19 public:
20 GrGLConicEffect(const GrGeometryProcessor&);
21
22 void onEmitCode(EmitArgs&, GrGPArgs*) override;
23
24 static inline void GenKey(const GrGeometryProcessor&,
25 const GrShaderCaps&,
26 GrProcessorKeyBuilder*);
27
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & primProc,const CoordTransformRange & transformRange)28 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
29 const CoordTransformRange& transformRange) override {
30 const GrConicEffect& ce = primProc.cast<GrConicEffect>();
31
32 if (!ce.viewMatrix().isIdentity() &&
33 !SkMatrixPriv::CheapEqual(fViewMatrix, ce.viewMatrix()))
34 {
35 fViewMatrix = ce.viewMatrix();
36 float viewMatrix[3 * 3];
37 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
38 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
39 }
40
41 if (ce.color() != fColor) {
42 pdman.set4fv(fColorUniform, 1, ce.color().vec());
43 fColor = ce.color();
44 }
45
46 if (ce.coverageScale() != 0xff && ce.coverageScale() != fCoverageScale) {
47 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale()));
48 fCoverageScale = ce.coverageScale();
49 }
50 this->setTransformDataHelper(ce.localMatrix(), pdman, transformRange);
51 }
52
53 private:
54 SkMatrix fViewMatrix;
55 SkPMColor4f fColor;
56 uint8_t fCoverageScale;
57 GrClipEdgeType fEdgeType;
58 UniformHandle fColorUniform;
59 UniformHandle fCoverageScaleUniform;
60 UniformHandle fViewMatrixUniform;
61
62 typedef GrGLSLGeometryProcessor INHERITED;
63 };
64
GrGLConicEffect(const GrGeometryProcessor & processor)65 GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor)
66 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) {
67 const GrConicEffect& ce = processor.cast<GrConicEffect>();
68 fEdgeType = ce.getEdgeType();
69 }
70
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)71 void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
72 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
73 const GrConicEffect& gp = args.fGP.cast<GrConicEffect>();
74 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
75 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
76
77 // emit attributes
78 varyingHandler->emitAttributes(gp);
79
80 GrGLSLVarying v(kFloat4_GrSLType);
81 varyingHandler->addVarying("ConicCoeffs", &v);
82 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs().name());
83
84 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
85 // Setup pass through color
86 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
87
88 // Setup position
89 this->writeOutputPosition(vertBuilder,
90 uniformHandler,
91 gpArgs,
92 gp.inPosition().name(),
93 gp.viewMatrix(),
94 &fViewMatrixUniform);
95
96 // emit transforms with position
97 this->emitTransforms(vertBuilder,
98 varyingHandler,
99 uniformHandler,
100 gp.inPosition().asShaderVar(),
101 gp.localMatrix(),
102 args.fFPCoordTransformHandler);
103
104 // TODO: we should check on the number of bits float and half provide and use the smallest one
105 // that suffices. Additionally we should assert that the upstream code only lets us get here if
106 // either float or half provides the required number of bits.
107
108 GrShaderVar edgeAlpha("edgeAlpha", kHalf_GrSLType, 0);
109 GrShaderVar dklmdx("dklmdx", kFloat3_GrSLType, 0);
110 GrShaderVar dklmdy("dklmdy", kFloat3_GrSLType, 0);
111 GrShaderVar dfdx("dfdx", kFloat_GrSLType, 0);
112 GrShaderVar dfdy("dfdy", kFloat_GrSLType, 0);
113 GrShaderVar gF("gF", kFloat2_GrSLType, 0);
114 GrShaderVar gFM("gFM", kFloat_GrSLType, 0);
115 GrShaderVar func("func", kFloat_GrSLType, 0);
116
117 fragBuilder->declAppend(edgeAlpha);
118 fragBuilder->declAppend(dklmdx);
119 fragBuilder->declAppend(dklmdy);
120 fragBuilder->declAppend(dfdx);
121 fragBuilder->declAppend(dfdy);
122 fragBuilder->declAppend(gF);
123 fragBuilder->declAppend(gFM);
124 fragBuilder->declAppend(func);
125
126 switch (fEdgeType) {
127 case GrClipEdgeType::kHairlineAA: {
128 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
129 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
130 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
131 dfdx.c_str(),
132 v.fsIn(), dklmdx.c_str(),
133 v.fsIn(), dklmdx.c_str(),
134 v.fsIn(), dklmdx.c_str());
135 fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
136 dfdy.c_str(),
137 v.fsIn(), dklmdy.c_str(),
138 v.fsIn(), dklmdy.c_str(),
139 v.fsIn(), dklmdy.c_str());
140 fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(),
141 dfdy.c_str());
142 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
143 gFM.c_str(), gF.c_str(), gF.c_str());
144 fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;",
145 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
146 fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
147 fragBuilder->codeAppendf("%s = half(%s / %s);",
148 edgeAlpha.c_str(), func.c_str(), gFM.c_str());
149 fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
150 edgeAlpha.c_str(), edgeAlpha.c_str());
151 // Add line below for smooth cubic ramp
152 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
153 break;
154 }
155 case GrClipEdgeType::kFillAA: {
156 fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
157 fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
158 fragBuilder->codeAppendf("%s ="
159 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
160 dfdx.c_str(),
161 v.fsIn(), dklmdx.c_str(),
162 v.fsIn(), dklmdx.c_str(),
163 v.fsIn(), dklmdx.c_str());
164 fragBuilder->codeAppendf("%s ="
165 "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
166 dfdy.c_str(),
167 v.fsIn(), dklmdy.c_str(),
168 v.fsIn(), dklmdy.c_str(),
169 v.fsIn(), dklmdy.c_str());
170 fragBuilder->codeAppendf("%s = float2(%s, %s);", gF.c_str(), dfdx.c_str(),
171 dfdy.c_str());
172 fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
173 gFM.c_str(), gF.c_str(), gF.c_str());
174 fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
175 func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
176 fragBuilder->codeAppendf("%s = half(%s / %s);",
177 edgeAlpha.c_str(), func.c_str(), gFM.c_str());
178 fragBuilder->codeAppendf("%s = saturate(0.5 - %s);",
179 edgeAlpha.c_str(), edgeAlpha.c_str());
180 // Add line below for smooth cubic ramp
181 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
182 break;
183 }
184 case GrClipEdgeType::kFillBW: {
185 fragBuilder->codeAppendf("%s = half(%s.x * %s.x - %s.y * %s.z);",
186 edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
187 fragBuilder->codeAppendf("%s = half(%s < 0.0);",
188 edgeAlpha.c_str(), edgeAlpha.c_str());
189 break;
190 }
191 default:
192 SK_ABORT("Shouldn't get here");
193 }
194
195 // TODO should we really be doing this?
196 if (gp.coverageScale() != 0xff) {
197 const char* coverageScale;
198 fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
199 kFloat_GrSLType,
200 "Coverage",
201 &coverageScale);
202 fragBuilder->codeAppendf("%s = half4(half(%s) * %s);",
203 args.fOutputCoverage, coverageScale, edgeAlpha.c_str());
204 } else {
205 fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
206 }
207 }
208
GenKey(const GrGeometryProcessor & gp,const GrShaderCaps &,GrProcessorKeyBuilder * b)209 void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp,
210 const GrShaderCaps&,
211 GrProcessorKeyBuilder* b) {
212 const GrConicEffect& ce = gp.cast<GrConicEffect>();
213 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
214 key |= 0xff != ce.coverageScale() ? 0x8 : 0x0;
215 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
216 key |= ComputePosKey(ce.viewMatrix()) << 5;
217 b->add32(key);
218 }
219
220 //////////////////////////////////////////////////////////////////////////////
221
222 constexpr GrPrimitiveProcessor::Attribute GrConicEffect::kAttributes[];
223
~GrConicEffect()224 GrConicEffect::~GrConicEffect() {}
225
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const226 void GrConicEffect::getGLSLProcessorKey(const GrShaderCaps& caps,
227 GrProcessorKeyBuilder* b) const {
228 GrGLConicEffect::GenKey(*this, caps, b);
229 }
230
createGLSLInstance(const GrShaderCaps &) const231 GrGLSLPrimitiveProcessor* GrConicEffect::createGLSLInstance(const GrShaderCaps&) const {
232 return new GrGLConicEffect(*this);
233 }
234
GrConicEffect(const SkPMColor4f & color,const SkMatrix & viewMatrix,uint8_t coverage,GrClipEdgeType edgeType,const SkMatrix & localMatrix,bool usesLocalCoords)235 GrConicEffect::GrConicEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage,
236 GrClipEdgeType edgeType, const SkMatrix& localMatrix,
237 bool usesLocalCoords)
238 : INHERITED(kGrConicEffect_ClassID)
239 , fColor(color)
240 , fViewMatrix(viewMatrix)
241 , fLocalMatrix(viewMatrix)
242 , fUsesLocalCoords(usesLocalCoords)
243 , fCoverageScale(coverage)
244 , fEdgeType(edgeType) {
245 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
246 }
247
248 //////////////////////////////////////////////////////////////////////////////
249
250 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect);
251
252 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)253 GrGeometryProcessor* GrConicEffect::TestCreate(GrProcessorTestData* d) {
254 GrGeometryProcessor* gp;
255 do {
256 GrClipEdgeType edgeType =
257 static_cast<GrClipEdgeType>(
258 d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));
259 gp = GrConicEffect::Make(d->allocator(),
260 SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
261 GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(),
262 GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
263 } while (nullptr == gp);
264 return gp;
265 }
266 #endif
267
268 //////////////////////////////////////////////////////////////////////////////
269 // Quad
270 //////////////////////////////////////////////////////////////////////////////
271
272 class GrGLQuadEffect : public GrGLSLGeometryProcessor {
273 public:
274 GrGLQuadEffect(const GrGeometryProcessor&);
275
276 void onEmitCode(EmitArgs&, GrGPArgs*) override;
277
278 static inline void GenKey(const GrGeometryProcessor&,
279 const GrShaderCaps&,
280 GrProcessorKeyBuilder*);
281
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor & primProc,const CoordTransformRange & transformRange)282 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
283 const CoordTransformRange& transformRange) override {
284 const GrQuadEffect& qe = primProc.cast<GrQuadEffect>();
285
286 if (!qe.viewMatrix().isIdentity() &&
287 !SkMatrixPriv::CheapEqual(fViewMatrix, qe.viewMatrix()))
288 {
289 fViewMatrix = qe.viewMatrix();
290 float viewMatrix[3 * 3];
291 GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
292 pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
293 }
294
295 if (qe.color() != fColor) {
296 pdman.set4fv(fColorUniform, 1, qe.color().vec());
297 fColor = qe.color();
298 }
299
300 if (qe.coverageScale() != 0xff && qe.coverageScale() != fCoverageScale) {
301 pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale()));
302 fCoverageScale = qe.coverageScale();
303 }
304 this->setTransformDataHelper(qe.localMatrix(), pdman, transformRange);
305 }
306
307 private:
308 SkMatrix fViewMatrix;
309 SkPMColor4f fColor;
310 uint8_t fCoverageScale;
311 GrClipEdgeType fEdgeType;
312 UniformHandle fColorUniform;
313 UniformHandle fCoverageScaleUniform;
314 UniformHandle fViewMatrixUniform;
315
316 typedef GrGLSLGeometryProcessor INHERITED;
317 };
318
GrGLQuadEffect(const GrGeometryProcessor & processor)319 GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor)
320 : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(SK_PMColor4fILLEGAL), fCoverageScale(0xff) {
321 const GrQuadEffect& ce = processor.cast<GrQuadEffect>();
322 fEdgeType = ce.getEdgeType();
323 }
324
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)325 void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
326 GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
327 const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>();
328 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
329 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
330
331 // emit attributes
332 varyingHandler->emitAttributes(gp);
333
334 GrGLSLVarying v(kHalf4_GrSLType);
335 varyingHandler->addVarying("HairQuadEdge", &v);
336 vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge().name());
337
338 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
339 // Setup pass through color
340 this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
341
342 // Setup position
343 this->writeOutputPosition(vertBuilder,
344 uniformHandler,
345 gpArgs,
346 gp.inPosition().name(),
347 gp.viewMatrix(),
348 &fViewMatrixUniform);
349
350 // emit transforms with position
351 this->emitTransforms(vertBuilder,
352 varyingHandler,
353 uniformHandler,
354 gp.inPosition().asShaderVar(),
355 gp.localMatrix(),
356 args.fFPCoordTransformHandler);
357
358 fragBuilder->codeAppendf("half edgeAlpha;");
359
360 switch (fEdgeType) {
361 case GrClipEdgeType::kHairlineAA: {
362 fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
363 fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
364 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
365 " 2.0 * %s.x * duvdy.x - duvdy.y);",
366 v.fsIn(), v.fsIn());
367 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
368 v.fsIn(), v.fsIn(), v.fsIn());
369 fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));");
370 fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);");
371 // Add line below for smooth cubic ramp
372 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
373 break;
374 }
375 case GrClipEdgeType::kFillAA: {
376 fragBuilder->codeAppendf("half2 duvdx = half2(dFdx(%s.xy));", v.fsIn());
377 fragBuilder->codeAppendf("half2 duvdy = half2(dFdy(%s.xy));", v.fsIn());
378 fragBuilder->codeAppendf("half2 gF = half2(2.0 * %s.x * duvdx.x - duvdx.y,"
379 " 2.0 * %s.x * duvdy.x - duvdy.y);",
380 v.fsIn(), v.fsIn());
381 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
382 v.fsIn(), v.fsIn(), v.fsIn());
383 fragBuilder->codeAppend("edgeAlpha = edgeAlpha / sqrt(dot(gF, gF));");
384 fragBuilder->codeAppend("edgeAlpha = saturate(0.5 - edgeAlpha);");
385 // Add line below for smooth cubic ramp
386 // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
387 break;
388 }
389 case GrClipEdgeType::kFillBW: {
390 fragBuilder->codeAppendf("edgeAlpha = half(%s.x * %s.x - %s.y);",
391 v.fsIn(), v.fsIn(), v.fsIn());
392 fragBuilder->codeAppend("edgeAlpha = half(edgeAlpha < 0.0);");
393 break;
394 }
395 default:
396 SK_ABORT("Shouldn't get here");
397 }
398
399 if (0xff != gp.coverageScale()) {
400 const char* coverageScale;
401 fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
402 kHalf_GrSLType,
403 "Coverage",
404 &coverageScale);
405 fragBuilder->codeAppendf("%s = half4(%s * edgeAlpha);", args.fOutputCoverage,
406 coverageScale);
407 } else {
408 fragBuilder->codeAppendf("%s = half4(edgeAlpha);", args.fOutputCoverage);
409 }
410 }
411
GenKey(const GrGeometryProcessor & gp,const GrShaderCaps &,GrProcessorKeyBuilder * b)412 void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp,
413 const GrShaderCaps&,
414 GrProcessorKeyBuilder* b) {
415 const GrQuadEffect& ce = gp.cast<GrQuadEffect>();
416 uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
417 key |= ce.coverageScale() != 0xff ? 0x8 : 0x0;
418 key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
419 key |= ComputePosKey(ce.viewMatrix()) << 5;
420 b->add32(key);
421 }
422
423 //////////////////////////////////////////////////////////////////////////////
424
425 constexpr GrPrimitiveProcessor::Attribute GrQuadEffect::kAttributes[];
426
~GrQuadEffect()427 GrQuadEffect::~GrQuadEffect() {}
428
getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const429 void GrQuadEffect::getGLSLProcessorKey(const GrShaderCaps& caps,
430 GrProcessorKeyBuilder* b) const {
431 GrGLQuadEffect::GenKey(*this, caps, b);
432 }
433
createGLSLInstance(const GrShaderCaps &) const434 GrGLSLPrimitiveProcessor* GrQuadEffect::createGLSLInstance(const GrShaderCaps&) const {
435 return new GrGLQuadEffect(*this);
436 }
437
GrQuadEffect(const SkPMColor4f & color,const SkMatrix & viewMatrix,uint8_t coverage,GrClipEdgeType edgeType,const SkMatrix & localMatrix,bool usesLocalCoords)438 GrQuadEffect::GrQuadEffect(const SkPMColor4f& color, const SkMatrix& viewMatrix, uint8_t coverage,
439 GrClipEdgeType edgeType, const SkMatrix& localMatrix,
440 bool usesLocalCoords)
441 : INHERITED(kGrQuadEffect_ClassID)
442 , fColor(color)
443 , fViewMatrix(viewMatrix)
444 , fLocalMatrix(localMatrix)
445 , fUsesLocalCoords(usesLocalCoords)
446 , fCoverageScale(coverage)
447 , fEdgeType(edgeType) {
448 this->setVertexAttributes(kAttributes, SK_ARRAY_COUNT(kAttributes));
449 }
450
451 //////////////////////////////////////////////////////////////////////////////
452
453 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect);
454
455 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)456 GrGeometryProcessor* GrQuadEffect::TestCreate(GrProcessorTestData* d) {
457 GrGeometryProcessor* gp;
458 do {
459 GrClipEdgeType edgeType = static_cast<GrClipEdgeType>(
460 d->fRandom->nextULessThan(kGrClipEdgeTypeCnt));
461 gp = GrQuadEffect::Make(d->allocator(),
462 SkPMColor4f::FromBytes_RGBA(GrRandomColor(d->fRandom)),
463 GrTest::TestMatrix(d->fRandom), edgeType, *d->caps(),
464 GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
465 } while (nullptr == gp);
466 return gp;
467 }
468 #endif
469