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