1 /*
2 * Copyright 2016 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 "InstanceProcessor.h"
9
10 #include "GrContext.h"
11 #include "GrRenderTargetPriv.h"
12 #include "GrResourceCache.h"
13 #include "GrShaderCaps.h"
14 #include "glsl/GrGLSLGeometryProcessor.h"
15 #include "glsl/GrGLSLFragmentShaderBuilder.h"
16 #include "glsl/GrGLSLProgramBuilder.h"
17 #include "glsl/GrGLSLVarying.h"
18
19 namespace gr_instanced {
20
CheckSupport(const GrShaderCaps & shaderCaps,const GrCaps & caps)21 GrCaps::InstancedSupport InstanceProcessor::CheckSupport(const GrShaderCaps& shaderCaps,
22 const GrCaps& caps) {
23 if (!shaderCaps.canUseAnyFunctionInShader() ||
24 !shaderCaps.flatInterpolationSupport() ||
25 !shaderCaps.integerSupport() ||
26 0 == shaderCaps.maxVertexSamplers() ||
27 !caps.shaderCaps()->texelBufferSupport() ||
28 caps.maxVertexAttributes() < kNumAttribs) {
29 return GrCaps::InstancedSupport::kNone;
30 }
31 if (!caps.sampleLocationsSupport() ||
32 !shaderCaps.sampleVariablesSupport() ||
33 !shaderCaps.shaderDerivativeSupport()) {
34 return GrCaps::InstancedSupport::kBasic;
35 }
36 if (0 == caps.maxRasterSamples() ||
37 !shaderCaps.sampleMaskOverrideCoverageSupport()) {
38 return GrCaps::InstancedSupport::kMultisampled;
39 }
40 return GrCaps::InstancedSupport::kMixedSampled;
41 }
42
InstanceProcessor(OpInfo opInfo,GrBuffer * paramsBuffer)43 InstanceProcessor::InstanceProcessor(OpInfo opInfo, GrBuffer* paramsBuffer) : fOpInfo(opInfo) {
44 this->initClassID<InstanceProcessor>();
45
46 this->addVertexAttrib("shapeCoords", kVec2f_GrVertexAttribType, kHigh_GrSLPrecision);
47 this->addVertexAttrib("vertexAttrs", kInt_GrVertexAttribType);
48 this->addVertexAttrib("instanceInfo", kUint_GrVertexAttribType);
49 this->addVertexAttrib("shapeMatrixX", kVec3f_GrVertexAttribType, kHigh_GrSLPrecision);
50 this->addVertexAttrib("shapeMatrixY", kVec3f_GrVertexAttribType, kHigh_GrSLPrecision);
51 this->addVertexAttrib("color", kVec4f_GrVertexAttribType, kLow_GrSLPrecision);
52 this->addVertexAttrib("localRect", kVec4f_GrVertexAttribType, kHigh_GrSLPrecision);
53
54 GR_STATIC_ASSERT(0 == (int)Attrib::kShapeCoords);
55 GR_STATIC_ASSERT(1 == (int)Attrib::kVertexAttrs);
56 GR_STATIC_ASSERT(2 == (int)Attrib::kInstanceInfo);
57 GR_STATIC_ASSERT(3 == (int)Attrib::kShapeMatrixX);
58 GR_STATIC_ASSERT(4 == (int)Attrib::kShapeMatrixY);
59 GR_STATIC_ASSERT(5 == (int)Attrib::kColor);
60 GR_STATIC_ASSERT(6 == (int)Attrib::kLocalRect);
61 GR_STATIC_ASSERT(7 == kNumAttribs);
62
63 if (fOpInfo.fHasParams) {
64 SkASSERT(paramsBuffer);
65 fParamsAccess.reset(kRGBA_float_GrPixelConfig, paramsBuffer, kVertex_GrShaderFlag);
66 this->addBufferAccess(&fParamsAccess);
67 }
68
69 if (GrAATypeIsHW(fOpInfo.aaType())) {
70 if (!fOpInfo.isSimpleRects() || GrAAType::kMixedSamples == fOpInfo.aaType()) {
71 this->setWillUseSampleLocations();
72 }
73 }
74 }
75
76 class GLSLInstanceProcessor : public GrGLSLGeometryProcessor {
77 public:
78 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override;
79
80 private:
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor &,FPCoordTransformIter && transformIter)81 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
82 FPCoordTransformIter&& transformIter) override {
83 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
84 }
85
86 class VertexInputs;
87 class Backend;
88 class BackendNonAA;
89 class BackendCoverage;
90 class BackendMultisample;
91
92 typedef GrGLSLGeometryProcessor INHERITED;
93 };
94
createGLSLInstance(const GrShaderCaps &) const95 GrGLSLPrimitiveProcessor* InstanceProcessor::createGLSLInstance(const GrShaderCaps&) const {
96 return new GLSLInstanceProcessor();
97 }
98
99 class GLSLInstanceProcessor::VertexInputs {
100 public:
VertexInputs(const InstanceProcessor & instProc,GrGLSLVertexBuilder * vertexBuilder)101 VertexInputs(const InstanceProcessor& instProc, GrGLSLVertexBuilder* vertexBuilder)
102 : fInstProc(instProc),
103 fVertexBuilder(vertexBuilder) {
104 }
105
initParams(const TexelBufferHandle paramsBuffer)106 void initParams(const TexelBufferHandle paramsBuffer) {
107 fParamsBuffer = paramsBuffer;
108 fVertexBuilder->codeAppendf("highp int paramsIdx = int(%s & 0x%x);",
109 this->attr(Attrib::kInstanceInfo),
110 kParamsIdx_InfoMask);
111 }
112
attr(Attrib attr) const113 const char* attr(Attrib attr) const { return fInstProc.getAttrib((int)attr).fName; }
114
fetchNextParam(GrSLType type=kVec4f_GrSLType) const115 void fetchNextParam(GrSLType type = kVec4f_GrSLType) const {
116 SkASSERT(fParamsBuffer.isValid());
117 switch (type) {
118 case kVec2f_GrSLType: // fall through
119 case kVec3f_GrSLType: // fall through
120 case kVec4f_GrSLType:
121 break;
122 default:
123 fVertexBuilder->codeAppendf("%s(", GrGLSLTypeString(type));
124 }
125 fVertexBuilder->appendTexelFetch(fParamsBuffer, "paramsIdx++");
126 switch (type) {
127 case kVec2f_GrSLType:
128 fVertexBuilder->codeAppend(".xy");
129 break;
130 case kVec3f_GrSLType:
131 fVertexBuilder->codeAppend(".xyz");
132 break;
133 case kVec4f_GrSLType:
134 break;
135 default:
136 fVertexBuilder->codeAppend(")");
137 }
138 }
139
skipParams(unsigned n) const140 void skipParams(unsigned n) const {
141 SkASSERT(fParamsBuffer.isValid());
142 fVertexBuilder->codeAppendf("paramsIdx += %u;", n);
143 }
144
145 private:
146 const InstanceProcessor& fInstProc;
147 GrGLSLVertexBuilder* fVertexBuilder;
148 TexelBufferHandle fParamsBuffer;
149 };
150
151 class GLSLInstanceProcessor::Backend {
152 public:
153 static Backend* SK_WARN_UNUSED_RESULT Create(const GrPipeline&, OpInfo, const VertexInputs&);
~Backend()154 virtual ~Backend() {}
155
156 void init(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*);
157 virtual void setupRect(GrGLSLVertexBuilder*) = 0;
158 virtual void setupOval(GrGLSLVertexBuilder*) = 0;
159 void setupRRect(GrGLSLVertexBuilder*, int* usedShapeDefinitions);
160
161 void initInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*);
162 virtual void setupInnerRect(GrGLSLVertexBuilder*) = 0;
163 virtual void setupInnerOval(GrGLSLVertexBuilder*) = 0;
164 void setupInnerSimpleRRect(GrGLSLVertexBuilder*);
165
outShapeCoords()166 const char* outShapeCoords() {
167 return fModifiedShapeCoords ? fModifiedShapeCoords : fInputs.attr(Attrib::kShapeCoords);
168 }
169
170 void emitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char* outCoverage,
171 const char* outColor);
172
173 protected:
Backend(OpInfo opInfo,const VertexInputs & inputs)174 Backend(OpInfo opInfo, const VertexInputs& inputs)
175 : fOpInfo(opInfo)
176 , fInputs(inputs)
177 , fModifiesCoverage(false)
178 , fModifiesColor(false)
179 , fNeedsNeighborRadii(false)
180 , fColor(kVec4f_GrSLType)
181 , fTriangleIsArc(kInt_GrSLType)
182 , fArcCoords(kVec2f_GrSLType)
183 , fInnerShapeCoords(kVec2f_GrSLType)
184 , fInnerRRect(kVec4f_GrSLType)
185 , fModifiedShapeCoords(nullptr) {
186 if (fOpInfo.fShapeTypes & kRRect_ShapesMask) {
187 fModifiedShapeCoords = "adjustedShapeCoords";
188 }
189 }
190
191 virtual void onInit(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) = 0;
192 virtual void adjustRRectVertices(GrGLSLVertexBuilder*);
onSetupRRect(GrGLSLVertexBuilder *)193 virtual void onSetupRRect(GrGLSLVertexBuilder*) {}
194
195 virtual void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) = 0;
196 virtual void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) = 0;
197
198 virtual void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*,
199 const char* outCoverage, const char* outColor) = 0;
200
201 void setupSimpleRadii(GrGLSLVertexBuilder*);
202 void setupNinePatchRadii(GrGLSLVertexBuilder*);
203 void setupComplexRadii(GrGLSLVertexBuilder*);
204
205 const OpInfo fOpInfo;
206 const VertexInputs& fInputs;
207 bool fModifiesCoverage;
208 bool fModifiesColor;
209 bool fNeedsNeighborRadii;
210 GrGLSLVertToFrag fColor;
211 GrGLSLVertToFrag fTriangleIsArc;
212 GrGLSLVertToFrag fArcCoords;
213 GrGLSLVertToFrag fInnerShapeCoords;
214 GrGLSLVertToFrag fInnerRRect;
215 const char* fModifiedShapeCoords;
216 };
217
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)218 void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
219 const GrPipeline& pipeline = args.fVertBuilder->getProgramBuilder()->pipeline();
220 const InstanceProcessor& ip = args.fGP.cast<InstanceProcessor>();
221 GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
222 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
223 GrGLSLVertexBuilder* v = args.fVertBuilder;
224 GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
225
226 varyingHandler->emitAttributes(ip);
227
228 VertexInputs inputs(ip, v);
229 if (ip.opInfo().fHasParams) {
230 SkASSERT(1 == ip.numBuffers());
231 inputs.initParams(args.fTexelBuffers[0]);
232 }
233
234 if (!ip.opInfo().fHasPerspective) {
235 v->codeAppendf("mat2x3 shapeMatrix = mat2x3(%s, %s);",
236 inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
237 } else {
238 v->defineConstantf("int", "PERSPECTIVE_FLAG", "0x%x", kPerspective_InfoFlag);
239 v->codeAppendf("mat3 shapeMatrix = mat3(%s, %s, vec3(0, 0, 1));",
240 inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
241 v->codeAppendf("if (0 != (%s & PERSPECTIVE_FLAG)) {",
242 inputs.attr(Attrib::kInstanceInfo));
243 v->codeAppend ( "shapeMatrix[2] = ");
244 inputs.fetchNextParam(kVec3f_GrSLType);
245 v->codeAppend ( ";");
246 v->codeAppend ("}");
247 }
248
249 bool hasSingleShapeType = SkIsPow2(ip.opInfo().fShapeTypes);
250 if (!hasSingleShapeType) {
251 v->defineConstant("SHAPE_TYPE_BIT", kShapeType_InfoBit);
252 v->codeAppendf("uint shapeType = %s >> SHAPE_TYPE_BIT;",
253 inputs.attr(Attrib::kInstanceInfo));
254 }
255
256 std::unique_ptr<Backend> backend(Backend::Create(pipeline, ip.opInfo(), inputs));
257 backend->init(varyingHandler, v);
258
259 int usedShapeDefinitions = 0;
260
261 if (hasSingleShapeType || !(ip.opInfo().fShapeTypes & ~kRRect_ShapesMask)) {
262 if (kRect_ShapeFlag == ip.opInfo().fShapeTypes) {
263 backend->setupRect(v);
264 } else if (kOval_ShapeFlag == ip.opInfo().fShapeTypes) {
265 backend->setupOval(v);
266 } else {
267 backend->setupRRect(v, &usedShapeDefinitions);
268 }
269 } else {
270 if (ip.opInfo().fShapeTypes & kRRect_ShapesMask) {
271 v->codeAppend ("if (shapeType >= SIMPLE_R_RECT_SHAPE_TYPE) {");
272 backend->setupRRect(v, &usedShapeDefinitions);
273 v->codeAppend ("}");
274 usedShapeDefinitions |= kSimpleRRect_ShapeFlag;
275 }
276 if (ip.opInfo().fShapeTypes & kOval_ShapeFlag) {
277 if (ip.opInfo().fShapeTypes & kRect_ShapeFlag) {
278 if (ip.opInfo().fShapeTypes & kRRect_ShapesMask) {
279 v->codeAppend ("else ");
280 }
281 v->codeAppend ("if (OVAL_SHAPE_TYPE == shapeType) {");
282 usedShapeDefinitions |= kOval_ShapeFlag;
283 } else {
284 v->codeAppend ("else {");
285 }
286 backend->setupOval(v);
287 v->codeAppend ("}");
288 }
289 if (ip.opInfo().fShapeTypes & kRect_ShapeFlag) {
290 v->codeAppend ("else {");
291 backend->setupRect(v);
292 v->codeAppend ("}");
293 }
294 }
295
296 if (ip.opInfo().fInnerShapeTypes) {
297 bool hasSingleInnerShapeType = SkIsPow2(ip.opInfo().fInnerShapeTypes);
298 if (!hasSingleInnerShapeType) {
299 v->defineConstantf("int", "INNER_SHAPE_TYPE_MASK", "0x%x", kInnerShapeType_InfoMask);
300 v->defineConstant("INNER_SHAPE_TYPE_BIT", kInnerShapeType_InfoBit);
301 v->codeAppendf("uint innerShapeType = ((%s & INNER_SHAPE_TYPE_MASK) >> "
302 "INNER_SHAPE_TYPE_BIT);",
303 inputs.attr(Attrib::kInstanceInfo));
304 }
305 // Here we take advantage of the fact that outerRect == localRect in recordDRRect.
306 v->codeAppendf("vec4 outer = %s;", inputs.attr(Attrib::kLocalRect));
307 v->codeAppend ("vec4 inner = ");
308 inputs.fetchNextParam();
309 v->codeAppend (";");
310 // outer2Inner is a transform from shape coords to inner shape coords:
311 // e.g. innerShapeCoords = shapeCoords * outer2Inner.xy + outer2Inner.zw
312 v->codeAppend ("vec4 outer2Inner = vec4(outer.zw - outer.xy, "
313 "outer.xy + outer.zw - inner.xy - inner.zw) / "
314 "(inner.zw - inner.xy).xyxy;");
315 v->codeAppendf("vec2 innerShapeCoords = %s * outer2Inner.xy + outer2Inner.zw;",
316 backend->outShapeCoords());
317
318 backend->initInnerShape(varyingHandler, v);
319
320 SkASSERT(0 == (ip.opInfo().fInnerShapeTypes & kRRect_ShapesMask) ||
321 kSimpleRRect_ShapeFlag == (ip.opInfo().fInnerShapeTypes & kRRect_ShapesMask));
322
323 if (hasSingleInnerShapeType) {
324 if (kRect_ShapeFlag == ip.opInfo().fInnerShapeTypes) {
325 backend->setupInnerRect(v);
326 } else if (kOval_ShapeFlag == ip.opInfo().fInnerShapeTypes) {
327 backend->setupInnerOval(v);
328 } else {
329 backend->setupInnerSimpleRRect(v);
330 }
331 } else {
332 if (ip.opInfo().fInnerShapeTypes & kSimpleRRect_ShapeFlag) {
333 v->codeAppend ("if (SIMPLE_R_RECT_SHAPE_TYPE == innerShapeType) {");
334 backend->setupInnerSimpleRRect(v);
335 v->codeAppend("}");
336 usedShapeDefinitions |= kSimpleRRect_ShapeFlag;
337 }
338 if (ip.opInfo().fInnerShapeTypes & kOval_ShapeFlag) {
339 if (ip.opInfo().fInnerShapeTypes & kRect_ShapeFlag) {
340 if (ip.opInfo().fInnerShapeTypes & kSimpleRRect_ShapeFlag) {
341 v->codeAppend ("else ");
342 }
343 v->codeAppend ("if (OVAL_SHAPE_TYPE == innerShapeType) {");
344 usedShapeDefinitions |= kOval_ShapeFlag;
345 } else {
346 v->codeAppend ("else {");
347 }
348 backend->setupInnerOval(v);
349 v->codeAppend("}");
350 }
351 if (ip.opInfo().fInnerShapeTypes & kRect_ShapeFlag) {
352 v->codeAppend("else {");
353 backend->setupInnerRect(v);
354 v->codeAppend("}");
355 }
356 }
357 }
358
359 if (usedShapeDefinitions & kOval_ShapeFlag) {
360 v->defineConstant("OVAL_SHAPE_TYPE", (int)ShapeType::kOval);
361 }
362 if (usedShapeDefinitions & kSimpleRRect_ShapeFlag) {
363 v->defineConstant("SIMPLE_R_RECT_SHAPE_TYPE", (int)ShapeType::kSimpleRRect);
364 }
365 if (usedShapeDefinitions & kNinePatch_ShapeFlag) {
366 v->defineConstant("NINE_PATCH_SHAPE_TYPE", (int)ShapeType::kNinePatch);
367 }
368 SkASSERT(!(usedShapeDefinitions & (kRect_ShapeFlag | kComplexRRect_ShapeFlag)));
369
370 backend->emitCode(v, f, args.fOutputCoverage, args.fOutputColor);
371
372 const char* localCoords = nullptr;
373 if (ip.opInfo().fUsesLocalCoords) {
374 localCoords = "localCoords";
375 v->codeAppendf("vec2 t = 0.5 * (%s + vec2(1));", backend->outShapeCoords());
376 v->codeAppendf("vec2 localCoords = (1.0 - t) * %s.xy + t * %s.zw;",
377 inputs.attr(Attrib::kLocalRect), inputs.attr(Attrib::kLocalRect));
378 }
379 if (ip.opInfo().fHasLocalMatrix && ip.opInfo().fHasParams) {
380 v->defineConstantf("int", "LOCAL_MATRIX_FLAG", "0x%x", kLocalMatrix_InfoFlag);
381 v->codeAppendf("if (0 != (%s & LOCAL_MATRIX_FLAG)) {",
382 inputs.attr(Attrib::kInstanceInfo));
383 if (!ip.opInfo().fUsesLocalCoords) {
384 inputs.skipParams(2);
385 } else {
386 v->codeAppendf( "mat2x3 localMatrix;");
387 v->codeAppend ( "localMatrix[0] = ");
388 inputs.fetchNextParam(kVec3f_GrSLType);
389 v->codeAppend ( ";");
390 v->codeAppend ( "localMatrix[1] = ");
391 inputs.fetchNextParam(kVec3f_GrSLType);
392 v->codeAppend ( ";");
393 v->codeAppend ( "localCoords = (vec3(localCoords, 1) * localMatrix).xy;");
394 }
395 v->codeAppend("}");
396 }
397
398 GrSLType positionType = ip.opInfo().fHasPerspective ? kVec3f_GrSLType : kVec2f_GrSLType;
399 v->codeAppendf("%s deviceCoords = vec3(%s, 1) * shapeMatrix;",
400 GrGLSLTypeString(positionType), backend->outShapeCoords());
401 gpArgs->fPositionVar.set(positionType, "deviceCoords");
402
403 this->emitTransforms(v, varyingHandler, uniHandler, gpArgs->fPositionVar, localCoords,
404 args.fFPCoordTransformHandler);
405 }
406
407 ////////////////////////////////////////////////////////////////////////////////////////////////////
408
init(GrGLSLVaryingHandler * varyingHandler,GrGLSLVertexBuilder * v)409 void GLSLInstanceProcessor::Backend::init(GrGLSLVaryingHandler* varyingHandler,
410 GrGLSLVertexBuilder* v) {
411 if (fModifiedShapeCoords) {
412 v->codeAppendf("vec2 %s = %s;", fModifiedShapeCoords, fInputs.attr(Attrib::kShapeCoords));
413 }
414
415 this->onInit(varyingHandler, v);
416
417 if (!fColor.vsOut()) {
418 varyingHandler->addFlatVarying("color", &fColor, kLow_GrSLPrecision);
419 v->codeAppendf("%s = %s;", fColor.vsOut(), fInputs.attr(Attrib::kColor));
420 }
421 }
422
setupRRect(GrGLSLVertexBuilder * v,int * usedShapeDefinitions)423 void GLSLInstanceProcessor::Backend::setupRRect(GrGLSLVertexBuilder* v, int* usedShapeDefinitions) {
424 v->codeAppendf("uvec2 corner = uvec2(%s & 1, (%s >> 1) & 1);",
425 fInputs.attr(Attrib::kVertexAttrs), fInputs.attr(Attrib::kVertexAttrs));
426 v->codeAppend ("vec2 cornerSign = vec2(corner) * 2.0 - 1.0;");
427 v->codeAppendf("vec2 radii%s;", fNeedsNeighborRadii ? ", neighborRadii" : "");
428 v->codeAppend ("mat2 p = ");
429 fInputs.fetchNextParam(kMat22f_GrSLType);
430 v->codeAppend (";");
431 uint8_t types = fOpInfo.fShapeTypes & kRRect_ShapesMask;
432 if (0 == (types & (types - 1))) {
433 if (kSimpleRRect_ShapeFlag == types) {
434 this->setupSimpleRadii(v);
435 } else if (kNinePatch_ShapeFlag == types) {
436 this->setupNinePatchRadii(v);
437 } else if (kComplexRRect_ShapeFlag == types) {
438 this->setupComplexRadii(v);
439 }
440 } else {
441 if (types & kSimpleRRect_ShapeFlag) {
442 v->codeAppend ("if (SIMPLE_R_RECT_SHAPE_TYPE == shapeType) {");
443 this->setupSimpleRadii(v);
444 v->codeAppend ("}");
445 *usedShapeDefinitions |= kSimpleRRect_ShapeFlag;
446 }
447 if (types & kNinePatch_ShapeFlag) {
448 if (types & kComplexRRect_ShapeFlag) {
449 if (types & kSimpleRRect_ShapeFlag) {
450 v->codeAppend ("else ");
451 }
452 v->codeAppend ("if (NINE_PATCH_SHAPE_TYPE == shapeType) {");
453 *usedShapeDefinitions |= kNinePatch_ShapeFlag;
454 } else {
455 v->codeAppend ("else {");
456 }
457 this->setupNinePatchRadii(v);
458 v->codeAppend ("}");
459 }
460 if (types & kComplexRRect_ShapeFlag) {
461 v->codeAppend ("else {");
462 this->setupComplexRadii(v);
463 v->codeAppend ("}");
464 }
465 }
466
467 this->adjustRRectVertices(v);
468
469 if (fArcCoords.vsOut()) {
470 v->codeAppendf("%s = (cornerSign * %s + radii - vec2(1)) / radii;",
471 fArcCoords.vsOut(), fModifiedShapeCoords);
472 }
473 if (fTriangleIsArc.vsOut()) {
474 v->codeAppendf("%s = int(all(equal(vec2(1), abs(%s))));",
475 fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kShapeCoords));
476 }
477
478 this->onSetupRRect(v);
479 }
480
setupSimpleRadii(GrGLSLVertexBuilder * v)481 void GLSLInstanceProcessor::Backend::setupSimpleRadii(GrGLSLVertexBuilder* v) {
482 if (fNeedsNeighborRadii) {
483 v->codeAppend ("neighborRadii = ");
484 }
485 v->codeAppend("radii = p[0] * 2.0 / p[1];");
486 }
487
setupNinePatchRadii(GrGLSLVertexBuilder * v)488 void GLSLInstanceProcessor::Backend::setupNinePatchRadii(GrGLSLVertexBuilder* v) {
489 v->codeAppend("radii = vec2(p[0][corner.x], p[1][corner.y]);");
490 if (fNeedsNeighborRadii) {
491 v->codeAppend("neighborRadii = vec2(p[0][1 - corner.x], p[1][1 - corner.y]);");
492 }
493 }
494
setupComplexRadii(GrGLSLVertexBuilder * v)495 void GLSLInstanceProcessor::Backend::setupComplexRadii(GrGLSLVertexBuilder* v) {
496 /**
497 * The x and y radii of each arc are stored in separate vectors,
498 * in the following order:
499 *
500 * __x1 _ _ _ x3__
501 *
502 * y1 | | y2
503 *
504 * | |
505 *
506 * y3 |__ _ _ _ __| y4
507 * x2 x4
508 *
509 */
510 v->codeAppend("mat2 p2 = ");
511 fInputs.fetchNextParam(kMat22f_GrSLType);
512 v->codeAppend(";");
513 v->codeAppend("radii = vec2(p[corner.x][corner.y], p2[corner.y][corner.x]);");
514 if (fNeedsNeighborRadii) {
515 v->codeAppend("neighborRadii = vec2(p[1 - corner.x][corner.y], "
516 "p2[1 - corner.y][corner.x]);");
517 }
518 }
519
adjustRRectVertices(GrGLSLVertexBuilder * v)520 void GLSLInstanceProcessor::Backend::adjustRRectVertices(GrGLSLVertexBuilder* v) {
521 // Resize the 4 triangles that arcs are drawn into so they match their corresponding radii.
522 // 0.5 is a special value that indicates the edge of an arc triangle.
523 v->codeAppendf("if (abs(%s.x) == 0.5)"
524 "%s.x = cornerSign.x * (1.0 - radii.x);",
525 fInputs.attr(Attrib::kShapeCoords), fModifiedShapeCoords);
526 v->codeAppendf("if (abs(%s.y) == 0.5) "
527 "%s.y = cornerSign.y * (1.0 - radii.y);",
528 fInputs.attr(Attrib::kShapeCoords), fModifiedShapeCoords);
529 }
530
initInnerShape(GrGLSLVaryingHandler * varyingHandler,GrGLSLVertexBuilder * v)531 void GLSLInstanceProcessor::Backend::initInnerShape(GrGLSLVaryingHandler* varyingHandler,
532 GrGLSLVertexBuilder* v) {
533 SkASSERT(!(fOpInfo.fInnerShapeTypes & (kNinePatch_ShapeFlag | kComplexRRect_ShapeFlag)));
534
535 this->onInitInnerShape(varyingHandler, v);
536
537 if (fInnerShapeCoords.vsOut()) {
538 v->codeAppendf("%s = innerShapeCoords;", fInnerShapeCoords.vsOut());
539 }
540 }
541
setupInnerSimpleRRect(GrGLSLVertexBuilder * v)542 void GLSLInstanceProcessor::Backend::setupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
543 v->codeAppend("mat2 innerP = ");
544 fInputs.fetchNextParam(kMat22f_GrSLType);
545 v->codeAppend(";");
546 v->codeAppend("vec2 innerRadii = innerP[0] * 2.0 / innerP[1];");
547 this->onSetupInnerSimpleRRect(v);
548 }
549
emitCode(GrGLSLVertexBuilder * v,GrGLSLPPFragmentBuilder * f,const char * outCoverage,const char * outColor)550 void GLSLInstanceProcessor::Backend::emitCode(GrGLSLVertexBuilder* v, GrGLSLPPFragmentBuilder* f,
551 const char* outCoverage, const char* outColor) {
552 SkASSERT(!fModifiesCoverage || outCoverage);
553 this->onEmitCode(v, f, fModifiesCoverage ? outCoverage : nullptr,
554 fModifiesColor ? outColor : nullptr);
555 if (outCoverage && !fModifiesCoverage) {
556 // Even though the subclass doesn't use coverage, we are expected to assign some value.
557 f->codeAppendf("%s = vec4(1);", outCoverage);
558 }
559 if (!fModifiesColor) {
560 // The subclass didn't assign a value to the output color.
561 f->codeAppendf("%s = %s;", outColor, fColor.fsIn());
562 }
563 }
564
565 ////////////////////////////////////////////////////////////////////////////////////////////////////
566
567 class GLSLInstanceProcessor::BackendNonAA : public Backend {
568 public:
BackendNonAA(OpInfo opInfo,const VertexInputs & inputs)569 BackendNonAA(OpInfo opInfo, const VertexInputs& inputs) : INHERITED(opInfo, inputs) {
570 if (fOpInfo.fCannotDiscard && !fOpInfo.isSimpleRects()) {
571 fModifiesColor = !fOpInfo.fCannotTweakAlphaForCoverage;
572 fModifiesCoverage = !fModifiesColor;
573 }
574 }
575
576 private:
577 void onInit(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
578 void setupRect(GrGLSLVertexBuilder*) override;
579 void setupOval(GrGLSLVertexBuilder*) override;
580
581 void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
582 void setupInnerRect(GrGLSLVertexBuilder*) override;
583 void setupInnerOval(GrGLSLVertexBuilder*) override;
584 void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) override;
585
586 void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char*,
587 const char*) override;
588
589 typedef Backend INHERITED;
590 };
591
onInit(GrGLSLVaryingHandler * varyingHandler,GrGLSLVertexBuilder *)592 void GLSLInstanceProcessor::BackendNonAA::onInit(GrGLSLVaryingHandler* varyingHandler,
593 GrGLSLVertexBuilder*) {
594 if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
595 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision);
596 varyingHandler->addVarying("arcCoords", &fArcCoords, kMedium_GrSLPrecision);
597 }
598 }
599
setupRect(GrGLSLVertexBuilder * v)600 void GLSLInstanceProcessor::BackendNonAA::setupRect(GrGLSLVertexBuilder* v) {
601 if (fTriangleIsArc.vsOut()) {
602 v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
603 }
604 }
605
setupOval(GrGLSLVertexBuilder * v)606 void GLSLInstanceProcessor::BackendNonAA::setupOval(GrGLSLVertexBuilder* v) {
607 SkASSERT(fArcCoords.vsOut());
608 SkASSERT(fTriangleIsArc.vsOut());
609 v->codeAppendf("%s = %s;", fArcCoords.vsOut(), this->outShapeCoords());
610 v->codeAppendf("%s = %s & 1;", fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kVertexAttrs));
611 }
612
onInitInnerShape(GrGLSLVaryingHandler * varyingHandler,GrGLSLVertexBuilder *)613 void GLSLInstanceProcessor::BackendNonAA::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
614 GrGLSLVertexBuilder*) {
615 varyingHandler->addVarying("innerShapeCoords", &fInnerShapeCoords, kMedium_GrSLPrecision);
616 if (kRect_ShapeFlag != fOpInfo.fInnerShapeTypes &&
617 kOval_ShapeFlag != fOpInfo.fInnerShapeTypes) {
618 varyingHandler->addFlatVarying("innerRRect", &fInnerRRect, kMedium_GrSLPrecision);
619 }
620 }
621
setupInnerRect(GrGLSLVertexBuilder * v)622 void GLSLInstanceProcessor::BackendNonAA::setupInnerRect(GrGLSLVertexBuilder* v) {
623 if (fInnerRRect.vsOut()) {
624 v->codeAppendf("%s = vec4(1);", fInnerRRect.vsOut());
625 }
626 }
627
setupInnerOval(GrGLSLVertexBuilder * v)628 void GLSLInstanceProcessor::BackendNonAA::setupInnerOval(GrGLSLVertexBuilder* v) {
629 if (fInnerRRect.vsOut()) {
630 v->codeAppendf("%s = vec4(0, 0, 1, 1);", fInnerRRect.vsOut());
631 }
632 }
633
onSetupInnerSimpleRRect(GrGLSLVertexBuilder * v)634 void GLSLInstanceProcessor::BackendNonAA::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
635 v->codeAppendf("%s = vec4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
636 }
637
onEmitCode(GrGLSLVertexBuilder *,GrGLSLPPFragmentBuilder * f,const char * outCoverage,const char * outColor)638 void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
639 GrGLSLPPFragmentBuilder* f,
640 const char* outCoverage,
641 const char* outColor) {
642 const char* dropFragment = nullptr;
643 if (!fOpInfo.fCannotDiscard) {
644 dropFragment = "discard";
645 } else if (fModifiesCoverage) {
646 f->codeAppend ("lowp float covered = 1.0;");
647 dropFragment = "covered = 0.0";
648 } else if (fModifiesColor) {
649 f->codeAppendf("lowp vec4 color = %s;", fColor.fsIn());
650 dropFragment = "color = vec4(0)";
651 }
652 if (fTriangleIsArc.fsIn()) {
653 SkASSERT(dropFragment);
654 f->codeAppendf("if (%s != 0 && dot(%s, %s) > 1.0) %s;",
655 fTriangleIsArc.fsIn(), fArcCoords.fsIn(), fArcCoords.fsIn(), dropFragment);
656 }
657 if (fOpInfo.fInnerShapeTypes) {
658 SkASSERT(dropFragment);
659 f->codeAppendf("// Inner shape.\n");
660 if (kRect_ShapeFlag == fOpInfo.fInnerShapeTypes) {
661 f->codeAppendf("if (all(lessThanEqual(abs(%s), vec2(1)))) %s;",
662 fInnerShapeCoords.fsIn(), dropFragment);
663 } else if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
664 f->codeAppendf("if ((dot(%s, %s) <= 1.0)) %s;",
665 fInnerShapeCoords.fsIn(), fInnerShapeCoords.fsIn(), dropFragment);
666 } else {
667 f->codeAppendf("if (all(lessThan(abs(%s), vec2(1)))) {", fInnerShapeCoords.fsIn());
668 f->codeAppendf( "vec2 distanceToArcEdge = abs(%s) - %s.xy;",
669 fInnerShapeCoords.fsIn(), fInnerRRect.fsIn());
670 f->codeAppend ( "if (any(lessThan(distanceToArcEdge, vec2(0)))) {");
671 f->codeAppendf( "%s;", dropFragment);
672 f->codeAppend ( "} else {");
673 f->codeAppendf( "vec2 rrectCoords = distanceToArcEdge * %s.zw;",
674 fInnerRRect.fsIn());
675 f->codeAppend ( "if (dot(rrectCoords, rrectCoords) <= 1.0) {");
676 f->codeAppendf( "%s;", dropFragment);
677 f->codeAppend ( "}");
678 f->codeAppend ( "}");
679 f->codeAppend ("}");
680 }
681 }
682 if (fModifiesCoverage) {
683 f->codeAppendf("%s = vec4(covered);", outCoverage);
684 } else if (fModifiesColor) {
685 f->codeAppendf("%s = color;", outColor);
686 }
687 }
688
689 ////////////////////////////////////////////////////////////////////////////////////////////////////
690
691 class GLSLInstanceProcessor::BackendCoverage : public Backend {
692 public:
BackendCoverage(OpInfo opInfo,const VertexInputs & inputs)693 BackendCoverage(OpInfo opInfo, const VertexInputs& inputs)
694 : INHERITED(opInfo, inputs)
695 , fColorTimesRectCoverage(kVec4f_GrSLType)
696 , fRectCoverage(kFloat_GrSLType)
697 , fEllipseCoords(kVec2f_GrSLType)
698 , fEllipseName(kVec2f_GrSLType)
699 , fBloatedRadius(kFloat_GrSLType)
700 , fDistanceToInnerEdge(kVec2f_GrSLType)
701 , fInnerShapeBloatedHalfSize(kVec2f_GrSLType)
702 , fInnerEllipseCoords(kVec2f_GrSLType)
703 , fInnerEllipseName(kVec2f_GrSLType) {
704 fShapeIsCircle = !fOpInfo.fNonSquare && !(fOpInfo.fShapeTypes & kRRect_ShapesMask);
705 fTweakAlphaForCoverage = !fOpInfo.fCannotTweakAlphaForCoverage && !fOpInfo.fInnerShapeTypes;
706 fModifiesCoverage = !fTweakAlphaForCoverage;
707 fModifiesColor = fTweakAlphaForCoverage;
708 fModifiedShapeCoords = "bloatedShapeCoords";
709 }
710
711 private:
712 void onInit(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
713 void setupRect(GrGLSLVertexBuilder*) override;
714 void setupOval(GrGLSLVertexBuilder*) override;
715 void adjustRRectVertices(GrGLSLVertexBuilder*) override;
716 void onSetupRRect(GrGLSLVertexBuilder*) override;
717
718 void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
719 void setupInnerRect(GrGLSLVertexBuilder*) override;
720 void setupInnerOval(GrGLSLVertexBuilder*) override;
721 void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) override;
722
723 void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char* outCoverage,
724 const char* outColor) override;
725
726 void emitRect(GrGLSLPPFragmentBuilder*, const char* outCoverage, const char* outColor);
727 void emitCircle(GrGLSLPPFragmentBuilder*, const char* outCoverage);
728 void emitArc(GrGLSLPPFragmentBuilder* f, const char* ellipseCoords, const char* ellipseName,
729 bool ellipseCoordsNeedClamp, bool ellipseCoordsMayBeNegative,
730 const char* outCoverage);
731 void emitInnerRect(GrGLSLPPFragmentBuilder*, const char* outCoverage);
732
733 GrGLSLVertToFrag fColorTimesRectCoverage;
734 GrGLSLVertToFrag fRectCoverage;
735 GrGLSLVertToFrag fEllipseCoords;
736 GrGLSLVertToFrag fEllipseName;
737 GrGLSLVertToFrag fBloatedRadius;
738 GrGLSLVertToFrag fDistanceToInnerEdge;
739 GrGLSLVertToFrag fInnerShapeBloatedHalfSize;
740 GrGLSLVertToFrag fInnerEllipseCoords;
741 GrGLSLVertToFrag fInnerEllipseName;
742 bool fShapeIsCircle;
743 bool fTweakAlphaForCoverage;
744
745 typedef Backend INHERITED;
746 };
747
onInit(GrGLSLVaryingHandler * varyingHandler,GrGLSLVertexBuilder * v)748 void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyingHandler,
749 GrGLSLVertexBuilder* v) {
750 v->codeAppend ("mat2 shapeTransposeMatrix = transpose(mat2(shapeMatrix));");
751 v->codeAppend ("vec2 shapeHalfSize = vec2(length(shapeTransposeMatrix[0]), "
752 "length(shapeTransposeMatrix[1]));");
753 v->codeAppend ("vec2 bloat = 0.5 / shapeHalfSize;");
754 v->codeAppendf("bloatedShapeCoords = %s * (1.0 + bloat);", fInputs.attr(Attrib::kShapeCoords));
755
756 if (kOval_ShapeFlag != fOpInfo.fShapeTypes) {
757 if (fTweakAlphaForCoverage) {
758 varyingHandler->addVarying("colorTimesRectCoverage", &fColorTimesRectCoverage,
759 kLow_GrSLPrecision);
760 if (kRect_ShapeFlag == fOpInfo.fShapeTypes) {
761 fColor = fColorTimesRectCoverage;
762 }
763 } else {
764 varyingHandler->addVarying("rectCoverage", &fRectCoverage, kLow_GrSLPrecision);
765 }
766 v->codeAppend("float rectCoverage = 0.0;");
767 }
768 if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
769 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision);
770 if (!fShapeIsCircle) {
771 varyingHandler->addVarying("ellipseCoords", &fEllipseCoords, kMedium_GrSLPrecision);
772 varyingHandler->addFlatVarying("ellipseName", &fEllipseName, kHigh_GrSLPrecision);
773 } else {
774 varyingHandler->addVarying("circleCoords", &fEllipseCoords, kHigh_GrSLPrecision);
775 varyingHandler->addFlatVarying("bloatedRadius", &fBloatedRadius, kHigh_GrSLPrecision);
776 }
777 }
778 }
779
setupRect(GrGLSLVertexBuilder * v)780 void GLSLInstanceProcessor::BackendCoverage::setupRect(GrGLSLVertexBuilder* v) {
781 // Make the border one pixel wide. Inner vs outer is indicated by coordAttrs.
782 v->codeAppendf("vec2 rectBloat = (%s != 0) ? bloat : -bloat;",
783 fInputs.attr(Attrib::kVertexAttrs));
784 // Here we use the absolute value, because when the rect is thinner than a pixel, this makes it
785 // mark the spot where pixel center is within half a pixel of the *opposite* edge. This,
786 // combined with the "maxCoverage" logic below gives us mathematically correct coverage even for
787 // subpixel rectangles.
788 v->codeAppendf("bloatedShapeCoords = %s * abs(vec2(1.0 + rectBloat));",
789 fInputs.attr(Attrib::kShapeCoords));
790
791 // Determine coverage at the vertex. Coverage naturally ramps from 0 to 1 unless the rect is
792 // narrower than a pixel.
793 v->codeAppend ("float maxCoverage = 4.0 * min(0.5, shapeHalfSize.x) *"
794 "min(0.5, shapeHalfSize.y);");
795 v->codeAppendf("rectCoverage = (%s != 0) ? 0.0 : maxCoverage;",
796 fInputs.attr(Attrib::kVertexAttrs));
797
798 if (fTriangleIsArc.vsOut()) {
799 v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
800 }
801 }
802
setupOval(GrGLSLVertexBuilder * v)803 void GLSLInstanceProcessor::BackendCoverage::setupOval(GrGLSLVertexBuilder* v) {
804 // Offset the inner and outer octagons by one pixel. Inner vs outer is indicated by coordAttrs.
805 v->codeAppendf("vec2 ovalBloat = (%s != 0) ? bloat : -bloat;",
806 fInputs.attr(Attrib::kVertexAttrs));
807 v->codeAppendf("bloatedShapeCoords = %s * max(vec2(1.0 + ovalBloat), vec2(0));",
808 fInputs.attr(Attrib::kShapeCoords));
809 v->codeAppendf("%s = bloatedShapeCoords * shapeHalfSize;", fEllipseCoords.vsOut());
810 if (fEllipseName.vsOut()) {
811 v->codeAppendf("%s = 1.0 / (shapeHalfSize * shapeHalfSize);", fEllipseName.vsOut());
812 }
813 if (fBloatedRadius.vsOut()) {
814 SkASSERT(fShapeIsCircle);
815 v->codeAppendf("%s = shapeHalfSize.x + 0.5;", fBloatedRadius.vsOut());
816 }
817 if (fTriangleIsArc.vsOut()) {
818 v->codeAppendf("%s = int(%s != 0);",
819 fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kVertexAttrs));
820 }
821 if (fColorTimesRectCoverage.vsOut() || fRectCoverage.vsOut()) {
822 v->codeAppendf("rectCoverage = 1.0;");
823 }
824 }
825
adjustRRectVertices(GrGLSLVertexBuilder * v)826 void GLSLInstanceProcessor::BackendCoverage::adjustRRectVertices(GrGLSLVertexBuilder* v) {
827 // We try to let the AA borders line up with the arc edges on their particular side, but we
828 // can't allow them to get closer than one half pixel to the edge or they might overlap with
829 // their neighboring border.
830 v->codeAppend("vec2 innerEdge = max(1.0 - bloat, vec2(0));");
831 v->codeAppend ("vec2 borderEdge = cornerSign * clamp(1.0 - radii, -innerEdge, innerEdge);");
832 // 0.5 is a special value that indicates this vertex is an arc edge.
833 v->codeAppendf("if (abs(%s.x) == 0.5)"
834 "bloatedShapeCoords.x = borderEdge.x;", fInputs.attr(Attrib::kShapeCoords));
835 v->codeAppendf("if (abs(%s.y) == 0.5)"
836 "bloatedShapeCoords.y = borderEdge.y;", fInputs.attr(Attrib::kShapeCoords));
837
838 // Adjust the interior border vertices to make the border one pixel wide. 0.75 is a special
839 // value to indicate these points.
840 v->codeAppendf("if (abs(%s.x) == 0.75) "
841 "bloatedShapeCoords.x = cornerSign.x * innerEdge.x;",
842 fInputs.attr(Attrib::kShapeCoords));
843 v->codeAppendf("if (abs(%s.y) == 0.75) "
844 "bloatedShapeCoords.y = cornerSign.y * innerEdge.y;",
845 fInputs.attr(Attrib::kShapeCoords));
846 }
847
onSetupRRect(GrGLSLVertexBuilder * v)848 void GLSLInstanceProcessor::BackendCoverage::onSetupRRect(GrGLSLVertexBuilder* v) {
849 // The geometry is laid out in such a way that rectCoverage will be 0 and 1 on the vertices, but
850 // we still need to recompute this value because when the rrect gets thinner than one pixel, the
851 // interior edge of the border will necessarily clamp, and we need to match the AA behavior of
852 // the arc segments (i.e. distance from bloated edge only; ignoring the fact that the pixel
853 // actully has less coverage because it's not completely inside the opposite edge.)
854 v->codeAppend("vec2 d = shapeHalfSize + 0.5 - abs(bloatedShapeCoords) * shapeHalfSize;");
855 v->codeAppend("rectCoverage = min(d.x, d.y);");
856
857 SkASSERT(!fShapeIsCircle);
858 // The AA border does not get closer than one half pixel to the edge of the rect, so to get a
859 // smooth transition from flat edge to arc, we don't allow the radii to be smaller than one half
860 // pixel. (We don't worry about the transition on the opposite side when a radius is so large
861 // that the border clamped on that side.)
862 v->codeAppendf("vec2 clampedRadii = max(radii, bloat);");
863 v->codeAppendf("%s = (cornerSign * bloatedShapeCoords + clampedRadii - vec2(1)) * "
864 "shapeHalfSize;", fEllipseCoords.vsOut());
865 v->codeAppendf("%s = 1.0 / (clampedRadii * clampedRadii * shapeHalfSize * shapeHalfSize);",
866 fEllipseName.vsOut());
867 }
868
onInitInnerShape(GrGLSLVaryingHandler * varyingHandler,GrGLSLVertexBuilder * v)869 void GLSLInstanceProcessor::BackendCoverage::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
870 GrGLSLVertexBuilder* v) {
871 v->codeAppend("vec2 innerShapeHalfSize = shapeHalfSize / outer2Inner.xy;");
872
873 if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
874 varyingHandler->addVarying("innerEllipseCoords", &fInnerEllipseCoords,
875 kMedium_GrSLPrecision);
876 varyingHandler->addFlatVarying("innerEllipseName", &fInnerEllipseName, kHigh_GrSLPrecision);
877 } else {
878 varyingHandler->addVarying("distanceToInnerEdge", &fDistanceToInnerEdge,
879 kMedium_GrSLPrecision);
880 varyingHandler->addFlatVarying("innerShapeBloatedHalfSize", &fInnerShapeBloatedHalfSize,
881 kMedium_GrSLPrecision);
882 if (kRect_ShapeFlag != fOpInfo.fInnerShapeTypes) {
883 varyingHandler->addVarying("innerShapeCoords", &fInnerShapeCoords,
884 kMedium_GrSLPrecision);
885 varyingHandler->addFlatVarying("innerEllipseName", &fInnerEllipseName,
886 kHigh_GrSLPrecision);
887 varyingHandler->addFlatVarying("innerRRect", &fInnerRRect, kMedium_GrSLPrecision);
888 }
889 }
890 }
891
setupInnerRect(GrGLSLVertexBuilder * v)892 void GLSLInstanceProcessor::BackendCoverage::setupInnerRect(GrGLSLVertexBuilder* v) {
893 if (fInnerRRect.vsOut()) {
894 // The fragment shader will generalize every inner shape as a round rect. Since this one
895 // is a rect, we simply emit bogus parameters for the round rect (effectively negative
896 // radii) that ensure the fragment shader always takes the "emitRect" codepath.
897 v->codeAppendf("%s.xy = abs(outer2Inner.xy) * (1.0 + bloat) + abs(outer2Inner.zw);",
898 fInnerRRect.vsOut());
899 }
900 }
901
setupInnerOval(GrGLSLVertexBuilder * v)902 void GLSLInstanceProcessor::BackendCoverage::setupInnerOval(GrGLSLVertexBuilder* v) {
903 v->codeAppendf("%s = 1.0 / (innerShapeHalfSize * innerShapeHalfSize);",
904 fInnerEllipseName.vsOut());
905 if (fInnerEllipseCoords.vsOut()) {
906 v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;", fInnerEllipseCoords.vsOut());
907 }
908 if (fInnerRRect.vsOut()) {
909 v->codeAppendf("%s = vec4(0, 0, innerShapeHalfSize);", fInnerRRect.vsOut());
910 }
911 }
912
onSetupInnerSimpleRRect(GrGLSLVertexBuilder * v)913 void GLSLInstanceProcessor::BackendCoverage::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
914 // The distance to ellipse formula doesn't work well when the radii are less than half a pixel.
915 v->codeAppend ("innerRadii = max(innerRadii, bloat);");
916 v->codeAppendf("%s = 1.0 / (innerRadii * innerRadii * innerShapeHalfSize * "
917 "innerShapeHalfSize);",
918 fInnerEllipseName.vsOut());
919 v->codeAppendf("%s = vec4(1.0 - innerRadii, innerShapeHalfSize);", fInnerRRect.vsOut());
920 }
921
onEmitCode(GrGLSLVertexBuilder * v,GrGLSLPPFragmentBuilder * f,const char * outCoverage,const char * outColor)922 void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
923 GrGLSLPPFragmentBuilder* f,
924 const char* outCoverage,
925 const char* outColor) {
926 if (fColorTimesRectCoverage.vsOut()) {
927 SkASSERT(!fRectCoverage.vsOut());
928 v->codeAppendf("%s = %s * rectCoverage;",
929 fColorTimesRectCoverage.vsOut(), fInputs.attr(Attrib::kColor));
930 }
931 if (fRectCoverage.vsOut()) {
932 SkASSERT(!fColorTimesRectCoverage.vsOut());
933 v->codeAppendf("%s = rectCoverage;", fRectCoverage.vsOut());
934 }
935
936 SkString coverage("lowp float coverage");
937 if (fOpInfo.fInnerShapeTypes || (!fTweakAlphaForCoverage && fTriangleIsArc.fsIn())) {
938 f->codeAppendf("%s;", coverage.c_str());
939 coverage = "coverage";
940 }
941 if (fTriangleIsArc.fsIn()) {
942 f->codeAppendf("if (%s == 0) {", fTriangleIsArc.fsIn());
943 this->emitRect(f, coverage.c_str(), outColor);
944 f->codeAppend ("} else {");
945 if (fShapeIsCircle) {
946 this->emitCircle(f, coverage.c_str());
947 } else {
948 bool ellipseCoordsMayBeNegative = SkToBool(fOpInfo.fShapeTypes & kOval_ShapeFlag);
949 this->emitArc(f, fEllipseCoords.fsIn(), fEllipseName.fsIn(),
950 true /*ellipseCoordsNeedClamp*/, ellipseCoordsMayBeNegative,
951 coverage.c_str());
952 }
953 if (fTweakAlphaForCoverage) {
954 f->codeAppendf("%s = %s * coverage;", outColor, fColor.fsIn());
955 }
956 f->codeAppend ("}");
957 } else {
958 this->emitRect(f, coverage.c_str(), outColor);
959 }
960
961 if (fOpInfo.fInnerShapeTypes) {
962 f->codeAppendf("// Inner shape.\n");
963 SkString innerCoverageDecl("lowp float innerCoverage");
964 if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
965 this->emitArc(f, fInnerEllipseCoords.fsIn(), fInnerEllipseName.fsIn(),
966 true /*ellipseCoordsNeedClamp*/, true /*ellipseCoordsMayBeNegative*/,
967 innerCoverageDecl.c_str());
968 } else {
969 v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;",
970 fDistanceToInnerEdge.vsOut());
971 v->codeAppendf("%s = innerShapeHalfSize + 0.5;", fInnerShapeBloatedHalfSize.vsOut());
972
973 if (kRect_ShapeFlag == fOpInfo.fInnerShapeTypes) {
974 this->emitInnerRect(f, innerCoverageDecl.c_str());
975 } else {
976 f->codeAppendf("%s = 0.0;", innerCoverageDecl.c_str());
977 f->codeAppendf("mediump vec2 distanceToArcEdge = abs(%s) - %s.xy;",
978 fInnerShapeCoords.fsIn(), fInnerRRect.fsIn());
979 f->codeAppend ("if (any(lessThan(distanceToArcEdge, vec2(1e-5)))) {");
980 this->emitInnerRect(f, "innerCoverage");
981 f->codeAppend ("} else {");
982 f->codeAppendf( "mediump vec2 ellipseCoords = distanceToArcEdge * %s.zw;",
983 fInnerRRect.fsIn());
984 this->emitArc(f, "ellipseCoords", fInnerEllipseName.fsIn(),
985 false /*ellipseCoordsNeedClamp*/,
986 false /*ellipseCoordsMayBeNegative*/, "innerCoverage");
987 f->codeAppend ("}");
988 }
989 }
990 f->codeAppendf("%s = vec4(max(coverage - innerCoverage, 0.0));", outCoverage);
991 } else if (!fTweakAlphaForCoverage) {
992 f->codeAppendf("%s = vec4(coverage);", outCoverage);
993 }
994 }
995
emitRect(GrGLSLPPFragmentBuilder * f,const char * outCoverage,const char * outColor)996 void GLSLInstanceProcessor::BackendCoverage::emitRect(GrGLSLPPFragmentBuilder* f,
997 const char* outCoverage,
998 const char* outColor) {
999 if (fColorTimesRectCoverage.fsIn()) {
1000 f->codeAppendf("%s = %s;", outColor, fColorTimesRectCoverage.fsIn());
1001 } else if (fTweakAlphaForCoverage) {
1002 // We are drawing just ovals. The interior rect always has 100% coverage.
1003 f->codeAppendf("%s = %s;", outColor, fColor.fsIn());
1004 } else if (fRectCoverage.fsIn()) {
1005 f->codeAppendf("%s = %s;", outCoverage, fRectCoverage.fsIn());
1006 } else {
1007 f->codeAppendf("%s = 1.0;", outCoverage);
1008 }
1009 }
1010
emitCircle(GrGLSLPPFragmentBuilder * f,const char * outCoverage)1011 void GLSLInstanceProcessor::BackendCoverage::emitCircle(GrGLSLPPFragmentBuilder* f,
1012 const char* outCoverage) {
1013 // TODO: circleCoords = max(circleCoords, 0) if we decide to do this optimization on rrects.
1014 SkASSERT(!(kRRect_ShapesMask & fOpInfo.fShapeTypes));
1015 f->codeAppendf("mediump float distanceToEdge = %s - length(%s);",
1016 fBloatedRadius.fsIn(), fEllipseCoords.fsIn());
1017 f->codeAppendf("%s = clamp(distanceToEdge, 0.0, 1.0);", outCoverage);
1018 }
1019
emitArc(GrGLSLPPFragmentBuilder * f,const char * ellipseCoords,const char * ellipseName,bool ellipseCoordsNeedClamp,bool ellipseCoordsMayBeNegative,const char * outCoverage)1020 void GLSLInstanceProcessor::BackendCoverage::emitArc(GrGLSLPPFragmentBuilder* f,
1021 const char* ellipseCoords,
1022 const char* ellipseName,
1023 bool ellipseCoordsNeedClamp,
1024 bool ellipseCoordsMayBeNegative,
1025 const char* outCoverage) {
1026 SkASSERT(!ellipseCoordsMayBeNegative || ellipseCoordsNeedClamp);
1027 if (ellipseCoordsNeedClamp) {
1028 // This serves two purposes:
1029 // - To restrict the arcs of rounded rects to their positive quadrants.
1030 // - To avoid inversesqrt(0) in the ellipse formula.
1031 if (ellipseCoordsMayBeNegative) {
1032 f->codeAppendf("mediump vec2 ellipseClampedCoords = max(abs(%s), vec2(1e-4));",
1033 ellipseCoords);
1034 } else {
1035 f->codeAppendf("mediump vec2 ellipseClampedCoords = max(%s, vec2(1e-4));",
1036 ellipseCoords);
1037 }
1038 ellipseCoords = "ellipseClampedCoords";
1039 }
1040 // ellipseCoords are in pixel space and ellipseName is 1 / rx^2, 1 / ry^2.
1041 f->codeAppendf("highp vec2 Z = %s * %s;", ellipseCoords, ellipseName);
1042 // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
1043 f->codeAppendf("highp float implicit = dot(Z, %s) - 1.0;", ellipseCoords);
1044 // gradDot is the squared length of the gradient of the implicit.
1045 f->codeAppendf("highp float gradDot = 4.0 * dot(Z, Z);");
1046 f->codeAppend ("mediump float approxDist = implicit * inversesqrt(gradDot);");
1047 f->codeAppendf("%s = clamp(0.5 - approxDist, 0.0, 1.0);", outCoverage);
1048 }
1049
emitInnerRect(GrGLSLPPFragmentBuilder * f,const char * outCoverage)1050 void GLSLInstanceProcessor::BackendCoverage::emitInnerRect(GrGLSLPPFragmentBuilder* f,
1051 const char* outCoverage) {
1052 f->codeAppendf("lowp vec2 c = %s - abs(%s);",
1053 fInnerShapeBloatedHalfSize.fsIn(), fDistanceToInnerEdge.fsIn());
1054 f->codeAppendf("%s = clamp(min(c.x, c.y), 0.0, 1.0);", outCoverage);
1055 }
1056
1057 ////////////////////////////////////////////////////////////////////////////////////////////////////
1058
1059 class GLSLInstanceProcessor::BackendMultisample : public Backend {
1060 public:
BackendMultisample(OpInfo opInfo,const VertexInputs & inputs,int effectiveSampleCnt)1061 BackendMultisample(OpInfo opInfo, const VertexInputs& inputs, int effectiveSampleCnt)
1062 : INHERITED(opInfo, inputs)
1063 , fEffectiveSampleCnt(effectiveSampleCnt)
1064 , fShapeCoords(kVec2f_GrSLType)
1065 , fShapeInverseMatrix(kMat22f_GrSLType)
1066 , fFragShapeHalfSpan(kVec2f_GrSLType)
1067 , fArcTest(kVec2f_GrSLType)
1068 , fArcInverseMatrix(kMat22f_GrSLType)
1069 , fFragArcHalfSpan(kVec2f_GrSLType)
1070 , fEarlyAccept(kInt_GrSLType)
1071 , fInnerShapeInverseMatrix(kMat22f_GrSLType)
1072 , fFragInnerShapeHalfSpan(kVec2f_GrSLType) {
1073 fRectTrianglesMaySplit = fOpInfo.fHasPerspective;
1074 fNeedsNeighborRadii = this->isMixedSampled() && !fOpInfo.fHasPerspective;
1075 }
1076
1077 private:
isMixedSampled() const1078 bool isMixedSampled() const { return GrAAType::kMixedSamples == fOpInfo.aaType(); }
1079
1080 void onInit(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
1081 void setupRect(GrGLSLVertexBuilder*) override;
1082 void setupOval(GrGLSLVertexBuilder*) override;
1083 void adjustRRectVertices(GrGLSLVertexBuilder*) override;
1084 void onSetupRRect(GrGLSLVertexBuilder*) override;
1085
1086 void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
1087 void setupInnerRect(GrGLSLVertexBuilder*) override;
1088 void setupInnerOval(GrGLSLVertexBuilder*) override;
1089 void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) override;
1090
1091 void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char*,
1092 const char*) override;
1093
1094 struct EmitShapeCoords {
1095 const GrGLSLVarying* fVarying;
1096 const char* fInverseMatrix;
1097 const char* fFragHalfSpan;
1098 };
1099
1100 struct EmitShapeOpts {
1101 bool fIsTightGeometry;
1102 bool fResolveMixedSamples;
1103 bool fInvertCoverage;
1104 };
1105
1106 void emitRect(GrGLSLPPFragmentBuilder*, const EmitShapeCoords&, const EmitShapeOpts&);
1107 void emitArc(GrGLSLPPFragmentBuilder*, const EmitShapeCoords&, bool coordsMayBeNegative,
1108 bool clampCoords, const EmitShapeOpts&);
1109 void emitSimpleRRect(GrGLSLPPFragmentBuilder*, const EmitShapeCoords&, const char* rrect,
1110 const EmitShapeOpts&);
1111 void interpolateAtSample(GrGLSLPPFragmentBuilder*, const GrGLSLVarying&, const char* sampleIdx,
1112 const char* interpolationMatrix);
1113 void acceptOrRejectWholeFragment(GrGLSLPPFragmentBuilder*, bool inside, const EmitShapeOpts&);
1114 void acceptCoverageMask(GrGLSLPPFragmentBuilder*, const char* shapeMask, const EmitShapeOpts&,
1115 bool maybeSharedEdge = true);
1116
1117 int fEffectiveSampleCnt;
1118 bool fRectTrianglesMaySplit;
1119 GrGLSLVertToFrag fShapeCoords;
1120 GrGLSLVertToFrag fShapeInverseMatrix;
1121 GrGLSLVertToFrag fFragShapeHalfSpan;
1122 GrGLSLVertToFrag fArcTest;
1123 GrGLSLVertToFrag fArcInverseMatrix;
1124 GrGLSLVertToFrag fFragArcHalfSpan;
1125 GrGLSLVertToFrag fEarlyAccept;
1126 GrGLSLVertToFrag fInnerShapeInverseMatrix;
1127 GrGLSLVertToFrag fFragInnerShapeHalfSpan;
1128 SkString fSquareFun;
1129
1130 typedef Backend INHERITED;
1131 };
1132
onInit(GrGLSLVaryingHandler * varyingHandler,GrGLSLVertexBuilder * v)1133 void GLSLInstanceProcessor::BackendMultisample::onInit(GrGLSLVaryingHandler* varyingHandler,
1134 GrGLSLVertexBuilder* v) {
1135 if (!this->isMixedSampled()) {
1136 if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
1137 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision);
1138 varyingHandler->addVarying("arcCoords", &fArcCoords, kHigh_GrSLPrecision);
1139 if (!fOpInfo.fHasPerspective) {
1140 varyingHandler->addFlatVarying("arcInverseMatrix", &fArcInverseMatrix,
1141 kHigh_GrSLPrecision);
1142 varyingHandler->addFlatVarying("fragArcHalfSpan", &fFragArcHalfSpan,
1143 kHigh_GrSLPrecision);
1144 }
1145 } else if (!fOpInfo.fInnerShapeTypes) {
1146 return;
1147 }
1148 } else {
1149 varyingHandler->addVarying("shapeCoords", &fShapeCoords, kHigh_GrSLPrecision);
1150 if (!fOpInfo.fHasPerspective) {
1151 varyingHandler->addFlatVarying("shapeInverseMatrix", &fShapeInverseMatrix,
1152 kHigh_GrSLPrecision);
1153 varyingHandler->addFlatVarying("fragShapeHalfSpan", &fFragShapeHalfSpan,
1154 kHigh_GrSLPrecision);
1155 }
1156 if (fOpInfo.fShapeTypes & kRRect_ShapesMask) {
1157 varyingHandler->addVarying("arcCoords", &fArcCoords, kHigh_GrSLPrecision);
1158 varyingHandler->addVarying("arcTest", &fArcTest, kHigh_GrSLPrecision);
1159 if (!fOpInfo.fHasPerspective) {
1160 varyingHandler->addFlatVarying("arcInverseMatrix", &fArcInverseMatrix,
1161 kHigh_GrSLPrecision);
1162 varyingHandler->addFlatVarying("fragArcHalfSpan", &fFragArcHalfSpan,
1163 kHigh_GrSLPrecision);
1164 }
1165 } else if (fOpInfo.fShapeTypes & kOval_ShapeFlag) {
1166 fArcCoords = fShapeCoords;
1167 fArcInverseMatrix = fShapeInverseMatrix;
1168 fFragArcHalfSpan = fFragShapeHalfSpan;
1169 if (fOpInfo.fShapeTypes & kRect_ShapeFlag) {
1170 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc,
1171 kLow_GrSLPrecision);
1172 }
1173 }
1174 if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
1175 v->defineConstantf("int", "SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1);
1176 varyingHandler->addFlatVarying("earlyAccept", &fEarlyAccept, kHigh_GrSLPrecision);
1177 }
1178 }
1179 if (!fOpInfo.fHasPerspective) {
1180 v->codeAppend("mat2 shapeInverseMatrix = inverse(mat2(shapeMatrix));");
1181 v->codeAppend("vec2 fragShapeSpan = abs(vec4(shapeInverseMatrix).xz) + "
1182 "abs(vec4(shapeInverseMatrix).yw);");
1183 }
1184 }
1185
setupRect(GrGLSLVertexBuilder * v)1186 void GLSLInstanceProcessor::BackendMultisample::setupRect(GrGLSLVertexBuilder* v) {
1187 if (fShapeCoords.vsOut()) {
1188 v->codeAppendf("%s = %s;", fShapeCoords.vsOut(), this->outShapeCoords());
1189 }
1190 if (fShapeInverseMatrix.vsOut()) {
1191 v->codeAppendf("%s = shapeInverseMatrix;", fShapeInverseMatrix.vsOut());
1192 }
1193 if (fFragShapeHalfSpan.vsOut()) {
1194 v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut());
1195 }
1196 if (fArcTest.vsOut()) {
1197 // Pick a value that is not > 0.
1198 v->codeAppendf("%s = vec2(0);", fArcTest.vsOut());
1199 }
1200 if (fTriangleIsArc.vsOut()) {
1201 v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
1202 }
1203 if (fEarlyAccept.vsOut()) {
1204 v->codeAppendf("%s = SAMPLE_MASK_ALL;", fEarlyAccept.vsOut());
1205 }
1206 }
1207
setupOval(GrGLSLVertexBuilder * v)1208 void GLSLInstanceProcessor::BackendMultisample::setupOval(GrGLSLVertexBuilder* v) {
1209 v->codeAppendf("%s = abs(%s);", fArcCoords.vsOut(), this->outShapeCoords());
1210 if (fArcInverseMatrix.vsOut()) {
1211 v->codeAppendf("vec2 s = sign(%s);", this->outShapeCoords());
1212 v->codeAppendf("%s = shapeInverseMatrix * mat2(s.x, 0, 0 , s.y);",
1213 fArcInverseMatrix.vsOut());
1214 }
1215 if (fFragArcHalfSpan.vsOut()) {
1216 v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragArcHalfSpan.vsOut());
1217 }
1218 if (fArcTest.vsOut()) {
1219 // Pick a value that is > 0.
1220 v->codeAppendf("%s = vec2(1);", fArcTest.vsOut());
1221 }
1222 if (fTriangleIsArc.vsOut()) {
1223 if (!this->isMixedSampled()) {
1224 v->codeAppendf("%s = %s & 1;",
1225 fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kVertexAttrs));
1226 } else {
1227 v->codeAppendf("%s = 1;", fTriangleIsArc.vsOut());
1228 }
1229 }
1230 if (fEarlyAccept.vsOut()) {
1231 v->codeAppendf("%s = ~%s & SAMPLE_MASK_ALL;",
1232 fEarlyAccept.vsOut(), fInputs.attr(Attrib::kVertexAttrs));
1233 }
1234 }
1235
adjustRRectVertices(GrGLSLVertexBuilder * v)1236 void GLSLInstanceProcessor::BackendMultisample::adjustRRectVertices(GrGLSLVertexBuilder* v) {
1237 if (!this->isMixedSampled()) {
1238 INHERITED::adjustRRectVertices(v);
1239 return;
1240 }
1241
1242 if (!fOpInfo.fHasPerspective) {
1243 // For the mixed samples algorithm it's best to bloat the corner triangles a bit so that
1244 // more of the pixels that cross into the arc region are completely inside the shared edges.
1245 // We also snap to a regular rect if the radii shrink smaller than a pixel.
1246 v->codeAppend ("vec2 midpt = 0.5 * (neighborRadii - radii);");
1247 v->codeAppend ("vec2 cornerSize = any(lessThan(radii, fragShapeSpan)) ? "
1248 "vec2(0) : min(radii + 0.5 * fragShapeSpan, 1.0 - midpt);");
1249 } else {
1250 // TODO: We could still bloat the corner triangle in the perspective case; we would just
1251 // need to find the screen-space derivative of shape coords at this particular point.
1252 v->codeAppend ("vec2 cornerSize = any(lessThan(radii, vec2(1e-3))) ? vec2(0) : radii;");
1253 }
1254
1255 v->codeAppendf("if (abs(%s.x) == 0.5)"
1256 "%s.x = cornerSign.x * (1.0 - cornerSize.x);",
1257 fInputs.attr(Attrib::kShapeCoords), fModifiedShapeCoords);
1258 v->codeAppendf("if (abs(%s.y) == 0.5)"
1259 "%s.y = cornerSign.y * (1.0 - cornerSize.y);",
1260 fInputs.attr(Attrib::kShapeCoords), fModifiedShapeCoords);
1261 }
1262
onSetupRRect(GrGLSLVertexBuilder * v)1263 void GLSLInstanceProcessor::BackendMultisample::onSetupRRect(GrGLSLVertexBuilder* v) {
1264 if (fShapeCoords.vsOut()) {
1265 v->codeAppendf("%s = %s;", fShapeCoords.vsOut(), this->outShapeCoords());
1266 }
1267 if (fShapeInverseMatrix.vsOut()) {
1268 v->codeAppendf("%s = shapeInverseMatrix;", fShapeInverseMatrix.vsOut());
1269 }
1270 if (fFragShapeHalfSpan.vsOut()) {
1271 v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut());
1272 }
1273 if (fArcInverseMatrix.vsOut()) {
1274 v->codeAppend ("vec2 s = cornerSign / radii;");
1275 v->codeAppendf("%s = shapeInverseMatrix * mat2(s.x, 0, 0, s.y);",
1276 fArcInverseMatrix.vsOut());
1277 }
1278 if (fFragArcHalfSpan.vsOut()) {
1279 v->codeAppendf("%s = 0.5 * (abs(vec4(%s).xz) + abs(vec4(%s).yw));",
1280 fFragArcHalfSpan.vsOut(), fArcInverseMatrix.vsOut(),
1281 fArcInverseMatrix.vsOut());
1282 }
1283 if (fArcTest.vsOut()) {
1284 // The interior triangles are laid out as a fan. fArcTest is both distances from shared
1285 // edges of a fan triangle to a point within that triangle. fArcTest is used to check if a
1286 // fragment is too close to either shared edge, in which case we point sample the shape as a
1287 // rect at that point in order to guarantee the mixed samples discard logic works correctly.
1288 v->codeAppendf("%s = (cornerSize == vec2(0)) ? vec2(0) : "
1289 "cornerSign * %s * mat2(1, cornerSize.x - 1.0, cornerSize.y - 1.0, 1);",
1290 fArcTest.vsOut(), fModifiedShapeCoords);
1291 if (!fOpInfo.fHasPerspective) {
1292 // Shift the point at which distances to edges are measured from the center of the pixel
1293 // to the corner. This way the sign of fArcTest will quickly tell us whether a pixel
1294 // is completely inside the shared edge. Perspective mode will accomplish this same task
1295 // by finding the derivatives in the fragment shader.
1296 v->codeAppendf("%s -= 0.5 * (fragShapeSpan.yx * abs(radii - 1.0) + fragShapeSpan);",
1297 fArcTest.vsOut());
1298 }
1299 }
1300 if (fEarlyAccept.vsOut()) {
1301 SkASSERT(this->isMixedSampled());
1302 v->codeAppendf("%s = all(equal(vec2(1), abs(%s))) ? 0 : SAMPLE_MASK_ALL;",
1303 fEarlyAccept.vsOut(), fInputs.attr(Attrib::kShapeCoords));
1304 }
1305 }
1306
1307 void
onInitInnerShape(GrGLSLVaryingHandler * varyingHandler,GrGLSLVertexBuilder * v)1308 GLSLInstanceProcessor::BackendMultisample::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
1309 GrGLSLVertexBuilder* v) {
1310 varyingHandler->addVarying("innerShapeCoords", &fInnerShapeCoords, kHigh_GrSLPrecision);
1311 if (kOval_ShapeFlag != fOpInfo.fInnerShapeTypes &&
1312 kRect_ShapeFlag != fOpInfo.fInnerShapeTypes) {
1313 varyingHandler->addFlatVarying("innerRRect", &fInnerRRect, kHigh_GrSLPrecision);
1314 }
1315 if (!fOpInfo.fHasPerspective) {
1316 varyingHandler->addFlatVarying("innerShapeInverseMatrix", &fInnerShapeInverseMatrix,
1317 kHigh_GrSLPrecision);
1318 v->codeAppendf("%s = shapeInverseMatrix * mat2(outer2Inner.x, 0, 0, outer2Inner.y);",
1319 fInnerShapeInverseMatrix.vsOut());
1320 varyingHandler->addFlatVarying("fragInnerShapeHalfSpan", &fFragInnerShapeHalfSpan,
1321 kHigh_GrSLPrecision);
1322 v->codeAppendf("%s = 0.5 * fragShapeSpan * outer2Inner.xy;",
1323 fFragInnerShapeHalfSpan.vsOut());
1324 }
1325 }
1326
setupInnerRect(GrGLSLVertexBuilder * v)1327 void GLSLInstanceProcessor::BackendMultisample::setupInnerRect(GrGLSLVertexBuilder* v) {
1328 if (fInnerRRect.vsOut()) {
1329 // The fragment shader will generalize every inner shape as a round rect. Since this one
1330 // is a rect, we simply emit bogus parameters for the round rect (negative radii) that
1331 // ensure the fragment shader always takes the "sample as rect" codepath.
1332 v->codeAppendf("%s = vec4(2.0 * (inner.zw - inner.xy) / (outer.zw - outer.xy), vec2(0));",
1333 fInnerRRect.vsOut());
1334 }
1335 }
1336
setupInnerOval(GrGLSLVertexBuilder * v)1337 void GLSLInstanceProcessor::BackendMultisample::setupInnerOval(GrGLSLVertexBuilder* v) {
1338 if (fInnerRRect.vsOut()) {
1339 v->codeAppendf("%s = vec4(0, 0, 1, 1);", fInnerRRect.vsOut());
1340 }
1341 }
1342
onSetupInnerSimpleRRect(GrGLSLVertexBuilder * v)1343 void GLSLInstanceProcessor::BackendMultisample::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
1344 // Avoid numeric instability by not allowing the inner radii to get smaller than 1/10th pixel.
1345 if (fFragInnerShapeHalfSpan.vsOut()) {
1346 v->codeAppendf("innerRadii = max(innerRadii, 2e-1 * %s);", fFragInnerShapeHalfSpan.vsOut());
1347 } else {
1348 v->codeAppend ("innerRadii = max(innerRadii, vec2(1e-4));");
1349 }
1350 v->codeAppendf("%s = vec4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
1351 }
1352
onEmitCode(GrGLSLVertexBuilder *,GrGLSLPPFragmentBuilder * f,const char *,const char *)1353 void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
1354 GrGLSLPPFragmentBuilder* f,
1355 const char*, const char*) {
1356 f->defineConstant("SAMPLE_COUNT", fEffectiveSampleCnt);
1357 if (this->isMixedSampled()) {
1358 f->defineConstantf("int", "SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1);
1359 f->defineConstantf("int", "SAMPLE_MASK_MSB", "0x%x", 1 << (fEffectiveSampleCnt - 1));
1360 }
1361
1362 if (kRect_ShapeFlag != (fOpInfo.fShapeTypes | fOpInfo.fInnerShapeTypes)) {
1363 GrShaderVar x("x", kVec2f_GrSLType, GrShaderVar::kNonArray, kHigh_GrSLPrecision);
1364 f->emitFunction(kFloat_GrSLType, "square", 1, &x, "return dot(x, x);", &fSquareFun);
1365 }
1366
1367 EmitShapeCoords shapeCoords;
1368 shapeCoords.fVarying = &fShapeCoords;
1369 shapeCoords.fInverseMatrix = fShapeInverseMatrix.fsIn();
1370 shapeCoords.fFragHalfSpan = fFragShapeHalfSpan.fsIn();
1371
1372 EmitShapeCoords arcCoords;
1373 arcCoords.fVarying = &fArcCoords;
1374 arcCoords.fInverseMatrix = fArcInverseMatrix.fsIn();
1375 arcCoords.fFragHalfSpan = fFragArcHalfSpan.fsIn();
1376 bool clampArcCoords = this->isMixedSampled() && (fOpInfo.fShapeTypes & kRRect_ShapesMask);
1377
1378 EmitShapeOpts opts;
1379 opts.fIsTightGeometry = true;
1380 opts.fResolveMixedSamples = this->isMixedSampled();
1381 opts.fInvertCoverage = false;
1382
1383 if (fOpInfo.fHasPerspective && fOpInfo.fInnerShapeTypes) {
1384 // This determines if the fragment should consider the inner shape in its sample mask.
1385 // We take the derivative early in case discards may occur before we get to the inner shape.
1386 f->codeAppendf("highp vec2 fragInnerShapeApproxHalfSpan = 0.5 * fwidth(%s);",
1387 fInnerShapeCoords.fsIn());
1388 }
1389
1390 if (!this->isMixedSampled()) {
1391 SkASSERT(!fArcTest.fsIn());
1392 if (fTriangleIsArc.fsIn()) {
1393 f->codeAppendf("if (%s != 0) {", fTriangleIsArc.fsIn());
1394 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1395
1396 f->codeAppend ("}");
1397 }
1398 } else {
1399 const char* arcTest = fArcTest.fsIn();
1400 if (arcTest && fOpInfo.fHasPerspective) {
1401 // The non-perspective version accounts for fwidth() in the vertex shader.
1402 // We make sure to take the derivative here, before a neighbor pixel may early accept.
1403 f->codeAppendf("highp vec2 arcTest = %s - 0.5 * fwidth(%s);",
1404 fArcTest.fsIn(), fArcTest.fsIn());
1405 arcTest = "arcTest";
1406 }
1407 const char* earlyAccept = fEarlyAccept.fsIn() ? fEarlyAccept.fsIn() : "SAMPLE_MASK_ALL";
1408 f->codeAppendf("if (gl_SampleMaskIn[0] == %s) {", earlyAccept);
1409 f->overrideSampleCoverage(earlyAccept);
1410 f->codeAppend ("} else {");
1411 if (arcTest) {
1412 // At this point, if the sample mask is all set it means we are inside an arc triangle.
1413 f->codeAppendf("if (gl_SampleMaskIn[0] == SAMPLE_MASK_ALL || "
1414 "all(greaterThan(%s, vec2(0)))) {", arcTest);
1415 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1416 f->codeAppend ("} else {");
1417 this->emitRect(f, shapeCoords, opts);
1418 f->codeAppend ("}");
1419 } else if (fTriangleIsArc.fsIn()) {
1420 f->codeAppendf("if (%s == 0) {", fTriangleIsArc.fsIn());
1421 this->emitRect(f, shapeCoords, opts);
1422 f->codeAppend ("} else {");
1423 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1424 f->codeAppend ("}");
1425 } else if (fOpInfo.fShapeTypes == kOval_ShapeFlag) {
1426 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1427 } else {
1428 SkASSERT(fOpInfo.fShapeTypes == kRect_ShapeFlag);
1429 this->emitRect(f, shapeCoords, opts);
1430 }
1431 f->codeAppend ("}");
1432 }
1433
1434 if (fOpInfo.fInnerShapeTypes) {
1435 f->codeAppendf("// Inner shape.\n");
1436
1437 EmitShapeCoords innerShapeCoords;
1438 innerShapeCoords.fVarying = &fInnerShapeCoords;
1439 if (!fOpInfo.fHasPerspective) {
1440 innerShapeCoords.fInverseMatrix = fInnerShapeInverseMatrix.fsIn();
1441 innerShapeCoords.fFragHalfSpan = fFragInnerShapeHalfSpan.fsIn();
1442 }
1443
1444 EmitShapeOpts innerOpts;
1445 innerOpts.fIsTightGeometry = false;
1446 innerOpts.fResolveMixedSamples = false; // Mixed samples are resolved in the outer shape.
1447 innerOpts.fInvertCoverage = true;
1448
1449 if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
1450 this->emitArc(f, innerShapeCoords, true, false, innerOpts);
1451 } else {
1452 f->codeAppendf("if (all(lessThan(abs(%s), 1.0 + %s))) {", fInnerShapeCoords.fsIn(),
1453 !fOpInfo.fHasPerspective ? innerShapeCoords.fFragHalfSpan
1454 : "fragInnerShapeApproxHalfSpan"); // Above.
1455 if (kRect_ShapeFlag == fOpInfo.fInnerShapeTypes) {
1456 this->emitRect(f, innerShapeCoords, innerOpts);
1457 } else {
1458 this->emitSimpleRRect(f, innerShapeCoords, fInnerRRect.fsIn(), innerOpts);
1459 }
1460 f->codeAppend ("}");
1461 }
1462 }
1463 }
1464
emitRect(GrGLSLPPFragmentBuilder * f,const EmitShapeCoords & coords,const EmitShapeOpts & opts)1465 void GLSLInstanceProcessor::BackendMultisample::emitRect(GrGLSLPPFragmentBuilder* f,
1466 const EmitShapeCoords& coords,
1467 const EmitShapeOpts& opts) {
1468 // Full MSAA doesn't need to do anything to draw a rect.
1469 SkASSERT(!opts.fIsTightGeometry || opts.fResolveMixedSamples);
1470 if (coords.fFragHalfSpan) {
1471 f->codeAppendf("if (all(lessThanEqual(abs(%s), 1.0 - %s))) {",
1472 coords.fVarying->fsIn(), coords.fFragHalfSpan);
1473 // The entire pixel is inside the rect.
1474 this->acceptOrRejectWholeFragment(f, true, opts);
1475 f->codeAppend ("} else ");
1476 if (opts.fIsTightGeometry && !fRectTrianglesMaySplit) {
1477 f->codeAppendf("if (any(lessThan(abs(%s), 1.0 - %s))) {",
1478 coords.fVarying->fsIn(), coords.fFragHalfSpan);
1479 // The pixel falls on an edge of the rectangle and is known to not be on a shared edge.
1480 this->acceptCoverageMask(f, "gl_SampleMaskIn[0]", opts, false);
1481 f->codeAppend ("} else");
1482 }
1483 f->codeAppend ("{");
1484 }
1485 f->codeAppend ("int rectMask = 0;");
1486 f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
1487 f->codeAppend ( "highp vec2 pt = ");
1488 this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
1489 f->codeAppend ( ";");
1490 f->codeAppend ( "if (all(lessThan(abs(pt), vec2(1)))) rectMask |= (1 << i);");
1491 f->codeAppend ("}");
1492 this->acceptCoverageMask(f, "rectMask", opts);
1493 if (coords.fFragHalfSpan) {
1494 f->codeAppend ("}");
1495 }
1496 }
1497
emitArc(GrGLSLPPFragmentBuilder * f,const EmitShapeCoords & coords,bool coordsMayBeNegative,bool clampCoords,const EmitShapeOpts & opts)1498 void GLSLInstanceProcessor::BackendMultisample::emitArc(GrGLSLPPFragmentBuilder* f,
1499 const EmitShapeCoords& coords,
1500 bool coordsMayBeNegative, bool clampCoords,
1501 const EmitShapeOpts& opts) {
1502 if (coords.fFragHalfSpan) {
1503 SkString absArcCoords;
1504 absArcCoords.printf(coordsMayBeNegative ? "abs(%s)" : "%s", coords.fVarying->fsIn());
1505 if (clampCoords) {
1506 f->codeAppendf("if (%s(max(%s + %s, vec2(0))) < 1.0) {",
1507 fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
1508 } else {
1509 f->codeAppendf("if (%s(%s + %s) < 1.0) {",
1510 fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
1511 }
1512 // The entire pixel is inside the arc.
1513 this->acceptOrRejectWholeFragment(f, true, opts);
1514 f->codeAppendf("} else if (%s(max(%s - %s, vec2(0))) >= 1.0) {",
1515 fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
1516 // The entire pixel is outside the arc.
1517 this->acceptOrRejectWholeFragment(f, false, opts);
1518 f->codeAppend ("} else {");
1519 }
1520 f->codeAppend ( "int arcMask = 0;");
1521 f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {");
1522 f->codeAppend ( "highp vec2 pt = ");
1523 this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
1524 f->codeAppend ( ";");
1525 if (clampCoords) {
1526 SkASSERT(!coordsMayBeNegative);
1527 f->codeAppend ( "pt = max(pt, vec2(0));");
1528 }
1529 f->codeAppendf( "if (%s(pt) < 1.0) arcMask |= (1 << i);", fSquareFun.c_str());
1530 f->codeAppend ( "}");
1531 this->acceptCoverageMask(f, "arcMask", opts);
1532 if (coords.fFragHalfSpan) {
1533 f->codeAppend ("}");
1534 }
1535 }
1536
emitSimpleRRect(GrGLSLPPFragmentBuilder * f,const EmitShapeCoords & coords,const char * rrect,const EmitShapeOpts & opts)1537 void GLSLInstanceProcessor::BackendMultisample::emitSimpleRRect(GrGLSLPPFragmentBuilder* f,
1538 const EmitShapeCoords& coords,
1539 const char* rrect,
1540 const EmitShapeOpts& opts) {
1541 f->codeAppendf("highp vec2 distanceToArcEdge = abs(%s) - %s.xy;", coords.fVarying->fsIn(),
1542 rrect);
1543 f->codeAppend ("if (any(lessThan(distanceToArcEdge, vec2(0)))) {");
1544 this->emitRect(f, coords, opts);
1545 f->codeAppend ("} else {");
1546 if (coords.fInverseMatrix && coords.fFragHalfSpan) {
1547 f->codeAppendf("highp vec2 rrectCoords = distanceToArcEdge * %s.zw;", rrect);
1548 f->codeAppendf("highp vec2 fragRRectHalfSpan = %s * %s.zw;", coords.fFragHalfSpan, rrect);
1549 f->codeAppendf("if (%s(rrectCoords + fragRRectHalfSpan) <= 1.0) {", fSquareFun.c_str());
1550 // The entire pixel is inside the round rect.
1551 this->acceptOrRejectWholeFragment(f, true, opts);
1552 f->codeAppendf("} else if (%s(max(rrectCoords - fragRRectHalfSpan, vec2(0))) >= 1.0) {",
1553 fSquareFun.c_str());
1554 // The entire pixel is outside the round rect.
1555 this->acceptOrRejectWholeFragment(f, false, opts);
1556 f->codeAppend ("} else {");
1557 f->codeAppendf( "highp vec2 s = %s.zw * sign(%s);", rrect, coords.fVarying->fsIn());
1558 f->codeAppendf( "highp mat2 innerRRectInverseMatrix = %s * mat2(s.x, 0, 0, s.y);",
1559 coords.fInverseMatrix);
1560 f->codeAppend ( "highp int rrectMask = 0;");
1561 f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {");
1562 f->codeAppend ( "highp vec2 pt = rrectCoords + ");
1563 f->appendOffsetToSample("i", GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
1564 f->codeAppend ( "* innerRRectInverseMatrix;");
1565 f->codeAppendf( "if (%s(max(pt, vec2(0))) < 1.0) rrectMask |= (1 << i);",
1566 fSquareFun.c_str());
1567 f->codeAppend ( "}");
1568 this->acceptCoverageMask(f, "rrectMask", opts);
1569 f->codeAppend ("}");
1570 } else {
1571 f->codeAppend ("int rrectMask = 0;");
1572 f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
1573 f->codeAppend ( "highp vec2 shapePt = ");
1574 this->interpolateAtSample(f, *coords.fVarying, "i", nullptr);
1575 f->codeAppend ( ";");
1576 f->codeAppendf( "highp vec2 rrectPt = max(abs(shapePt) - %s.xy, vec2(0)) * %s.zw;",
1577 rrect, rrect);
1578 f->codeAppendf( "if (%s(rrectPt) < 1.0) rrectMask |= (1 << i);", fSquareFun.c_str());
1579 f->codeAppend ("}");
1580 this->acceptCoverageMask(f, "rrectMask", opts);
1581 }
1582 f->codeAppend ("}");
1583 }
1584
interpolateAtSample(GrGLSLPPFragmentBuilder * f,const GrGLSLVarying & varying,const char * sampleIdx,const char * interpolationMatrix)1585 void GLSLInstanceProcessor::BackendMultisample::interpolateAtSample(GrGLSLPPFragmentBuilder* f,
1586 const GrGLSLVarying& varying,
1587 const char* sampleIdx,
1588 const char* interpolationMatrix) {
1589 if (interpolationMatrix) {
1590 f->codeAppendf("(%s + ", varying.fsIn());
1591 f->appendOffsetToSample(sampleIdx, GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
1592 f->codeAppendf(" * %s)", interpolationMatrix);
1593 } else {
1594 SkAssertResult(
1595 f->enableFeature(GrGLSLFragmentBuilder::kMultisampleInterpolation_GLSLFeature));
1596 f->codeAppendf("interpolateAtOffset(%s, ", varying.fsIn());
1597 f->appendOffsetToSample(sampleIdx, GrGLSLFPFragmentBuilder::kGLSLWindow_Coordinates);
1598 f->codeAppend(")");
1599 }
1600 }
1601
1602 void
acceptOrRejectWholeFragment(GrGLSLPPFragmentBuilder * f,bool inside,const EmitShapeOpts & opts)1603 GLSLInstanceProcessor::BackendMultisample::acceptOrRejectWholeFragment(GrGLSLPPFragmentBuilder* f,
1604 bool inside,
1605 const EmitShapeOpts& opts) {
1606 if (inside != opts.fInvertCoverage) { // Accept the entire fragment.
1607 if (opts.fResolveMixedSamples) {
1608 // This is a mixed sampled fragment in the interior of the shape. Reassign 100% coverage
1609 // to one fragment, and drop all other fragments that may fall on this same pixel. Since
1610 // our geometry is water tight and non-overlapping, we can take advantage of the
1611 // properties that (1) the incoming sample masks will be disjoint across fragments that
1612 // fall on a common pixel, and (2) since the entire fragment is inside the shape, each
1613 // sample's corresponding bit will be set in the incoming sample mask of exactly one
1614 // fragment.
1615 f->codeAppend("if ((gl_SampleMaskIn[0] & SAMPLE_MASK_MSB) == 0) {");
1616 // Drop this fragment.
1617 if (!fOpInfo.fCannotDiscard) {
1618 f->codeAppend("discard;");
1619 } else {
1620 f->overrideSampleCoverage("0");
1621 }
1622 f->codeAppend("} else {");
1623 // Override the lone surviving fragment to full coverage.
1624 f->overrideSampleCoverage("-1");
1625 f->codeAppend("}");
1626 }
1627 } else { // Reject the entire fragment.
1628 if (!fOpInfo.fCannotDiscard) {
1629 f->codeAppend("discard;");
1630 } else if (opts.fResolveMixedSamples) {
1631 f->overrideSampleCoverage("0");
1632 } else {
1633 f->maskSampleCoverage("0");
1634 }
1635 }
1636 }
1637
acceptCoverageMask(GrGLSLPPFragmentBuilder * f,const char * shapeMask,const EmitShapeOpts & opts,bool maybeSharedEdge)1638 void GLSLInstanceProcessor::BackendMultisample::acceptCoverageMask(GrGLSLPPFragmentBuilder* f,
1639 const char* shapeMask,
1640 const EmitShapeOpts& opts,
1641 bool maybeSharedEdge) {
1642 if (opts.fResolveMixedSamples) {
1643 if (maybeSharedEdge) {
1644 // This is a mixed sampled fragment, potentially on the outer edge of the shape, with
1645 // only partial shape coverage. Override the coverage of one fragment to "shapeMask",
1646 // and drop all other fragments that may fall on this same pixel. Since our geometry is
1647 // water tight, non-overlapping, and completely contains the shape, this means that each
1648 // "on" bit from shapeMask is guaranteed to be set in the incoming sample mask of one,
1649 // and only one, fragment that falls on this same pixel.
1650 SkASSERT(!opts.fInvertCoverage);
1651 f->codeAppendf("if ((gl_SampleMaskIn[0] & (1 << findMSB(%s))) == 0) {", shapeMask);
1652 // Drop this fragment.
1653 if (!fOpInfo.fCannotDiscard) {
1654 f->codeAppend ("discard;");
1655 } else {
1656 f->overrideSampleCoverage("0");
1657 }
1658 f->codeAppend ("} else {");
1659 // Override the coverage of the lone surviving fragment to "shapeMask".
1660 f->overrideSampleCoverage(shapeMask);
1661 f->codeAppend ("}");
1662 } else {
1663 f->overrideSampleCoverage(shapeMask);
1664 }
1665 } else {
1666 f->maskSampleCoverage(shapeMask, opts.fInvertCoverage);
1667 }
1668 }
1669
1670 ////////////////////////////////////////////////////////////////////////////////////////////////////
1671
Create(const GrPipeline & pipeline,OpInfo opInfo,const VertexInputs & inputs)1672 GLSLInstanceProcessor::Backend* GLSLInstanceProcessor::Backend::Create(const GrPipeline& pipeline,
1673 OpInfo opInfo,
1674 const VertexInputs& inputs) {
1675 switch (opInfo.aaType()) {
1676 default:
1677 SkFAIL("Unexpected antialias mode.");
1678 case GrAAType::kNone:
1679 return new BackendNonAA(opInfo, inputs);
1680 case GrAAType::kCoverage:
1681 return new BackendCoverage(opInfo, inputs);
1682 case GrAAType::kMSAA:
1683 case GrAAType::kMixedSamples: {
1684 const GrRenderTargetPriv& rtp = pipeline.getRenderTarget()->renderTargetPriv();
1685 const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline);
1686 return new BackendMultisample(opInfo, inputs, specs.fEffectiveSampleCnt);
1687 }
1688 }
1689 }
1690
1691 ////////////////////////////////////////////////////////////////////////////////////////////////////
1692
1693 const ShapeVertex kVertexData[] = {
1694 // Rectangle.
1695 {+1, +1, ~0}, /*0*/
1696 {-1, +1, ~0}, /*1*/
1697 {-1, -1, ~0}, /*2*/
1698 {+1, -1, ~0}, /*3*/
1699 // The next 4 are for the bordered version.
1700 {+1, +1, 0}, /*4*/
1701 {-1, +1, 0}, /*5*/
1702 {-1, -1, 0}, /*6*/
1703 {+1, -1, 0}, /*7*/
1704
1705 // Octagon that inscribes the unit circle, cut by an interior unit octagon.
1706 {+1.000000f, 0.000000f, 0}, /* 8*/
1707 {+1.000000f, +0.414214f, ~0}, /* 9*/
1708 {+0.707106f, +0.707106f, 0}, /*10*/
1709 {+0.414214f, +1.000000f, ~0}, /*11*/
1710 { 0.000000f, +1.000000f, 0}, /*12*/
1711 {-0.414214f, +1.000000f, ~0}, /*13*/
1712 {-0.707106f, +0.707106f, 0}, /*14*/
1713 {-1.000000f, +0.414214f, ~0}, /*15*/
1714 {-1.000000f, 0.000000f, 0}, /*16*/
1715 {-1.000000f, -0.414214f, ~0}, /*17*/
1716 {-0.707106f, -0.707106f, 0}, /*18*/
1717 {-0.414214f, -1.000000f, ~0}, /*19*/
1718 { 0.000000f, -1.000000f, 0}, /*20*/
1719 {+0.414214f, -1.000000f, ~0}, /*21*/
1720 {+0.707106f, -0.707106f, 0}, /*22*/
1721 {+1.000000f, -0.414214f, ~0}, /*23*/
1722 // This vertex is for the fanned versions.
1723 { 0.000000f, 0.000000f, ~0}, /*24*/
1724
1725 // Rectangle with disjoint corner segments.
1726 {+1.0, +0.5, 0x3}, /*25*/
1727 {+1.0, +1.0, 0x3}, /*26*/
1728 {+0.5, +1.0, 0x3}, /*27*/
1729 {-0.5, +1.0, 0x2}, /*28*/
1730 {-1.0, +1.0, 0x2}, /*29*/
1731 {-1.0, +0.5, 0x2}, /*30*/
1732 {-1.0, -0.5, 0x0}, /*31*/
1733 {-1.0, -1.0, 0x0}, /*32*/
1734 {-0.5, -1.0, 0x0}, /*33*/
1735 {+0.5, -1.0, 0x1}, /*34*/
1736 {+1.0, -1.0, 0x1}, /*35*/
1737 {+1.0, -0.5, 0x1}, /*36*/
1738 // The next 4 are for the fanned version.
1739 { 0.0, 0.0, 0x3}, /*37*/
1740 { 0.0, 0.0, 0x2}, /*38*/
1741 { 0.0, 0.0, 0x0}, /*39*/
1742 { 0.0, 0.0, 0x1}, /*40*/
1743 // The next 8 are for the bordered version.
1744 {+0.75, +0.50, 0x3}, /*41*/
1745 {+0.50, +0.75, 0x3}, /*42*/
1746 {-0.50, +0.75, 0x2}, /*43*/
1747 {-0.75, +0.50, 0x2}, /*44*/
1748 {-0.75, -0.50, 0x0}, /*45*/
1749 {-0.50, -0.75, 0x0}, /*46*/
1750 {+0.50, -0.75, 0x1}, /*47*/
1751 {+0.75, -0.50, 0x1}, /*48*/
1752
1753 // 16-gon that inscribes the unit circle, cut by an interior unit 16-gon.
1754 {+1.000000f, +0.000000f, 0}, /*49*/
1755 {+1.000000f, +0.198913f, ~0}, /*50*/
1756 {+0.923879f, +0.382683f, 0}, /*51*/
1757 {+0.847760f, +0.566455f, ~0}, /*52*/
1758 {+0.707106f, +0.707106f, 0}, /*53*/
1759 {+0.566455f, +0.847760f, ~0}, /*54*/
1760 {+0.382683f, +0.923879f, 0}, /*55*/
1761 {+0.198913f, +1.000000f, ~0}, /*56*/
1762 {+0.000000f, +1.000000f, 0}, /*57*/
1763 {-0.198913f, +1.000000f, ~0}, /*58*/
1764 {-0.382683f, +0.923879f, 0}, /*59*/
1765 {-0.566455f, +0.847760f, ~0}, /*60*/
1766 {-0.707106f, +0.707106f, 0}, /*61*/
1767 {-0.847760f, +0.566455f, ~0}, /*62*/
1768 {-0.923879f, +0.382683f, 0}, /*63*/
1769 {-1.000000f, +0.198913f, ~0}, /*64*/
1770 {-1.000000f, +0.000000f, 0}, /*65*/
1771 {-1.000000f, -0.198913f, ~0}, /*66*/
1772 {-0.923879f, -0.382683f, 0}, /*67*/
1773 {-0.847760f, -0.566455f, ~0}, /*68*/
1774 {-0.707106f, -0.707106f, 0}, /*69*/
1775 {-0.566455f, -0.847760f, ~0}, /*70*/
1776 {-0.382683f, -0.923879f, 0}, /*71*/
1777 {-0.198913f, -1.000000f, ~0}, /*72*/
1778 {-0.000000f, -1.000000f, 0}, /*73*/
1779 {+0.198913f, -1.000000f, ~0}, /*74*/
1780 {+0.382683f, -0.923879f, 0}, /*75*/
1781 {+0.566455f, -0.847760f, ~0}, /*76*/
1782 {+0.707106f, -0.707106f, 0}, /*77*/
1783 {+0.847760f, -0.566455f, ~0}, /*78*/
1784 {+0.923879f, -0.382683f, 0}, /*79*/
1785 {+1.000000f, -0.198913f, ~0}, /*80*/
1786 };
1787
1788 const uint8_t kIndexData[] = {
1789 // Rectangle.
1790 0, 1, 2,
1791 0, 2, 3,
1792
1793 // Rectangle with a border.
1794 0, 1, 5,
1795 5, 4, 0,
1796 1, 2, 6,
1797 6, 5, 1,
1798 2, 3, 7,
1799 7, 6, 2,
1800 3, 0, 4,
1801 4, 7, 3,
1802 4, 5, 6,
1803 6, 7, 4,
1804
1805 // Octagon that inscribes the unit circle, cut by an interior unit octagon.
1806 10, 8, 9,
1807 12, 10, 11,
1808 14, 12, 13,
1809 16, 14, 15,
1810 18, 16, 17,
1811 20, 18, 19,
1812 22, 20, 21,
1813 8, 22, 23,
1814 8, 10, 12,
1815 12, 14, 16,
1816 16, 18, 20,
1817 20, 22, 8,
1818 8, 12, 16,
1819 16, 20, 8,
1820
1821 // Same octagons, but with the interior arranged as a fan. Used by mixed samples.
1822 10, 8, 9,
1823 12, 10, 11,
1824 14, 12, 13,
1825 16, 14, 15,
1826 18, 16, 17,
1827 20, 18, 19,
1828 22, 20, 21,
1829 8, 22, 23,
1830 24, 8, 10,
1831 12, 24, 10,
1832 24, 12, 14,
1833 16, 24, 14,
1834 24, 16, 18,
1835 20, 24, 18,
1836 24, 20, 22,
1837 8, 24, 22,
1838
1839 // Same octagons, but with the inner and outer disjoint. Used by coverage AA.
1840 8, 22, 23,
1841 9, 8, 23,
1842 10, 8, 9,
1843 11, 10, 9,
1844 12, 10, 11,
1845 13, 12, 11,
1846 14, 12, 13,
1847 15, 14, 13,
1848 16, 14, 15,
1849 17, 16, 15,
1850 18, 16, 17,
1851 19, 18, 17,
1852 20, 18, 19,
1853 21, 20, 19,
1854 22, 20, 21,
1855 23, 22, 21,
1856 22, 8, 10,
1857 10, 12, 14,
1858 14, 16, 18,
1859 18, 20, 22,
1860 22, 10, 14,
1861 14, 18, 22,
1862
1863 // Rectangle with disjoint corner segments.
1864 27, 25, 26,
1865 30, 28, 29,
1866 33, 31, 32,
1867 36, 34, 35,
1868 25, 27, 28,
1869 28, 30, 31,
1870 31, 33, 34,
1871 34, 36, 25,
1872 25, 28, 31,
1873 31, 34, 25,
1874
1875 // Same rectangle with disjoint corners, but with the interior arranged as a fan. Used by
1876 // mixed samples.
1877 27, 25, 26,
1878 30, 28, 29,
1879 33, 31, 32,
1880 36, 34, 35,
1881 27, 37, 25,
1882 28, 37, 27,
1883 30, 38, 28,
1884 31, 38, 30,
1885 33, 39, 31,
1886 34, 39, 33,
1887 36, 40, 34,
1888 25, 40, 36,
1889
1890 // Same rectangle with disjoint corners, with a border as well. Used by coverage AA.
1891 41, 25, 26,
1892 42, 41, 26,
1893 27, 42, 26,
1894 43, 28, 29,
1895 44, 43, 29,
1896 30, 44, 29,
1897 45, 31, 32,
1898 46, 45, 32,
1899 33, 46, 32,
1900 47, 34, 35,
1901 48, 47, 35,
1902 36, 48, 35,
1903 27, 28, 42,
1904 42, 28, 43,
1905 30, 31, 44,
1906 44, 31, 45,
1907 33, 34, 46,
1908 46, 34, 47,
1909 36, 25, 48,
1910 48, 25, 41,
1911 41, 42, 43,
1912 43, 44, 45,
1913 45, 46, 47,
1914 47, 48, 41,
1915 41, 43, 45,
1916 45, 47, 41,
1917
1918 // Same as the disjoint octagons, but with 16-gons instead. Used by coverage AA when the oval is
1919 // sufficiently large.
1920 49, 79, 80,
1921 50, 49, 80,
1922 51, 49, 50,
1923 52, 51, 50,
1924 53, 51, 52,
1925 54, 53, 52,
1926 55, 53, 54,
1927 56, 55, 54,
1928 57, 55, 56,
1929 58, 57, 56,
1930 59, 57, 58,
1931 60, 59, 58,
1932 61, 59, 60,
1933 62, 61, 60,
1934 63, 61, 62,
1935 64, 63, 62,
1936 65, 63, 64,
1937 66, 65, 64,
1938 67, 65, 66,
1939 68, 67, 66,
1940 69, 67, 68,
1941 70, 69, 68,
1942 71, 69, 70,
1943 72, 71, 70,
1944 73, 71, 72,
1945 74, 73, 72,
1946 75, 73, 74,
1947 76, 75, 74,
1948 77, 75, 76,
1949 78, 77, 76,
1950 79, 77, 78,
1951 80, 79, 78,
1952 49, 51, 53,
1953 53, 55, 57,
1954 57, 59, 61,
1955 61, 63, 65,
1956 65, 67, 69,
1957 69, 71, 73,
1958 73, 75, 77,
1959 77, 79, 49,
1960 49, 53, 57,
1961 57, 61, 65,
1962 65, 69, 73,
1963 73, 77, 49,
1964 49, 57, 65,
1965 65, 73, 49,
1966 };
1967
1968 enum {
1969 kRect_FirstIndex = 0,
1970 kRect_TriCount = 2,
1971
1972 kFramedRect_FirstIndex = 6,
1973 kFramedRect_TriCount = 10,
1974
1975 kOctagons_FirstIndex = 36,
1976 kOctagons_TriCount = 14,
1977
1978 kOctagonsFanned_FirstIndex = 78,
1979 kOctagonsFanned_TriCount = 16,
1980
1981 kDisjointOctagons_FirstIndex = 126,
1982 kDisjointOctagons_TriCount = 22,
1983
1984 kCorneredRect_FirstIndex = 192,
1985 kCorneredRect_TriCount = 10,
1986
1987 kCorneredRectFanned_FirstIndex = 222,
1988 kCorneredRectFanned_TriCount = 12,
1989
1990 kCorneredFramedRect_FirstIndex = 258,
1991 kCorneredFramedRect_TriCount = 26,
1992
1993 kDisjoint16Gons_FirstIndex = 336,
1994 kDisjoint16Gons_TriCount = 46,
1995 };
1996
1997 GR_DECLARE_STATIC_UNIQUE_KEY(gShapeVertexBufferKey);
1998
FindOrCreateVertexBuffer(GrGpu * gpu)1999 const GrBuffer* InstanceProcessor::FindOrCreateVertexBuffer(GrGpu* gpu) {
2000 GR_DEFINE_STATIC_UNIQUE_KEY(gShapeVertexBufferKey);
2001 GrResourceCache* cache = gpu->getContext()->getResourceCache();
2002 if (GrGpuResource* cached = cache->findAndRefUniqueResource(gShapeVertexBufferKey)) {
2003 return static_cast<GrBuffer*>(cached);
2004 }
2005 if (GrBuffer* buffer = gpu->createBuffer(sizeof(kVertexData), kVertex_GrBufferType,
2006 kStatic_GrAccessPattern, kVertexData)) {
2007 buffer->resourcePriv().setUniqueKey(gShapeVertexBufferKey);
2008 return buffer;
2009 }
2010 return nullptr;
2011 }
2012
2013 GR_DECLARE_STATIC_UNIQUE_KEY(gShapeIndexBufferKey);
2014
FindOrCreateIndex8Buffer(GrGpu * gpu)2015 const GrBuffer* InstanceProcessor::FindOrCreateIndex8Buffer(GrGpu* gpu) {
2016 GR_DEFINE_STATIC_UNIQUE_KEY(gShapeIndexBufferKey);
2017 GrResourceCache* cache = gpu->getContext()->getResourceCache();
2018 if (GrGpuResource* cached = cache->findAndRefUniqueResource(gShapeIndexBufferKey)) {
2019 return static_cast<GrBuffer*>(cached);
2020 }
2021 if (GrBuffer* buffer = gpu->createBuffer(sizeof(kIndexData), kIndex_GrBufferType,
2022 kStatic_GrAccessPattern, kIndexData)) {
2023 buffer->resourcePriv().setUniqueKey(gShapeIndexBufferKey);
2024 return buffer;
2025 }
2026 return nullptr;
2027 }
2028
GetIndexRangeForRect(GrAAType aaType)2029 IndexRange InstanceProcessor::GetIndexRangeForRect(GrAAType aaType) {
2030 switch (aaType) {
2031 case GrAAType::kCoverage:
2032 return {kFramedRect_FirstIndex, 3 * kFramedRect_TriCount};
2033 case GrAAType::kNone:
2034 case GrAAType::kMSAA:
2035 case GrAAType::kMixedSamples:
2036 return {kRect_FirstIndex, 3 * kRect_TriCount};
2037 }
2038 SkFAIL("Unexpected aa type!");
2039 return {0, 0};
2040 }
2041
GetIndexRangeForOval(GrAAType aaType,const SkRect & devBounds)2042 IndexRange InstanceProcessor::GetIndexRangeForOval(GrAAType aaType, const SkRect& devBounds) {
2043 if (GrAAType::kCoverage == aaType && devBounds.height() * devBounds.width() >= 256 * 256) {
2044 // This threshold was chosen quasi-scientifically on Tegra X1.
2045 return {kDisjoint16Gons_FirstIndex, 3 * kDisjoint16Gons_TriCount};
2046 }
2047
2048 switch (aaType) {
2049 case GrAAType::kNone:
2050 case GrAAType::kMSAA:
2051 return {kOctagons_FirstIndex, 3 * kOctagons_TriCount};
2052 case GrAAType::kCoverage:
2053 return {kDisjointOctagons_FirstIndex, 3 * kDisjointOctagons_TriCount};
2054 case GrAAType::kMixedSamples:
2055 return {kOctagonsFanned_FirstIndex, 3 * kOctagonsFanned_TriCount};
2056 }
2057 SkFAIL("Unexpected aa type!");
2058 return {0, 0};
2059 }
2060
GetIndexRangeForRRect(GrAAType aaType)2061 IndexRange InstanceProcessor::GetIndexRangeForRRect(GrAAType aaType) {
2062 switch (aaType) {
2063 case GrAAType::kNone:
2064 case GrAAType::kMSAA:
2065 return {kCorneredRect_FirstIndex, 3 * kCorneredRect_TriCount};
2066 case GrAAType::kCoverage:
2067 return {kCorneredFramedRect_FirstIndex, 3 * kCorneredFramedRect_TriCount};
2068 case GrAAType::kMixedSamples:
2069 return {kCorneredRectFanned_FirstIndex, 3 * kCorneredRectFanned_TriCount};
2070 }
2071 SkFAIL("Unexpected aa type!");
2072 return {0, 0};
2073 }
2074
GetNameOfIndexRange(IndexRange range)2075 const char* InstanceProcessor::GetNameOfIndexRange(IndexRange range) {
2076 switch (range.fStart) {
2077 case kRect_FirstIndex: return "basic_rect";
2078 case kFramedRect_FirstIndex: return "coverage_rect";
2079
2080 case kOctagons_FirstIndex: return "basic_oval";
2081 case kDisjointOctagons_FirstIndex: return "coverage_oval";
2082 case kDisjoint16Gons_FirstIndex: return "coverage_large_oval";
2083 case kOctagonsFanned_FirstIndex: return "mixed_samples_oval";
2084
2085 case kCorneredRect_FirstIndex: return "basic_round_rect";
2086 case kCorneredFramedRect_FirstIndex: return "coverage_round_rect";
2087 case kCorneredRectFanned_FirstIndex: return "mixed_samples_round_rect";
2088
2089 default: return "unknown";
2090 }
2091 }
2092
2093 }
2094