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