LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/instanced - InstanceProcessor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1008 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 82 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13