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