blob: 2ac5b8e8c89c5ae1a2f1952eb19974afd3690585 [file] [log] [blame]
csmartdaltona7f29642016-07-07 08:49:11 -07001/*
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"
Brian Salomon94efbf52016-11-29 13:43:05 -050014#include "GrShaderCaps.h"
csmartdaltona7f29642016-07-07 08:49:11 -070015#include "glsl/GrGLSLGeometryProcessor.h"
16#include "glsl/GrGLSLFragmentShaderBuilder.h"
17#include "glsl/GrGLSLProgramBuilder.h"
18#include "glsl/GrGLSLVarying.h"
19
20namespace gr_instanced {
21
Brian Salomon1edc5b92016-11-29 13:43:46 -050022GrCaps::InstancedSupport InstanceProcessor::CheckSupport(const GrShaderCaps& shaderCaps,
csmartdaltone0d36292016-07-29 08:14:20 -070023 const GrCaps& caps) {
Brian Salomon1edc5b92016-11-29 13:43:46 -050024 if (!shaderCaps.canUseAnyFunctionInShader() ||
25 !shaderCaps.flatInterpolationSupport() ||
26 !shaderCaps.integerSupport() ||
27 0 == shaderCaps.maxVertexSamplers() ||
csmartdaltona7f29642016-07-07 08:49:11 -070028 !caps.shaderCaps()->texelBufferSupport() ||
29 caps.maxVertexAttributes() < kNumAttribs) {
csmartdaltone0d36292016-07-29 08:14:20 -070030 return GrCaps::InstancedSupport::kNone;
csmartdaltona7f29642016-07-07 08:49:11 -070031 }
csmartdaltone0d36292016-07-29 08:14:20 -070032 if (!caps.sampleLocationsSupport() ||
Brian Salomon1edc5b92016-11-29 13:43:46 -050033 !shaderCaps.sampleVariablesSupport() ||
34 !shaderCaps.shaderDerivativeSupport()) {
csmartdaltone0d36292016-07-29 08:14:20 -070035 return GrCaps::InstancedSupport::kBasic;
csmartdaltona7f29642016-07-07 08:49:11 -070036 }
csmartdaltone0d36292016-07-29 08:14:20 -070037 if (0 == caps.maxRasterSamples() ||
Brian Salomon1edc5b92016-11-29 13:43:46 -050038 !shaderCaps.sampleMaskOverrideCoverageSupport()) {
csmartdaltone0d36292016-07-29 08:14:20 -070039 return GrCaps::InstancedSupport::kMultisampled;
40 }
41 return GrCaps::InstancedSupport::kMixedSampled;
csmartdaltona7f29642016-07-07 08:49:11 -070042}
43
Brian Salomon99ad1642016-12-16 09:50:45 -050044InstanceProcessor::InstanceProcessor(OpInfo opInfo, GrBuffer* paramsBuffer) : fOpInfo(opInfo) {
csmartdaltona7f29642016-07-07 08:49:11 -070045 this->initClassID<InstanceProcessor>();
46
bsalomon6cb807b2016-08-17 11:33:39 -070047 this->addVertexAttrib("shapeCoords", kVec2f_GrVertexAttribType, kHigh_GrSLPrecision);
48 this->addVertexAttrib("vertexAttrs", kInt_GrVertexAttribType);
49 this->addVertexAttrib("instanceInfo", kUint_GrVertexAttribType);
50 this->addVertexAttrib("shapeMatrixX", kVec3f_GrVertexAttribType, kHigh_GrSLPrecision);
51 this->addVertexAttrib("shapeMatrixY", kVec3f_GrVertexAttribType, kHigh_GrSLPrecision);
52 this->addVertexAttrib("color", kVec4f_GrVertexAttribType, kLow_GrSLPrecision);
53 this->addVertexAttrib("localRect", kVec4f_GrVertexAttribType, kHigh_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -070054
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
Brian Salomon99ad1642016-12-16 09:50:45 -050064 if (fOpInfo.fHasParams) {
csmartdaltona7f29642016-07-07 08:49:11 -070065 SkASSERT(paramsBuffer);
66 fParamsAccess.reset(kRGBA_float_GrPixelConfig, paramsBuffer, kVertex_GrShaderFlag);
67 this->addBufferAccess(&fParamsAccess);
68 }
69
Brian Salomon99ad1642016-12-16 09:50:45 -050070 if (fOpInfo.fAntialiasMode >= AntialiasMode::kMSAA) {
71 if (!fOpInfo.isSimpleRects() || AntialiasMode::kMixedSamples == fOpInfo.fAntialiasMode) {
csmartdaltona7f29642016-07-07 08:49:11 -070072 this->setWillUseSampleLocations();
73 }
74 }
75}
76
77class GLSLInstanceProcessor : public GrGLSLGeometryProcessor {
78public:
79 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override;
80
81private:
bsalomona624bf32016-09-20 09:12:47 -070082 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
83 FPCoordTransformIter&& transformIter) override {
84 this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
85 }
csmartdaltona7f29642016-07-07 08:49:11 -070086
87 class VertexInputs;
88 class Backend;
89 class BackendNonAA;
90 class BackendCoverage;
91 class BackendMultisample;
92
93 typedef GrGLSLGeometryProcessor INHERITED;
94};
95
Brian Salomon94efbf52016-11-29 13:43:05 -050096GrGLSLPrimitiveProcessor* InstanceProcessor::createGLSLInstance(const GrShaderCaps&) const {
csmartdaltona7f29642016-07-07 08:49:11 -070097 return new GLSLInstanceProcessor();
98}
99
100class GLSLInstanceProcessor::VertexInputs {
101public:
102 VertexInputs(const InstanceProcessor& instProc, GrGLSLVertexBuilder* vertexBuilder)
103 : fInstProc(instProc),
104 fVertexBuilder(vertexBuilder) {
105 }
106
107 void initParams(const SamplerHandle paramsBuffer) {
108 fParamsBuffer = paramsBuffer;
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500109 fVertexBuilder->codeAppendf("highp int paramsIdx = int(%s & 0x%x);",
ethannicholas5961bc92016-10-12 06:39:56 -0700110 this->attr(Attrib::kInstanceInfo),
111 kParamsIdx_InfoMask);
csmartdaltona7f29642016-07-07 08:49:11 -0700112 }
113
114 const char* attr(Attrib attr) const { return fInstProc.getAttrib((int)attr).fName; }
115
116 void fetchNextParam(GrSLType type = kVec4f_GrSLType) const {
117 SkASSERT(fParamsBuffer.isValid());
Ethan Nicholas84645e32017-02-09 13:57:14 -0500118 switch (type) {
119 case kVec2f_GrSLType: // fall through
120 case kVec3f_GrSLType: // fall through
121 case kVec4f_GrSLType:
122 break;
123 default:
124 fVertexBuilder->codeAppendf("%s(", GrGLSLTypeString(type));
csmartdaltona7f29642016-07-07 08:49:11 -0700125 }
126 fVertexBuilder->appendTexelFetch(fParamsBuffer, "paramsIdx++");
Ethan Nicholas84645e32017-02-09 13:57:14 -0500127 switch (type) {
128 case kVec2f_GrSLType:
129 fVertexBuilder->codeAppend(".xy");
130 break;
131 case kVec3f_GrSLType:
132 fVertexBuilder->codeAppend(".xyz");
133 break;
134 case kVec4f_GrSLType:
135 break;
136 default:
137 fVertexBuilder->codeAppend(")");
csmartdaltona7f29642016-07-07 08:49:11 -0700138 }
139 }
140
141 void skipParams(unsigned n) const {
142 SkASSERT(fParamsBuffer.isValid());
143 fVertexBuilder->codeAppendf("paramsIdx += %u;", n);
144 }
145
146private:
147 const InstanceProcessor& fInstProc;
148 GrGLSLVertexBuilder* fVertexBuilder;
149 SamplerHandle fParamsBuffer;
150};
151
152class GLSLInstanceProcessor::Backend {
153public:
Brian Salomon99ad1642016-12-16 09:50:45 -0500154 static Backend* SK_WARN_UNUSED_RESULT Create(const GrPipeline&, OpInfo, const VertexInputs&);
csmartdaltona7f29642016-07-07 08:49:11 -0700155 virtual ~Backend() {}
156
157 void init(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*);
158 virtual void setupRect(GrGLSLVertexBuilder*) = 0;
159 virtual void setupOval(GrGLSLVertexBuilder*) = 0;
csmartdalton0caee172016-07-13 08:48:53 -0700160 void setupRRect(GrGLSLVertexBuilder*, int* usedShapeDefinitions);
csmartdaltona7f29642016-07-07 08:49:11 -0700161
162 void initInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*);
163 virtual void setupInnerRect(GrGLSLVertexBuilder*) = 0;
164 virtual void setupInnerOval(GrGLSLVertexBuilder*) = 0;
csmartdalton0caee172016-07-13 08:48:53 -0700165 void setupInnerSimpleRRect(GrGLSLVertexBuilder*);
csmartdaltona7f29642016-07-07 08:49:11 -0700166
167 const char* outShapeCoords() {
168 return fModifiedShapeCoords ? fModifiedShapeCoords : fInputs.attr(Attrib::kShapeCoords);
169 }
170
171 void emitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char* outCoverage,
172 const char* outColor);
173
174protected:
Brian Salomon99ad1642016-12-16 09:50:45 -0500175 Backend(OpInfo opInfo, const VertexInputs& inputs)
176 : fOpInfo(opInfo)
177 , fInputs(inputs)
178 , fModifiesCoverage(false)
179 , fModifiesColor(false)
180 , fNeedsNeighborRadii(false)
181 , fColor(kVec4f_GrSLType)
182 , fTriangleIsArc(kInt_GrSLType)
183 , fArcCoords(kVec2f_GrSLType)
184 , fInnerShapeCoords(kVec2f_GrSLType)
185 , fInnerRRect(kVec4f_GrSLType)
186 , fModifiedShapeCoords(nullptr) {
187 if (fOpInfo.fShapeTypes & kRRect_ShapesMask) {
csmartdaltona7f29642016-07-07 08:49:11 -0700188 fModifiedShapeCoords = "adjustedShapeCoords";
189 }
190 }
191
192 virtual void onInit(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) = 0;
193 virtual void adjustRRectVertices(GrGLSLVertexBuilder*);
194 virtual void onSetupRRect(GrGLSLVertexBuilder*) {}
195
196 virtual void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) = 0;
csmartdalton0caee172016-07-13 08:48:53 -0700197 virtual void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) = 0;
csmartdaltona7f29642016-07-07 08:49:11 -0700198
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
Brian Salomon99ad1642016-12-16 09:50:45 -0500206 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;
csmartdaltona7f29642016-07-07 08:49:11 -0700217};
218
219void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
220 const GrPipeline& pipeline = args.fVertBuilder->getProgramBuilder()->pipeline();
221 const InstanceProcessor& ip = args.fGP.cast<InstanceProcessor>();
222 GrGLSLUniformHandler* uniHandler = args.fUniformHandler;
223 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
224 GrGLSLVertexBuilder* v = args.fVertBuilder;
225 GrGLSLPPFragmentBuilder* f = args.fFragBuilder;
226
227 varyingHandler->emitAttributes(ip);
228
229 VertexInputs inputs(ip, v);
Brian Salomon99ad1642016-12-16 09:50:45 -0500230 if (ip.opInfo().fHasParams) {
csmartdaltona7f29642016-07-07 08:49:11 -0700231 SkASSERT(1 == ip.numBuffers());
232 inputs.initParams(args.fBufferSamplers[0]);
233 }
234
Brian Salomon99ad1642016-12-16 09:50:45 -0500235 if (!ip.opInfo().fHasPerspective) {
csmartdaltona7f29642016-07-07 08:49:11 -0700236 v->codeAppendf("mat2x3 shapeMatrix = mat2x3(%s, %s);",
237 inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
238 } else {
ethannicholas5961bc92016-10-12 06:39:56 -0700239 v->defineConstantf("int", "PERSPECTIVE_FLAG", "0x%x", kPerspective_InfoFlag);
csmartdaltona7f29642016-07-07 08:49:11 -0700240 v->codeAppendf("mat3 shapeMatrix = mat3(%s, %s, vec3(0, 0, 1));",
241 inputs.attr(Attrib::kShapeMatrixX), inputs.attr(Attrib::kShapeMatrixY));
ethannicholas5961bc92016-10-12 06:39:56 -0700242 v->codeAppendf("if (0 != (%s & PERSPECTIVE_FLAG)) {",
csmartdaltona7f29642016-07-07 08:49:11 -0700243 inputs.attr(Attrib::kInstanceInfo));
244 v->codeAppend ( "shapeMatrix[2] = ");
245 inputs.fetchNextParam(kVec3f_GrSLType);
246 v->codeAppend ( ";");
247 v->codeAppend ("}");
248 }
249
Brian Salomon99ad1642016-12-16 09:50:45 -0500250 bool hasSingleShapeType = SkIsPow2(ip.opInfo().fShapeTypes);
csmartdaltona7f29642016-07-07 08:49:11 -0700251 if (!hasSingleShapeType) {
ethannicholas5961bc92016-10-12 06:39:56 -0700252 v->defineConstant("SHAPE_TYPE_BIT", kShapeType_InfoBit);
csmartdaltona7f29642016-07-07 08:49:11 -0700253 v->codeAppendf("uint shapeType = %s >> SHAPE_TYPE_BIT;",
254 inputs.attr(Attrib::kInstanceInfo));
255 }
256
Brian Salomon99ad1642016-12-16 09:50:45 -0500257 std::unique_ptr<Backend> backend(Backend::Create(pipeline, ip.opInfo(), inputs));
csmartdaltona7f29642016-07-07 08:49:11 -0700258 backend->init(varyingHandler, v);
259
csmartdalton0caee172016-07-13 08:48:53 -0700260 int usedShapeDefinitions = 0;
261
Brian Salomon99ad1642016-12-16 09:50:45 -0500262 if (hasSingleShapeType || !(ip.opInfo().fShapeTypes & ~kRRect_ShapesMask)) {
263 if (kRect_ShapeFlag == ip.opInfo().fShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700264 backend->setupRect(v);
Brian Salomon99ad1642016-12-16 09:50:45 -0500265 } else if (kOval_ShapeFlag == ip.opInfo().fShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700266 backend->setupOval(v);
267 } else {
csmartdalton0caee172016-07-13 08:48:53 -0700268 backend->setupRRect(v, &usedShapeDefinitions);
csmartdaltona7f29642016-07-07 08:49:11 -0700269 }
270 } else {
Brian Salomon99ad1642016-12-16 09:50:45 -0500271 if (ip.opInfo().fShapeTypes & kRRect_ShapesMask) {
csmartdalton0caee172016-07-13 08:48:53 -0700272 v->codeAppend ("if (shapeType >= SIMPLE_R_RECT_SHAPE_TYPE) {");
273 backend->setupRRect(v, &usedShapeDefinitions);
274 v->codeAppend ("}");
275 usedShapeDefinitions |= kSimpleRRect_ShapeFlag;
csmartdaltona7f29642016-07-07 08:49:11 -0700276 }
Brian Salomon99ad1642016-12-16 09:50:45 -0500277 if (ip.opInfo().fShapeTypes & kOval_ShapeFlag) {
278 if (ip.opInfo().fShapeTypes & kRect_ShapeFlag) {
279 if (ip.opInfo().fShapeTypes & kRRect_ShapesMask) {
csmartdalton0caee172016-07-13 08:48:53 -0700280 v->codeAppend ("else ");
281 }
282 v->codeAppend ("if (OVAL_SHAPE_TYPE == shapeType) {");
283 usedShapeDefinitions |= kOval_ShapeFlag;
284 } else {
285 v->codeAppend ("else {");
286 }
csmartdaltona7f29642016-07-07 08:49:11 -0700287 backend->setupOval(v);
csmartdalton0caee172016-07-13 08:48:53 -0700288 v->codeAppend ("}");
csmartdaltona7f29642016-07-07 08:49:11 -0700289 }
Brian Salomon99ad1642016-12-16 09:50:45 -0500290 if (ip.opInfo().fShapeTypes & kRect_ShapeFlag) {
csmartdalton0caee172016-07-13 08:48:53 -0700291 v->codeAppend ("else {");
292 backend->setupRect(v);
293 v->codeAppend ("}");
csmartdaltona7f29642016-07-07 08:49:11 -0700294 }
csmartdaltona7f29642016-07-07 08:49:11 -0700295 }
296
Brian Salomon99ad1642016-12-16 09:50:45 -0500297 if (ip.opInfo().fInnerShapeTypes) {
298 bool hasSingleInnerShapeType = SkIsPow2(ip.opInfo().fInnerShapeTypes);
csmartdaltona7f29642016-07-07 08:49:11 -0700299 if (!hasSingleInnerShapeType) {
ethannicholas5961bc92016-10-12 06:39:56 -0700300 v->defineConstantf("int", "INNER_SHAPE_TYPE_MASK", "0x%x", kInnerShapeType_InfoMask);
301 v->defineConstant("INNER_SHAPE_TYPE_BIT", kInnerShapeType_InfoBit);
csmartdaltona7f29642016-07-07 08:49:11 -0700302 v->codeAppendf("uint innerShapeType = ((%s & INNER_SHAPE_TYPE_MASK) >> "
303 "INNER_SHAPE_TYPE_BIT);",
304 inputs.attr(Attrib::kInstanceInfo));
305 }
306 // Here we take advantage of the fact that outerRect == localRect in recordDRRect.
307 v->codeAppendf("vec4 outer = %s;", inputs.attr(Attrib::kLocalRect));
308 v->codeAppend ("vec4 inner = ");
309 inputs.fetchNextParam();
310 v->codeAppend (";");
311 // outer2Inner is a transform from shape coords to inner shape coords:
312 // e.g. innerShapeCoords = shapeCoords * outer2Inner.xy + outer2Inner.zw
313 v->codeAppend ("vec4 outer2Inner = vec4(outer.zw - outer.xy, "
314 "outer.xy + outer.zw - inner.xy - inner.zw) / "
315 "(inner.zw - inner.xy).xyxy;");
316 v->codeAppendf("vec2 innerShapeCoords = %s * outer2Inner.xy + outer2Inner.zw;",
317 backend->outShapeCoords());
318
319 backend->initInnerShape(varyingHandler, v);
320
Brian Salomon99ad1642016-12-16 09:50:45 -0500321 SkASSERT(0 == (ip.opInfo().fInnerShapeTypes & kRRect_ShapesMask) ||
322 kSimpleRRect_ShapeFlag == (ip.opInfo().fInnerShapeTypes & kRRect_ShapesMask));
csmartdalton0caee172016-07-13 08:48:53 -0700323
csmartdaltona7f29642016-07-07 08:49:11 -0700324 if (hasSingleInnerShapeType) {
Brian Salomon99ad1642016-12-16 09:50:45 -0500325 if (kRect_ShapeFlag == ip.opInfo().fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700326 backend->setupInnerRect(v);
Brian Salomon99ad1642016-12-16 09:50:45 -0500327 } else if (kOval_ShapeFlag == ip.opInfo().fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700328 backend->setupInnerOval(v);
329 } else {
csmartdalton0caee172016-07-13 08:48:53 -0700330 backend->setupInnerSimpleRRect(v);
csmartdaltona7f29642016-07-07 08:49:11 -0700331 }
332 } else {
Brian Salomon99ad1642016-12-16 09:50:45 -0500333 if (ip.opInfo().fInnerShapeTypes & kSimpleRRect_ShapeFlag) {
csmartdalton0caee172016-07-13 08:48:53 -0700334 v->codeAppend ("if (SIMPLE_R_RECT_SHAPE_TYPE == innerShapeType) {");
335 backend->setupInnerSimpleRRect(v);
336 v->codeAppend("}");
337 usedShapeDefinitions |= kSimpleRRect_ShapeFlag;
csmartdaltona7f29642016-07-07 08:49:11 -0700338 }
Brian Salomon99ad1642016-12-16 09:50:45 -0500339 if (ip.opInfo().fInnerShapeTypes & kOval_ShapeFlag) {
340 if (ip.opInfo().fInnerShapeTypes & kRect_ShapeFlag) {
341 if (ip.opInfo().fInnerShapeTypes & kSimpleRRect_ShapeFlag) {
csmartdalton0caee172016-07-13 08:48:53 -0700342 v->codeAppend ("else ");
343 }
344 v->codeAppend ("if (OVAL_SHAPE_TYPE == innerShapeType) {");
345 usedShapeDefinitions |= kOval_ShapeFlag;
346 } else {
347 v->codeAppend ("else {");
348 }
csmartdaltona7f29642016-07-07 08:49:11 -0700349 backend->setupInnerOval(v);
csmartdalton0caee172016-07-13 08:48:53 -0700350 v->codeAppend("}");
csmartdaltona7f29642016-07-07 08:49:11 -0700351 }
Brian Salomon99ad1642016-12-16 09:50:45 -0500352 if (ip.opInfo().fInnerShapeTypes & kRect_ShapeFlag) {
csmartdalton0caee172016-07-13 08:48:53 -0700353 v->codeAppend("else {");
354 backend->setupInnerRect(v);
355 v->codeAppend("}");
csmartdaltona7f29642016-07-07 08:49:11 -0700356 }
csmartdaltona7f29642016-07-07 08:49:11 -0700357 }
358 }
359
csmartdalton0caee172016-07-13 08:48:53 -0700360 if (usedShapeDefinitions & kOval_ShapeFlag) {
ethannicholas5961bc92016-10-12 06:39:56 -0700361 v->defineConstant("OVAL_SHAPE_TYPE", (int)ShapeType::kOval);
csmartdaltona7f29642016-07-07 08:49:11 -0700362 }
csmartdalton0caee172016-07-13 08:48:53 -0700363 if (usedShapeDefinitions & kSimpleRRect_ShapeFlag) {
ethannicholas5961bc92016-10-12 06:39:56 -0700364 v->defineConstant("SIMPLE_R_RECT_SHAPE_TYPE", (int)ShapeType::kSimpleRRect);
csmartdalton0caee172016-07-13 08:48:53 -0700365 }
366 if (usedShapeDefinitions & kNinePatch_ShapeFlag) {
ethannicholas5961bc92016-10-12 06:39:56 -0700367 v->defineConstant("NINE_PATCH_SHAPE_TYPE", (int)ShapeType::kNinePatch);
csmartdalton0caee172016-07-13 08:48:53 -0700368 }
369 SkASSERT(!(usedShapeDefinitions & (kRect_ShapeFlag | kComplexRRect_ShapeFlag)));
csmartdaltona7f29642016-07-07 08:49:11 -0700370
Brian Salomon8c852be2017-01-04 10:44:42 -0500371 backend->emitCode(v, f, args.fOutputCoverage, args.fOutputColor);
csmartdaltona7f29642016-07-07 08:49:11 -0700372
373 const char* localCoords = nullptr;
Brian Salomon99ad1642016-12-16 09:50:45 -0500374 if (ip.opInfo().fUsesLocalCoords) {
csmartdaltona7f29642016-07-07 08:49:11 -0700375 localCoords = "localCoords";
376 v->codeAppendf("vec2 t = 0.5 * (%s + vec2(1));", backend->outShapeCoords());
377 v->codeAppendf("vec2 localCoords = (1.0 - t) * %s.xy + t * %s.zw;",
378 inputs.attr(Attrib::kLocalRect), inputs.attr(Attrib::kLocalRect));
379 }
Brian Salomon99ad1642016-12-16 09:50:45 -0500380 if (ip.opInfo().fHasLocalMatrix && ip.opInfo().fHasParams) {
ethannicholas5961bc92016-10-12 06:39:56 -0700381 v->defineConstantf("int", "LOCAL_MATRIX_FLAG", "0x%x", kLocalMatrix_InfoFlag);
382 v->codeAppendf("if (0 != (%s & LOCAL_MATRIX_FLAG)) {",
csmartdaltona7f29642016-07-07 08:49:11 -0700383 inputs.attr(Attrib::kInstanceInfo));
Brian Salomon99ad1642016-12-16 09:50:45 -0500384 if (!ip.opInfo().fUsesLocalCoords) {
csmartdaltona7f29642016-07-07 08:49:11 -0700385 inputs.skipParams(2);
386 } else {
387 v->codeAppendf( "mat2x3 localMatrix;");
388 v->codeAppend ( "localMatrix[0] = ");
389 inputs.fetchNextParam(kVec3f_GrSLType);
390 v->codeAppend ( ";");
391 v->codeAppend ( "localMatrix[1] = ");
392 inputs.fetchNextParam(kVec3f_GrSLType);
393 v->codeAppend ( ";");
394 v->codeAppend ( "localCoords = (vec3(localCoords, 1) * localMatrix).xy;");
395 }
396 v->codeAppend("}");
397 }
398
Brian Salomon99ad1642016-12-16 09:50:45 -0500399 GrSLType positionType = ip.opInfo().fHasPerspective ? kVec3f_GrSLType : kVec2f_GrSLType;
csmartdaltona7f29642016-07-07 08:49:11 -0700400 v->codeAppendf("%s deviceCoords = vec3(%s, 1) * shapeMatrix;",
401 GrGLSLTypeString(positionType), backend->outShapeCoords());
402 gpArgs->fPositionVar.set(positionType, "deviceCoords");
403
404 this->emitTransforms(v, varyingHandler, uniHandler, gpArgs->fPositionVar, localCoords,
bsalomona624bf32016-09-20 09:12:47 -0700405 args.fFPCoordTransformHandler);
csmartdaltona7f29642016-07-07 08:49:11 -0700406}
407
408////////////////////////////////////////////////////////////////////////////////////////////////////
409
410void GLSLInstanceProcessor::Backend::init(GrGLSLVaryingHandler* varyingHandler,
411 GrGLSLVertexBuilder* v) {
412 if (fModifiedShapeCoords) {
413 v->codeAppendf("vec2 %s = %s;", fModifiedShapeCoords, fInputs.attr(Attrib::kShapeCoords));
414 }
415
416 this->onInit(varyingHandler, v);
417
418 if (!fColor.vsOut()) {
419 varyingHandler->addFlatVarying("color", &fColor, kLow_GrSLPrecision);
420 v->codeAppendf("%s = %s;", fColor.vsOut(), fInputs.attr(Attrib::kColor));
421 }
422}
423
csmartdalton0caee172016-07-13 08:48:53 -0700424void GLSLInstanceProcessor::Backend::setupRRect(GrGLSLVertexBuilder* v, int* usedShapeDefinitions) {
csmartdaltona7f29642016-07-07 08:49:11 -0700425 v->codeAppendf("uvec2 corner = uvec2(%s & 1, (%s >> 1) & 1);",
426 fInputs.attr(Attrib::kVertexAttrs), fInputs.attr(Attrib::kVertexAttrs));
427 v->codeAppend ("vec2 cornerSign = vec2(corner) * 2.0 - 1.0;");
428 v->codeAppendf("vec2 radii%s;", fNeedsNeighborRadii ? ", neighborRadii" : "");
429 v->codeAppend ("mat2 p = ");
430 fInputs.fetchNextParam(kMat22f_GrSLType);
431 v->codeAppend (";");
Brian Salomon99ad1642016-12-16 09:50:45 -0500432 uint8_t types = fOpInfo.fShapeTypes & kRRect_ShapesMask;
csmartdaltona7f29642016-07-07 08:49:11 -0700433 if (0 == (types & (types - 1))) {
434 if (kSimpleRRect_ShapeFlag == types) {
435 this->setupSimpleRadii(v);
436 } else if (kNinePatch_ShapeFlag == types) {
437 this->setupNinePatchRadii(v);
438 } else if (kComplexRRect_ShapeFlag == types) {
439 this->setupComplexRadii(v);
440 }
441 } else {
csmartdaltona7f29642016-07-07 08:49:11 -0700442 if (types & kSimpleRRect_ShapeFlag) {
csmartdalton0caee172016-07-13 08:48:53 -0700443 v->codeAppend ("if (SIMPLE_R_RECT_SHAPE_TYPE == shapeType) {");
csmartdaltona7f29642016-07-07 08:49:11 -0700444 this->setupSimpleRadii(v);
csmartdalton0caee172016-07-13 08:48:53 -0700445 v->codeAppend ("}");
446 *usedShapeDefinitions |= kSimpleRRect_ShapeFlag;
csmartdaltona7f29642016-07-07 08:49:11 -0700447 }
448 if (types & kNinePatch_ShapeFlag) {
csmartdalton0caee172016-07-13 08:48:53 -0700449 if (types & kComplexRRect_ShapeFlag) {
450 if (types & kSimpleRRect_ShapeFlag) {
451 v->codeAppend ("else ");
452 }
453 v->codeAppend ("if (NINE_PATCH_SHAPE_TYPE == shapeType) {");
454 *usedShapeDefinitions |= kNinePatch_ShapeFlag;
455 } else {
456 v->codeAppend ("else {");
457 }
csmartdaltona7f29642016-07-07 08:49:11 -0700458 this->setupNinePatchRadii(v);
csmartdalton0caee172016-07-13 08:48:53 -0700459 v->codeAppend ("}");
csmartdaltona7f29642016-07-07 08:49:11 -0700460 }
461 if (types & kComplexRRect_ShapeFlag) {
csmartdalton0caee172016-07-13 08:48:53 -0700462 v->codeAppend ("else {");
csmartdaltona7f29642016-07-07 08:49:11 -0700463 this->setupComplexRadii(v);
csmartdalton0caee172016-07-13 08:48:53 -0700464 v->codeAppend ("}");
csmartdaltona7f29642016-07-07 08:49:11 -0700465 }
csmartdaltona7f29642016-07-07 08:49:11 -0700466 }
467
468 this->adjustRRectVertices(v);
469
470 if (fArcCoords.vsOut()) {
471 v->codeAppendf("%s = (cornerSign * %s + radii - vec2(1)) / radii;",
472 fArcCoords.vsOut(), fModifiedShapeCoords);
473 }
474 if (fTriangleIsArc.vsOut()) {
475 v->codeAppendf("%s = int(all(equal(vec2(1), abs(%s))));",
476 fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kShapeCoords));
477 }
478
479 this->onSetupRRect(v);
480}
481
482void GLSLInstanceProcessor::Backend::setupSimpleRadii(GrGLSLVertexBuilder* v) {
483 if (fNeedsNeighborRadii) {
484 v->codeAppend ("neighborRadii = ");
485 }
486 v->codeAppend("radii = p[0] * 2.0 / p[1];");
487}
488
489void GLSLInstanceProcessor::Backend::setupNinePatchRadii(GrGLSLVertexBuilder* v) {
490 v->codeAppend("radii = vec2(p[0][corner.x], p[1][corner.y]);");
491 if (fNeedsNeighborRadii) {
492 v->codeAppend("neighborRadii = vec2(p[0][1u - corner.x], p[1][1u - corner.y]);");
493 }
494}
495
496void GLSLInstanceProcessor::Backend::setupComplexRadii(GrGLSLVertexBuilder* v) {
497 /**
498 * The x and y radii of each arc are stored in separate vectors,
499 * in the following order:
500 *
501 * __x1 _ _ _ x3__
502 *
503 * y1 | | y2
504 *
505 * | |
506 *
507 * y3 |__ _ _ _ __| y4
508 * x2 x4
509 *
510 */
511 v->codeAppend("mat2 p2 = ");
512 fInputs.fetchNextParam(kMat22f_GrSLType);
513 v->codeAppend(";");
514 v->codeAppend("radii = vec2(p[corner.x][corner.y], p2[corner.y][corner.x]);");
515 if (fNeedsNeighborRadii) {
516 v->codeAppend("neighborRadii = vec2(p[1u - corner.x][corner.y], "
517 "p2[1u - corner.y][corner.x]);");
518 }
519}
520
521void GLSLInstanceProcessor::Backend::adjustRRectVertices(GrGLSLVertexBuilder* v) {
522 // Resize the 4 triangles that arcs are drawn into so they match their corresponding radii.
523 // 0.5 is a special value that indicates the edge of an arc triangle.
524 v->codeAppendf("if (abs(%s.x) == 0.5)"
525 "%s.x = cornerSign.x * (1.0 - radii.x);",
526 fInputs.attr(Attrib::kShapeCoords), fModifiedShapeCoords);
527 v->codeAppendf("if (abs(%s.y) == 0.5) "
528 "%s.y = cornerSign.y * (1.0 - radii.y);",
529 fInputs.attr(Attrib::kShapeCoords), fModifiedShapeCoords);
530}
531
532void GLSLInstanceProcessor::Backend::initInnerShape(GrGLSLVaryingHandler* varyingHandler,
533 GrGLSLVertexBuilder* v) {
Brian Salomon99ad1642016-12-16 09:50:45 -0500534 SkASSERT(!(fOpInfo.fInnerShapeTypes & (kNinePatch_ShapeFlag | kComplexRRect_ShapeFlag)));
csmartdaltona7f29642016-07-07 08:49:11 -0700535
536 this->onInitInnerShape(varyingHandler, v);
537
538 if (fInnerShapeCoords.vsOut()) {
539 v->codeAppendf("%s = innerShapeCoords;", fInnerShapeCoords.vsOut());
540 }
541}
542
csmartdalton0caee172016-07-13 08:48:53 -0700543void GLSLInstanceProcessor::Backend::setupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
csmartdaltona7f29642016-07-07 08:49:11 -0700544 v->codeAppend("mat2 innerP = ");
545 fInputs.fetchNextParam(kMat22f_GrSLType);
546 v->codeAppend(";");
547 v->codeAppend("vec2 innerRadii = innerP[0] * 2.0 / innerP[1];");
csmartdalton0caee172016-07-13 08:48:53 -0700548 this->onSetupInnerSimpleRRect(v);
csmartdaltona7f29642016-07-07 08:49:11 -0700549}
550
551void GLSLInstanceProcessor::Backend::emitCode(GrGLSLVertexBuilder* v, GrGLSLPPFragmentBuilder* f,
552 const char* outCoverage, const char* outColor) {
553 SkASSERT(!fModifiesCoverage || outCoverage);
554 this->onEmitCode(v, f, fModifiesCoverage ? outCoverage : nullptr,
555 fModifiesColor ? outColor : nullptr);
556 if (outCoverage && !fModifiesCoverage) {
557 // Even though the subclass doesn't use coverage, we are expected to assign some value.
558 f->codeAppendf("%s = vec4(1);", outCoverage);
559 }
560 if (!fModifiesColor) {
561 // The subclass didn't assign a value to the output color.
562 f->codeAppendf("%s = %s;", outColor, fColor.fsIn());
563 }
564}
565
566////////////////////////////////////////////////////////////////////////////////////////////////////
567
568class GLSLInstanceProcessor::BackendNonAA : public Backend {
569public:
Brian Salomon99ad1642016-12-16 09:50:45 -0500570 BackendNonAA(OpInfo opInfo, const VertexInputs& inputs) : INHERITED(opInfo, inputs) {
571 if (fOpInfo.fCannotDiscard && !fOpInfo.isSimpleRects()) {
572 fModifiesColor = !fOpInfo.fCannotTweakAlphaForCoverage;
csmartdaltona7f29642016-07-07 08:49:11 -0700573 fModifiesCoverage = !fModifiesColor;
574 }
575 }
576
577private:
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;
csmartdalton0caee172016-07-13 08:48:53 -0700585 void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) override;
csmartdaltona7f29642016-07-07 08:49:11 -0700586
587 void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char*,
588 const char*) override;
589
590 typedef Backend INHERITED;
591};
592
593void GLSLInstanceProcessor::BackendNonAA::onInit(GrGLSLVaryingHandler* varyingHandler,
594 GrGLSLVertexBuilder*) {
Brian Salomon99ad1642016-12-16 09:50:45 -0500595 if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
csmartdaltondd57dd72016-07-13 08:59:52 -0700596 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -0700597 varyingHandler->addVarying("arcCoords", &fArcCoords, kMedium_GrSLPrecision);
598 }
599}
600
601void GLSLInstanceProcessor::BackendNonAA::setupRect(GrGLSLVertexBuilder* v) {
602 if (fTriangleIsArc.vsOut()) {
603 v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
604 }
605}
606
607void GLSLInstanceProcessor::BackendNonAA::setupOval(GrGLSLVertexBuilder* v) {
608 SkASSERT(fArcCoords.vsOut());
609 SkASSERT(fTriangleIsArc.vsOut());
610 v->codeAppendf("%s = %s;", fArcCoords.vsOut(), this->outShapeCoords());
611 v->codeAppendf("%s = %s & 1;", fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kVertexAttrs));
612}
613
614void GLSLInstanceProcessor::BackendNonAA::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
615 GrGLSLVertexBuilder*) {
616 varyingHandler->addVarying("innerShapeCoords", &fInnerShapeCoords, kMedium_GrSLPrecision);
Brian Salomon99ad1642016-12-16 09:50:45 -0500617 if (kRect_ShapeFlag != fOpInfo.fInnerShapeTypes &&
618 kOval_ShapeFlag != fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700619 varyingHandler->addFlatVarying("innerRRect", &fInnerRRect, kMedium_GrSLPrecision);
620 }
621}
622
623void GLSLInstanceProcessor::BackendNonAA::setupInnerRect(GrGLSLVertexBuilder* v) {
624 if (fInnerRRect.vsOut()) {
625 v->codeAppendf("%s = vec4(1);", fInnerRRect.vsOut());
626 }
627}
628
629void GLSLInstanceProcessor::BackendNonAA::setupInnerOval(GrGLSLVertexBuilder* v) {
630 if (fInnerRRect.vsOut()) {
631 v->codeAppendf("%s = vec4(0, 0, 1, 1);", fInnerRRect.vsOut());
632 }
633}
634
csmartdalton0caee172016-07-13 08:48:53 -0700635void GLSLInstanceProcessor::BackendNonAA::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
csmartdaltona7f29642016-07-07 08:49:11 -0700636 v->codeAppendf("%s = vec4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
637}
638
639void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
640 GrGLSLPPFragmentBuilder* f,
641 const char* outCoverage,
642 const char* outColor) {
643 const char* dropFragment = nullptr;
Brian Salomon99ad1642016-12-16 09:50:45 -0500644 if (!fOpInfo.fCannotDiscard) {
csmartdaltona7f29642016-07-07 08:49:11 -0700645 dropFragment = "discard";
646 } else if (fModifiesCoverage) {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500647 f->codeAppend ("lowp float covered = 1.0;");
csmartdaltona7f29642016-07-07 08:49:11 -0700648 dropFragment = "covered = 0.0";
649 } else if (fModifiesColor) {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500650 f->codeAppendf("lowp vec4 color = %s;", fColor.fsIn());
csmartdaltona7f29642016-07-07 08:49:11 -0700651 dropFragment = "color = vec4(0)";
652 }
653 if (fTriangleIsArc.fsIn()) {
654 SkASSERT(dropFragment);
655 f->codeAppendf("if (%s != 0 && dot(%s, %s) > 1.0) %s;",
656 fTriangleIsArc.fsIn(), fArcCoords.fsIn(), fArcCoords.fsIn(), dropFragment);
657 }
Brian Salomon99ad1642016-12-16 09:50:45 -0500658 if (fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700659 SkASSERT(dropFragment);
660 f->codeAppendf("// Inner shape.\n");
Brian Salomon99ad1642016-12-16 09:50:45 -0500661 if (kRect_ShapeFlag == fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700662 f->codeAppendf("if (all(lessThanEqual(abs(%s), vec2(1)))) %s;",
663 fInnerShapeCoords.fsIn(), dropFragment);
Brian Salomon99ad1642016-12-16 09:50:45 -0500664 } else if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700665 f->codeAppendf("if ((dot(%s, %s) <= 1.0)) %s;",
666 fInnerShapeCoords.fsIn(), fInnerShapeCoords.fsIn(), dropFragment);
667 } else {
668 f->codeAppendf("if (all(lessThan(abs(%s), vec2(1)))) {", fInnerShapeCoords.fsIn());
669 f->codeAppendf( "vec2 distanceToArcEdge = abs(%s) - %s.xy;",
670 fInnerShapeCoords.fsIn(), fInnerRRect.fsIn());
671 f->codeAppend ( "if (any(lessThan(distanceToArcEdge, vec2(0)))) {");
672 f->codeAppendf( "%s;", dropFragment);
673 f->codeAppend ( "} else {");
674 f->codeAppendf( "vec2 rrectCoords = distanceToArcEdge * %s.zw;",
675 fInnerRRect.fsIn());
676 f->codeAppend ( "if (dot(rrectCoords, rrectCoords) <= 1.0) {");
677 f->codeAppendf( "%s;", dropFragment);
678 f->codeAppend ( "}");
679 f->codeAppend ( "}");
680 f->codeAppend ("}");
681 }
682 }
683 if (fModifiesCoverage) {
684 f->codeAppendf("%s = vec4(covered);", outCoverage);
685 } else if (fModifiesColor) {
686 f->codeAppendf("%s = color;", outColor);
687 }
688}
689
690////////////////////////////////////////////////////////////////////////////////////////////////////
691
692class GLSLInstanceProcessor::BackendCoverage : public Backend {
693public:
Brian Salomon99ad1642016-12-16 09:50:45 -0500694 BackendCoverage(OpInfo opInfo, const VertexInputs& inputs)
695 : INHERITED(opInfo, inputs)
696 , fColorTimesRectCoverage(kVec4f_GrSLType)
697 , fRectCoverage(kFloat_GrSLType)
698 , fEllipseCoords(kVec2f_GrSLType)
699 , fEllipseName(kVec2f_GrSLType)
700 , fBloatedRadius(kFloat_GrSLType)
701 , fDistanceToInnerEdge(kVec2f_GrSLType)
702 , fInnerShapeBloatedHalfSize(kVec2f_GrSLType)
703 , fInnerEllipseCoords(kVec2f_GrSLType)
704 , fInnerEllipseName(kVec2f_GrSLType) {
705 fShapeIsCircle = !fOpInfo.fNonSquare && !(fOpInfo.fShapeTypes & kRRect_ShapesMask);
706 fTweakAlphaForCoverage = !fOpInfo.fCannotTweakAlphaForCoverage && !fOpInfo.fInnerShapeTypes;
csmartdaltona7f29642016-07-07 08:49:11 -0700707 fModifiesCoverage = !fTweakAlphaForCoverage;
708 fModifiesColor = fTweakAlphaForCoverage;
709 fModifiedShapeCoords = "bloatedShapeCoords";
710 }
711
712private:
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;
csmartdalton0caee172016-07-13 08:48:53 -0700722 void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) override;
csmartdaltona7f29642016-07-07 08:49:11 -0700723
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
749void GLSLInstanceProcessor::BackendCoverage::onInit(GrGLSLVaryingHandler* varyingHandler,
750 GrGLSLVertexBuilder* v) {
751 v->codeAppend ("mat2 shapeTransposeMatrix = transpose(mat2(shapeMatrix));");
752 v->codeAppend ("vec2 shapeHalfSize = vec2(length(shapeTransposeMatrix[0]), "
753 "length(shapeTransposeMatrix[1]));");
754 v->codeAppend ("vec2 bloat = 0.5 / shapeHalfSize;");
755 v->codeAppendf("bloatedShapeCoords = %s * (1.0 + bloat);", fInputs.attr(Attrib::kShapeCoords));
756
Brian Salomon99ad1642016-12-16 09:50:45 -0500757 if (kOval_ShapeFlag != fOpInfo.fShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700758 if (fTweakAlphaForCoverage) {
759 varyingHandler->addVarying("colorTimesRectCoverage", &fColorTimesRectCoverage,
760 kLow_GrSLPrecision);
Brian Salomon99ad1642016-12-16 09:50:45 -0500761 if (kRect_ShapeFlag == fOpInfo.fShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700762 fColor = fColorTimesRectCoverage;
763 }
764 } else {
765 varyingHandler->addVarying("rectCoverage", &fRectCoverage, kLow_GrSLPrecision);
766 }
767 v->codeAppend("float rectCoverage = 0.0;");
768 }
Brian Salomon99ad1642016-12-16 09:50:45 -0500769 if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
csmartdaltondd57dd72016-07-13 08:59:52 -0700770 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -0700771 if (!fShapeIsCircle) {
csmartdaltondd57dd72016-07-13 08:59:52 -0700772 varyingHandler->addVarying("ellipseCoords", &fEllipseCoords, kMedium_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -0700773 varyingHandler->addFlatVarying("ellipseName", &fEllipseName, kHigh_GrSLPrecision);
774 } else {
csmartdaltone0d36292016-07-29 08:14:20 -0700775 varyingHandler->addVarying("circleCoords", &fEllipseCoords, kHigh_GrSLPrecision);
776 varyingHandler->addFlatVarying("bloatedRadius", &fBloatedRadius, kHigh_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -0700777 }
778 }
779}
780
781void GLSLInstanceProcessor::BackendCoverage::setupRect(GrGLSLVertexBuilder* v) {
782 // Make the border one pixel wide. Inner vs outer is indicated by coordAttrs.
783 v->codeAppendf("vec2 rectBloat = (%s != 0) ? bloat : -bloat;",
784 fInputs.attr(Attrib::kVertexAttrs));
785 // Here we use the absolute value, because when the rect is thinner than a pixel, this makes it
786 // mark the spot where pixel center is within half a pixel of the *opposite* edge. This,
787 // combined with the "maxCoverage" logic below gives us mathematically correct coverage even for
788 // subpixel rectangles.
789 v->codeAppendf("bloatedShapeCoords = %s * abs(vec2(1.0 + rectBloat));",
790 fInputs.attr(Attrib::kShapeCoords));
791
792 // Determine coverage at the vertex. Coverage naturally ramps from 0 to 1 unless the rect is
793 // narrower than a pixel.
794 v->codeAppend ("float maxCoverage = 4.0 * min(0.5, shapeHalfSize.x) *"
795 "min(0.5, shapeHalfSize.y);");
796 v->codeAppendf("rectCoverage = (%s != 0) ? 0.0 : maxCoverage;",
797 fInputs.attr(Attrib::kVertexAttrs));
798
799 if (fTriangleIsArc.vsOut()) {
800 v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
801 }
802}
803
804void GLSLInstanceProcessor::BackendCoverage::setupOval(GrGLSLVertexBuilder* v) {
805 // Offset the inner and outer octagons by one pixel. Inner vs outer is indicated by coordAttrs.
806 v->codeAppendf("vec2 ovalBloat = (%s != 0) ? bloat : -bloat;",
807 fInputs.attr(Attrib::kVertexAttrs));
808 v->codeAppendf("bloatedShapeCoords = %s * max(vec2(1.0 + ovalBloat), vec2(0));",
809 fInputs.attr(Attrib::kShapeCoords));
810 v->codeAppendf("%s = bloatedShapeCoords * shapeHalfSize;", fEllipseCoords.vsOut());
811 if (fEllipseName.vsOut()) {
812 v->codeAppendf("%s = 1.0 / (shapeHalfSize * shapeHalfSize);", fEllipseName.vsOut());
813 }
814 if (fBloatedRadius.vsOut()) {
815 SkASSERT(fShapeIsCircle);
816 v->codeAppendf("%s = shapeHalfSize.x + 0.5;", fBloatedRadius.vsOut());
817 }
818 if (fTriangleIsArc.vsOut()) {
819 v->codeAppendf("%s = int(%s != 0);",
820 fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kVertexAttrs));
821 }
822 if (fColorTimesRectCoverage.vsOut() || fRectCoverage.vsOut()) {
823 v->codeAppendf("rectCoverage = 1.0;");
824 }
825}
826
827void GLSLInstanceProcessor::BackendCoverage::adjustRRectVertices(GrGLSLVertexBuilder* v) {
828 // We try to let the AA borders line up with the arc edges on their particular side, but we
829 // can't allow them to get closer than one half pixel to the edge or they might overlap with
830 // their neighboring border.
831 v->codeAppend("vec2 innerEdge = max(1.0 - bloat, vec2(0));");
832 v->codeAppend ("vec2 borderEdge = cornerSign * clamp(1.0 - radii, -innerEdge, innerEdge);");
833 // 0.5 is a special value that indicates this vertex is an arc edge.
834 v->codeAppendf("if (abs(%s.x) == 0.5)"
835 "bloatedShapeCoords.x = borderEdge.x;", fInputs.attr(Attrib::kShapeCoords));
836 v->codeAppendf("if (abs(%s.y) == 0.5)"
837 "bloatedShapeCoords.y = borderEdge.y;", fInputs.attr(Attrib::kShapeCoords));
838
839 // Adjust the interior border vertices to make the border one pixel wide. 0.75 is a special
840 // value to indicate these points.
841 v->codeAppendf("if (abs(%s.x) == 0.75) "
842 "bloatedShapeCoords.x = cornerSign.x * innerEdge.x;",
843 fInputs.attr(Attrib::kShapeCoords));
844 v->codeAppendf("if (abs(%s.y) == 0.75) "
845 "bloatedShapeCoords.y = cornerSign.y * innerEdge.y;",
846 fInputs.attr(Attrib::kShapeCoords));
847}
848
849void GLSLInstanceProcessor::BackendCoverage::onSetupRRect(GrGLSLVertexBuilder* v) {
850 // The geometry is laid out in such a way that rectCoverage will be 0 and 1 on the vertices, but
851 // we still need to recompute this value because when the rrect gets thinner than one pixel, the
852 // interior edge of the border will necessarily clamp, and we need to match the AA behavior of
853 // the arc segments (i.e. distance from bloated edge only; ignoring the fact that the pixel
854 // actully has less coverage because it's not completely inside the opposite edge.)
855 v->codeAppend("vec2 d = shapeHalfSize + 0.5 - abs(bloatedShapeCoords) * shapeHalfSize;");
856 v->codeAppend("rectCoverage = min(d.x, d.y);");
857
858 SkASSERT(!fShapeIsCircle);
859 // The AA border does not get closer than one half pixel to the edge of the rect, so to get a
860 // smooth transition from flat edge to arc, we don't allow the radii to be smaller than one half
861 // pixel. (We don't worry about the transition on the opposite side when a radius is so large
862 // that the border clamped on that side.)
863 v->codeAppendf("vec2 clampedRadii = max(radii, bloat);");
864 v->codeAppendf("%s = (cornerSign * bloatedShapeCoords + clampedRadii - vec2(1)) * "
865 "shapeHalfSize;", fEllipseCoords.vsOut());
866 v->codeAppendf("%s = 1.0 / (clampedRadii * clampedRadii * shapeHalfSize * shapeHalfSize);",
867 fEllipseName.vsOut());
868}
869
870void GLSLInstanceProcessor::BackendCoverage::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
871 GrGLSLVertexBuilder* v) {
872 v->codeAppend("vec2 innerShapeHalfSize = shapeHalfSize / outer2Inner.xy;");
873
Brian Salomon99ad1642016-12-16 09:50:45 -0500874 if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700875 varyingHandler->addVarying("innerEllipseCoords", &fInnerEllipseCoords,
876 kMedium_GrSLPrecision);
csmartdaltondd57dd72016-07-13 08:59:52 -0700877 varyingHandler->addFlatVarying("innerEllipseName", &fInnerEllipseName, kHigh_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -0700878 } else {
879 varyingHandler->addVarying("distanceToInnerEdge", &fDistanceToInnerEdge,
880 kMedium_GrSLPrecision);
881 varyingHandler->addFlatVarying("innerShapeBloatedHalfSize", &fInnerShapeBloatedHalfSize,
882 kMedium_GrSLPrecision);
Brian Salomon99ad1642016-12-16 09:50:45 -0500883 if (kRect_ShapeFlag != fOpInfo.fInnerShapeTypes) {
csmartdaltondd57dd72016-07-13 08:59:52 -0700884 varyingHandler->addVarying("innerShapeCoords", &fInnerShapeCoords,
885 kMedium_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -0700886 varyingHandler->addFlatVarying("innerEllipseName", &fInnerEllipseName,
csmartdaltondd57dd72016-07-13 08:59:52 -0700887 kHigh_GrSLPrecision);
888 varyingHandler->addFlatVarying("innerRRect", &fInnerRRect, kMedium_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -0700889 }
890 }
891}
892
893void GLSLInstanceProcessor::BackendCoverage::setupInnerRect(GrGLSLVertexBuilder* v) {
894 if (fInnerRRect.vsOut()) {
895 // The fragment shader will generalize every inner shape as a round rect. Since this one
896 // is a rect, we simply emit bogus parameters for the round rect (effectively negative
897 // radii) that ensure the fragment shader always takes the "emitRect" codepath.
898 v->codeAppendf("%s.xy = abs(outer2Inner.xy) * (1.0 + bloat) + abs(outer2Inner.zw);",
899 fInnerRRect.vsOut());
900 }
901}
902
903void GLSLInstanceProcessor::BackendCoverage::setupInnerOval(GrGLSLVertexBuilder* v) {
904 v->codeAppendf("%s = 1.0 / (innerShapeHalfSize * innerShapeHalfSize);",
905 fInnerEllipseName.vsOut());
906 if (fInnerEllipseCoords.vsOut()) {
907 v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;", fInnerEllipseCoords.vsOut());
908 }
909 if (fInnerRRect.vsOut()) {
910 v->codeAppendf("%s = vec4(0, 0, innerShapeHalfSize);", fInnerRRect.vsOut());
911 }
912}
913
csmartdalton0caee172016-07-13 08:48:53 -0700914void GLSLInstanceProcessor::BackendCoverage::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
csmartdaltona7f29642016-07-07 08:49:11 -0700915 // The distance to ellipse formula doesn't work well when the radii are less than half a pixel.
916 v->codeAppend ("innerRadii = max(innerRadii, bloat);");
917 v->codeAppendf("%s = 1.0 / (innerRadii * innerRadii * innerShapeHalfSize * "
918 "innerShapeHalfSize);",
919 fInnerEllipseName.vsOut());
920 v->codeAppendf("%s = vec4(1.0 - innerRadii, innerShapeHalfSize);", fInnerRRect.vsOut());
921}
922
923void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
924 GrGLSLPPFragmentBuilder* f,
925 const char* outCoverage,
926 const char* outColor) {
927 if (fColorTimesRectCoverage.vsOut()) {
928 SkASSERT(!fRectCoverage.vsOut());
929 v->codeAppendf("%s = %s * rectCoverage;",
930 fColorTimesRectCoverage.vsOut(), fInputs.attr(Attrib::kColor));
931 }
932 if (fRectCoverage.vsOut()) {
933 SkASSERT(!fColorTimesRectCoverage.vsOut());
934 v->codeAppendf("%s = rectCoverage;", fRectCoverage.vsOut());
935 }
936
Ethan Nicholas6762dd62016-11-22 15:40:27 -0500937 SkString coverage("lowp float coverage");
Brian Salomon99ad1642016-12-16 09:50:45 -0500938 if (fOpInfo.fInnerShapeTypes || (!fTweakAlphaForCoverage && fTriangleIsArc.fsIn())) {
csmartdaltona7f29642016-07-07 08:49:11 -0700939 f->codeAppendf("%s;", coverage.c_str());
940 coverage = "coverage";
941 }
942 if (fTriangleIsArc.fsIn()) {
943 f->codeAppendf("if (%s == 0) {", fTriangleIsArc.fsIn());
944 this->emitRect(f, coverage.c_str(), outColor);
945 f->codeAppend ("} else {");
946 if (fShapeIsCircle) {
947 this->emitCircle(f, coverage.c_str());
948 } else {
Brian Salomon99ad1642016-12-16 09:50:45 -0500949 bool ellipseCoordsMayBeNegative = SkToBool(fOpInfo.fShapeTypes & kOval_ShapeFlag);
csmartdaltona7f29642016-07-07 08:49:11 -0700950 this->emitArc(f, fEllipseCoords.fsIn(), fEllipseName.fsIn(),
951 true /*ellipseCoordsNeedClamp*/, ellipseCoordsMayBeNegative,
952 coverage.c_str());
953 }
954 if (fTweakAlphaForCoverage) {
955 f->codeAppendf("%s = %s * coverage;", outColor, fColor.fsIn());
956 }
957 f->codeAppend ("}");
958 } else {
959 this->emitRect(f, coverage.c_str(), outColor);
960 }
961
Brian Salomon99ad1642016-12-16 09:50:45 -0500962 if (fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700963 f->codeAppendf("// Inner shape.\n");
Ethan Nicholas6762dd62016-11-22 15:40:27 -0500964 SkString innerCoverageDecl("lowp float innerCoverage");
Brian Salomon99ad1642016-12-16 09:50:45 -0500965 if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700966 this->emitArc(f, fInnerEllipseCoords.fsIn(), fInnerEllipseName.fsIn(),
967 true /*ellipseCoordsNeedClamp*/, true /*ellipseCoordsMayBeNegative*/,
968 innerCoverageDecl.c_str());
969 } else {
970 v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;",
971 fDistanceToInnerEdge.vsOut());
972 v->codeAppendf("%s = innerShapeHalfSize + 0.5;", fInnerShapeBloatedHalfSize.vsOut());
973
Brian Salomon99ad1642016-12-16 09:50:45 -0500974 if (kRect_ShapeFlag == fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -0700975 this->emitInnerRect(f, innerCoverageDecl.c_str());
976 } else {
977 f->codeAppendf("%s = 0.0;", innerCoverageDecl.c_str());
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500978 f->codeAppendf("mediump vec2 distanceToArcEdge = abs(%s) - %s.xy;",
csmartdaltona7f29642016-07-07 08:49:11 -0700979 fInnerShapeCoords.fsIn(), fInnerRRect.fsIn());
980 f->codeAppend ("if (any(lessThan(distanceToArcEdge, vec2(1e-5)))) {");
981 this->emitInnerRect(f, "innerCoverage");
982 f->codeAppend ("} else {");
Ethan Nicholas1fc83b12016-11-22 09:31:35 -0500983 f->codeAppendf( "mediump vec2 ellipseCoords = distanceToArcEdge * %s.zw;",
csmartdaltona7f29642016-07-07 08:49:11 -0700984 fInnerRRect.fsIn());
985 this->emitArc(f, "ellipseCoords", fInnerEllipseName.fsIn(),
986 false /*ellipseCoordsNeedClamp*/,
987 false /*ellipseCoordsMayBeNegative*/, "innerCoverage");
988 f->codeAppend ("}");
989 }
990 }
991 f->codeAppendf("%s = vec4(max(coverage - innerCoverage, 0.0));", outCoverage);
992 } else if (!fTweakAlphaForCoverage) {
993 f->codeAppendf("%s = vec4(coverage);", outCoverage);
994 }
995}
996
997void GLSLInstanceProcessor::BackendCoverage::emitRect(GrGLSLPPFragmentBuilder* f,
998 const char* outCoverage,
999 const char* outColor) {
1000 if (fColorTimesRectCoverage.fsIn()) {
1001 f->codeAppendf("%s = %s;", outColor, fColorTimesRectCoverage.fsIn());
1002 } else if (fTweakAlphaForCoverage) {
1003 // We are drawing just ovals. The interior rect always has 100% coverage.
1004 f->codeAppendf("%s = %s;", outColor, fColor.fsIn());
1005 } else if (fRectCoverage.fsIn()) {
1006 f->codeAppendf("%s = %s;", outCoverage, fRectCoverage.fsIn());
1007 } else {
1008 f->codeAppendf("%s = 1.0;", outCoverage);
1009 }
1010}
1011
1012void GLSLInstanceProcessor::BackendCoverage::emitCircle(GrGLSLPPFragmentBuilder* f,
1013 const char* outCoverage) {
1014 // TODO: circleCoords = max(circleCoords, 0) if we decide to do this optimization on rrects.
Brian Salomon99ad1642016-12-16 09:50:45 -05001015 SkASSERT(!(kRRect_ShapesMask & fOpInfo.fShapeTypes));
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001016 f->codeAppendf("mediump float distanceToEdge = %s - length(%s);",
csmartdaltona7f29642016-07-07 08:49:11 -07001017 fBloatedRadius.fsIn(), fEllipseCoords.fsIn());
1018 f->codeAppendf("%s = clamp(distanceToEdge, 0.0, 1.0);", outCoverage);
1019}
1020
1021void GLSLInstanceProcessor::BackendCoverage::emitArc(GrGLSLPPFragmentBuilder* f,
1022 const char* ellipseCoords,
1023 const char* ellipseName,
1024 bool ellipseCoordsNeedClamp,
1025 bool ellipseCoordsMayBeNegative,
1026 const char* outCoverage) {
1027 SkASSERT(!ellipseCoordsMayBeNegative || ellipseCoordsNeedClamp);
1028 if (ellipseCoordsNeedClamp) {
1029 // This serves two purposes:
1030 // - To restrict the arcs of rounded rects to their positive quadrants.
1031 // - To avoid inversesqrt(0) in the ellipse formula.
1032 if (ellipseCoordsMayBeNegative) {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001033 f->codeAppendf("mediump vec2 ellipseClampedCoords = max(abs(%s), vec2(1e-4));",
1034 ellipseCoords);
csmartdaltona7f29642016-07-07 08:49:11 -07001035 } else {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001036 f->codeAppendf("mediump vec2 ellipseClampedCoords = max(%s, vec2(1e-4));",
1037 ellipseCoords);
csmartdaltona7f29642016-07-07 08:49:11 -07001038 }
1039 ellipseCoords = "ellipseClampedCoords";
1040 }
1041 // ellipseCoords are in pixel space and ellipseName is 1 / rx^2, 1 / ry^2.
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001042 f->codeAppendf("highp vec2 Z = %s * %s;", ellipseCoords, ellipseName);
csmartdaltona7f29642016-07-07 08:49:11 -07001043 // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001044 f->codeAppendf("highp float implicit = dot(Z, %s) - 1.0;", ellipseCoords);
csmartdaltona7f29642016-07-07 08:49:11 -07001045 // gradDot is the squared length of the gradient of the implicit.
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001046 f->codeAppendf("highp float gradDot = 4.0 * dot(Z, Z);");
1047 f->codeAppend ("mediump float approxDist = implicit * inversesqrt(gradDot);");
csmartdaltona7f29642016-07-07 08:49:11 -07001048 f->codeAppendf("%s = clamp(0.5 - approxDist, 0.0, 1.0);", outCoverage);
1049}
1050
1051void GLSLInstanceProcessor::BackendCoverage::emitInnerRect(GrGLSLPPFragmentBuilder* f,
1052 const char* outCoverage) {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001053 f->codeAppendf("lowp vec2 c = %s - abs(%s);",
csmartdaltona7f29642016-07-07 08:49:11 -07001054 fInnerShapeBloatedHalfSize.fsIn(), fDistanceToInnerEdge.fsIn());
1055 f->codeAppendf("%s = clamp(min(c.x, c.y), 0.0, 1.0);", outCoverage);
1056}
1057
1058////////////////////////////////////////////////////////////////////////////////////////////////////
1059
1060class GLSLInstanceProcessor::BackendMultisample : public Backend {
1061public:
Brian Salomon99ad1642016-12-16 09:50:45 -05001062 BackendMultisample(OpInfo opInfo, const VertexInputs& inputs, int effectiveSampleCnt)
1063 : INHERITED(opInfo, inputs)
1064 , fEffectiveSampleCnt(effectiveSampleCnt)
1065 , fShapeCoords(kVec2f_GrSLType)
1066 , fShapeInverseMatrix(kMat22f_GrSLType)
1067 , fFragShapeHalfSpan(kVec2f_GrSLType)
1068 , fArcTest(kVec2f_GrSLType)
1069 , fArcInverseMatrix(kMat22f_GrSLType)
1070 , fFragArcHalfSpan(kVec2f_GrSLType)
1071 , fEarlyAccept(kInt_GrSLType)
1072 , fInnerShapeInverseMatrix(kMat22f_GrSLType)
1073 , fFragInnerShapeHalfSpan(kVec2f_GrSLType) {
1074 fRectTrianglesMaySplit = fOpInfo.fHasPerspective;
1075 fNeedsNeighborRadii = this->isMixedSampled() && !fOpInfo.fHasPerspective;
csmartdaltona7f29642016-07-07 08:49:11 -07001076 }
1077
1078private:
Brian Salomon99ad1642016-12-16 09:50:45 -05001079 bool isMixedSampled() const { return AntialiasMode::kMixedSamples == fOpInfo.fAntialiasMode; }
csmartdaltona7f29642016-07-07 08:49:11 -07001080
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;
csmartdalton0caee172016-07-13 08:48:53 -07001090 void onSetupInnerSimpleRRect(GrGLSLVertexBuilder*) override;
csmartdaltona7f29642016-07-07 08:49:11 -07001091
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
1134void GLSLInstanceProcessor::BackendMultisample::onInit(GrGLSLVaryingHandler* varyingHandler,
1135 GrGLSLVertexBuilder* v) {
1136 if (!this->isMixedSampled()) {
Brian Salomon99ad1642016-12-16 09:50:45 -05001137 if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
csmartdaltondd57dd72016-07-13 08:59:52 -07001138 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kLow_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -07001139 varyingHandler->addVarying("arcCoords", &fArcCoords, kHigh_GrSLPrecision);
Brian Salomon99ad1642016-12-16 09:50:45 -05001140 if (!fOpInfo.fHasPerspective) {
csmartdaltona7f29642016-07-07 08:49:11 -07001141 varyingHandler->addFlatVarying("arcInverseMatrix", &fArcInverseMatrix,
1142 kHigh_GrSLPrecision);
1143 varyingHandler->addFlatVarying("fragArcHalfSpan", &fFragArcHalfSpan,
1144 kHigh_GrSLPrecision);
1145 }
Brian Salomon99ad1642016-12-16 09:50:45 -05001146 } else if (!fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -07001147 return;
1148 }
1149 } else {
1150 varyingHandler->addVarying("shapeCoords", &fShapeCoords, kHigh_GrSLPrecision);
Brian Salomon99ad1642016-12-16 09:50:45 -05001151 if (!fOpInfo.fHasPerspective) {
csmartdaltona7f29642016-07-07 08:49:11 -07001152 varyingHandler->addFlatVarying("shapeInverseMatrix", &fShapeInverseMatrix,
1153 kHigh_GrSLPrecision);
1154 varyingHandler->addFlatVarying("fragShapeHalfSpan", &fFragShapeHalfSpan,
1155 kHigh_GrSLPrecision);
1156 }
Brian Salomon99ad1642016-12-16 09:50:45 -05001157 if (fOpInfo.fShapeTypes & kRRect_ShapesMask) {
csmartdaltona7f29642016-07-07 08:49:11 -07001158 varyingHandler->addVarying("arcCoords", &fArcCoords, kHigh_GrSLPrecision);
1159 varyingHandler->addVarying("arcTest", &fArcTest, kHigh_GrSLPrecision);
Brian Salomon99ad1642016-12-16 09:50:45 -05001160 if (!fOpInfo.fHasPerspective) {
csmartdaltona7f29642016-07-07 08:49:11 -07001161 varyingHandler->addFlatVarying("arcInverseMatrix", &fArcInverseMatrix,
1162 kHigh_GrSLPrecision);
1163 varyingHandler->addFlatVarying("fragArcHalfSpan", &fFragArcHalfSpan,
1164 kHigh_GrSLPrecision);
1165 }
Brian Salomon99ad1642016-12-16 09:50:45 -05001166 } else if (fOpInfo.fShapeTypes & kOval_ShapeFlag) {
csmartdaltona7f29642016-07-07 08:49:11 -07001167 fArcCoords = fShapeCoords;
1168 fArcInverseMatrix = fShapeInverseMatrix;
1169 fFragArcHalfSpan = fFragShapeHalfSpan;
Brian Salomon99ad1642016-12-16 09:50:45 -05001170 if (fOpInfo.fShapeTypes & kRect_ShapeFlag) {
csmartdaltona7f29642016-07-07 08:49:11 -07001171 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc,
csmartdaltondd57dd72016-07-13 08:59:52 -07001172 kLow_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -07001173 }
1174 }
Brian Salomon99ad1642016-12-16 09:50:45 -05001175 if (kRect_ShapeFlag != fOpInfo.fShapeTypes) {
1176 v->defineConstantf("int", "SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1);
1177 varyingHandler->addFlatVarying("earlyAccept", &fEarlyAccept, kHigh_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -07001178 }
1179 }
Brian Salomon99ad1642016-12-16 09:50:45 -05001180 if (!fOpInfo.fHasPerspective) {
csmartdaltona7f29642016-07-07 08:49:11 -07001181 v->codeAppend("mat2 shapeInverseMatrix = inverse(mat2(shapeMatrix));");
1182 v->codeAppend("vec2 fragShapeSpan = abs(vec4(shapeInverseMatrix).xz) + "
1183 "abs(vec4(shapeInverseMatrix).yw);");
1184 }
1185}
1186
1187void GLSLInstanceProcessor::BackendMultisample::setupRect(GrGLSLVertexBuilder* v) {
1188 if (fShapeCoords.vsOut()) {
1189 v->codeAppendf("%s = %s;", fShapeCoords.vsOut(), this->outShapeCoords());
1190 }
1191 if (fShapeInverseMatrix.vsOut()) {
1192 v->codeAppendf("%s = shapeInverseMatrix;", fShapeInverseMatrix.vsOut());
1193 }
1194 if (fFragShapeHalfSpan.vsOut()) {
1195 v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut());
1196 }
1197 if (fArcTest.vsOut()) {
1198 // Pick a value that is not > 0.
1199 v->codeAppendf("%s = vec2(0);", fArcTest.vsOut());
1200 }
1201 if (fTriangleIsArc.vsOut()) {
1202 v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
1203 }
1204 if (fEarlyAccept.vsOut()) {
1205 v->codeAppendf("%s = SAMPLE_MASK_ALL;", fEarlyAccept.vsOut());
1206 }
1207}
1208
1209void GLSLInstanceProcessor::BackendMultisample::setupOval(GrGLSLVertexBuilder* v) {
1210 v->codeAppendf("%s = abs(%s);", fArcCoords.vsOut(), this->outShapeCoords());
1211 if (fArcInverseMatrix.vsOut()) {
1212 v->codeAppendf("vec2 s = sign(%s);", this->outShapeCoords());
1213 v->codeAppendf("%s = shapeInverseMatrix * mat2(s.x, 0, 0 , s.y);",
1214 fArcInverseMatrix.vsOut());
1215 }
1216 if (fFragArcHalfSpan.vsOut()) {
1217 v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragArcHalfSpan.vsOut());
1218 }
1219 if (fArcTest.vsOut()) {
1220 // Pick a value that is > 0.
1221 v->codeAppendf("%s = vec2(1);", fArcTest.vsOut());
1222 }
1223 if (fTriangleIsArc.vsOut()) {
1224 if (!this->isMixedSampled()) {
1225 v->codeAppendf("%s = %s & 1;",
1226 fTriangleIsArc.vsOut(), fInputs.attr(Attrib::kVertexAttrs));
1227 } else {
1228 v->codeAppendf("%s = 1;", fTriangleIsArc.vsOut());
1229 }
1230 }
1231 if (fEarlyAccept.vsOut()) {
1232 v->codeAppendf("%s = ~%s & SAMPLE_MASK_ALL;",
1233 fEarlyAccept.vsOut(), fInputs.attr(Attrib::kVertexAttrs));
1234 }
1235}
1236
1237void GLSLInstanceProcessor::BackendMultisample::adjustRRectVertices(GrGLSLVertexBuilder* v) {
1238 if (!this->isMixedSampled()) {
1239 INHERITED::adjustRRectVertices(v);
1240 return;
1241 }
1242
Brian Salomon99ad1642016-12-16 09:50:45 -05001243 if (!fOpInfo.fHasPerspective) {
csmartdaltona7f29642016-07-07 08:49:11 -07001244 // For the mixed samples algorithm it's best to bloat the corner triangles a bit so that
1245 // more of the pixels that cross into the arc region are completely inside the shared edges.
1246 // We also snap to a regular rect if the radii shrink smaller than a pixel.
1247 v->codeAppend ("vec2 midpt = 0.5 * (neighborRadii - radii);");
1248 v->codeAppend ("vec2 cornerSize = any(lessThan(radii, fragShapeSpan)) ? "
1249 "vec2(0) : min(radii + 0.5 * fragShapeSpan, 1.0 - midpt);");
1250 } else {
1251 // TODO: We could still bloat the corner triangle in the perspective case; we would just
1252 // need to find the screen-space derivative of shape coords at this particular point.
1253 v->codeAppend ("vec2 cornerSize = any(lessThan(radii, vec2(1e-3))) ? vec2(0) : radii;");
1254 }
1255
1256 v->codeAppendf("if (abs(%s.x) == 0.5)"
1257 "%s.x = cornerSign.x * (1.0 - cornerSize.x);",
1258 fInputs.attr(Attrib::kShapeCoords), fModifiedShapeCoords);
1259 v->codeAppendf("if (abs(%s.y) == 0.5)"
1260 "%s.y = cornerSign.y * (1.0 - cornerSize.y);",
1261 fInputs.attr(Attrib::kShapeCoords), fModifiedShapeCoords);
1262}
1263
1264void GLSLInstanceProcessor::BackendMultisample::onSetupRRect(GrGLSLVertexBuilder* v) {
1265 if (fShapeCoords.vsOut()) {
1266 v->codeAppendf("%s = %s;", fShapeCoords.vsOut(), this->outShapeCoords());
1267 }
1268 if (fShapeInverseMatrix.vsOut()) {
1269 v->codeAppendf("%s = shapeInverseMatrix;", fShapeInverseMatrix.vsOut());
1270 }
1271 if (fFragShapeHalfSpan.vsOut()) {
1272 v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut());
1273 }
1274 if (fArcInverseMatrix.vsOut()) {
1275 v->codeAppend ("vec2 s = cornerSign / radii;");
1276 v->codeAppendf("%s = shapeInverseMatrix * mat2(s.x, 0, 0, s.y);",
1277 fArcInverseMatrix.vsOut());
1278 }
1279 if (fFragArcHalfSpan.vsOut()) {
1280 v->codeAppendf("%s = 0.5 * (abs(vec4(%s).xz) + abs(vec4(%s).yw));",
1281 fFragArcHalfSpan.vsOut(), fArcInverseMatrix.vsOut(),
1282 fArcInverseMatrix.vsOut());
1283 }
1284 if (fArcTest.vsOut()) {
1285 // The interior triangles are laid out as a fan. fArcTest is both distances from shared
1286 // edges of a fan triangle to a point within that triangle. fArcTest is used to check if a
1287 // fragment is too close to either shared edge, in which case we point sample the shape as a
1288 // rect at that point in order to guarantee the mixed samples discard logic works correctly.
1289 v->codeAppendf("%s = (cornerSize == vec2(0)) ? vec2(0) : "
1290 "cornerSign * %s * mat2(1, cornerSize.x - 1.0, cornerSize.y - 1.0, 1);",
1291 fArcTest.vsOut(), fModifiedShapeCoords);
Brian Salomon99ad1642016-12-16 09:50:45 -05001292 if (!fOpInfo.fHasPerspective) {
csmartdaltona7f29642016-07-07 08:49:11 -07001293 // Shift the point at which distances to edges are measured from the center of the pixel
1294 // to the corner. This way the sign of fArcTest will quickly tell us whether a pixel
1295 // is completely inside the shared edge. Perspective mode will accomplish this same task
1296 // by finding the derivatives in the fragment shader.
1297 v->codeAppendf("%s -= 0.5 * (fragShapeSpan.yx * abs(radii - 1.0) + fragShapeSpan);",
1298 fArcTest.vsOut());
1299 }
1300 }
1301 if (fEarlyAccept.vsOut()) {
1302 SkASSERT(this->isMixedSampled());
1303 v->codeAppendf("%s = all(equal(vec2(1), abs(%s))) ? 0 : SAMPLE_MASK_ALL;",
1304 fEarlyAccept.vsOut(), fInputs.attr(Attrib::kShapeCoords));
1305 }
1306}
1307
1308void
1309GLSLInstanceProcessor::BackendMultisample::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
1310 GrGLSLVertexBuilder* v) {
1311 varyingHandler->addVarying("innerShapeCoords", &fInnerShapeCoords, kHigh_GrSLPrecision);
Brian Salomon99ad1642016-12-16 09:50:45 -05001312 if (kOval_ShapeFlag != fOpInfo.fInnerShapeTypes &&
1313 kRect_ShapeFlag != fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -07001314 varyingHandler->addFlatVarying("innerRRect", &fInnerRRect, kHigh_GrSLPrecision);
1315 }
Brian Salomon99ad1642016-12-16 09:50:45 -05001316 if (!fOpInfo.fHasPerspective) {
csmartdaltona7f29642016-07-07 08:49:11 -07001317 varyingHandler->addFlatVarying("innerShapeInverseMatrix", &fInnerShapeInverseMatrix,
1318 kHigh_GrSLPrecision);
1319 v->codeAppendf("%s = shapeInverseMatrix * mat2(outer2Inner.x, 0, 0, outer2Inner.y);",
1320 fInnerShapeInverseMatrix.vsOut());
1321 varyingHandler->addFlatVarying("fragInnerShapeHalfSpan", &fFragInnerShapeHalfSpan,
1322 kHigh_GrSLPrecision);
1323 v->codeAppendf("%s = 0.5 * fragShapeSpan * outer2Inner.xy;",
1324 fFragInnerShapeHalfSpan.vsOut());
1325 }
1326}
1327
1328void GLSLInstanceProcessor::BackendMultisample::setupInnerRect(GrGLSLVertexBuilder* v) {
1329 if (fInnerRRect.vsOut()) {
1330 // The fragment shader will generalize every inner shape as a round rect. Since this one
1331 // is a rect, we simply emit bogus parameters for the round rect (negative radii) that
1332 // ensure the fragment shader always takes the "sample as rect" codepath.
1333 v->codeAppendf("%s = vec4(2.0 * (inner.zw - inner.xy) / (outer.zw - outer.xy), vec2(0));",
1334 fInnerRRect.vsOut());
1335 }
1336}
1337
1338void GLSLInstanceProcessor::BackendMultisample::setupInnerOval(GrGLSLVertexBuilder* v) {
1339 if (fInnerRRect.vsOut()) {
1340 v->codeAppendf("%s = vec4(0, 0, 1, 1);", fInnerRRect.vsOut());
1341 }
1342}
1343
csmartdalton0caee172016-07-13 08:48:53 -07001344void GLSLInstanceProcessor::BackendMultisample::onSetupInnerSimpleRRect(GrGLSLVertexBuilder* v) {
csmartdaltona7f29642016-07-07 08:49:11 -07001345 // Avoid numeric instability by not allowing the inner radii to get smaller than 1/10th pixel.
1346 if (fFragInnerShapeHalfSpan.vsOut()) {
1347 v->codeAppendf("innerRadii = max(innerRadii, 2e-1 * %s);", fFragInnerShapeHalfSpan.vsOut());
1348 } else {
1349 v->codeAppend ("innerRadii = max(innerRadii, vec2(1e-4));");
1350 }
1351 v->codeAppendf("%s = vec4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect.vsOut());
1352}
1353
1354void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
1355 GrGLSLPPFragmentBuilder* f,
1356 const char*, const char*) {
ethannicholas5961bc92016-10-12 06:39:56 -07001357 f->defineConstant("SAMPLE_COUNT", fEffectiveSampleCnt);
csmartdaltona7f29642016-07-07 08:49:11 -07001358 if (this->isMixedSampled()) {
ethannicholas5961bc92016-10-12 06:39:56 -07001359 f->defineConstantf("int", "SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1);
1360 f->defineConstantf("int", "SAMPLE_MASK_MSB", "0x%x", 1 << (fEffectiveSampleCnt - 1));
csmartdaltona7f29642016-07-07 08:49:11 -07001361 }
1362
Brian Salomon99ad1642016-12-16 09:50:45 -05001363 if (kRect_ShapeFlag != (fOpInfo.fShapeTypes | fOpInfo.fInnerShapeTypes)) {
Brian Salomon99938a82016-11-21 13:41:08 -05001364 GrShaderVar x("x", kVec2f_GrSLType, GrShaderVar::kNonArray, kHigh_GrSLPrecision);
csmartdaltona7f29642016-07-07 08:49:11 -07001365 f->emitFunction(kFloat_GrSLType, "square", 1, &x, "return dot(x, x);", &fSquareFun);
1366 }
1367
1368 EmitShapeCoords shapeCoords;
1369 shapeCoords.fVarying = &fShapeCoords;
1370 shapeCoords.fInverseMatrix = fShapeInverseMatrix.fsIn();
1371 shapeCoords.fFragHalfSpan = fFragShapeHalfSpan.fsIn();
1372
1373 EmitShapeCoords arcCoords;
1374 arcCoords.fVarying = &fArcCoords;
1375 arcCoords.fInverseMatrix = fArcInverseMatrix.fsIn();
1376 arcCoords.fFragHalfSpan = fFragArcHalfSpan.fsIn();
Brian Salomon99ad1642016-12-16 09:50:45 -05001377 bool clampArcCoords = this->isMixedSampled() && (fOpInfo.fShapeTypes & kRRect_ShapesMask);
csmartdaltona7f29642016-07-07 08:49:11 -07001378
1379 EmitShapeOpts opts;
1380 opts.fIsTightGeometry = true;
1381 opts.fResolveMixedSamples = this->isMixedSampled();
1382 opts.fInvertCoverage = false;
1383
Brian Salomon99ad1642016-12-16 09:50:45 -05001384 if (fOpInfo.fHasPerspective && fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -07001385 // 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.
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001387 f->codeAppendf("highp vec2 fragInnerShapeApproxHalfSpan = 0.5 * fwidth(%s);",
csmartdaltona7f29642016-07-07 08:49:11 -07001388 fInnerShapeCoords.fsIn());
1389 }
1390
1391 if (!this->isMixedSampled()) {
1392 SkASSERT(!fArcTest.fsIn());
1393 if (fTriangleIsArc.fsIn()) {
1394 f->codeAppendf("if (%s != 0) {", fTriangleIsArc.fsIn());
1395 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1396
1397 f->codeAppend ("}");
1398 }
1399 } else {
1400 const char* arcTest = fArcTest.fsIn();
Brian Salomon99ad1642016-12-16 09:50:45 -05001401 if (arcTest && fOpInfo.fHasPerspective) {
csmartdaltone0d36292016-07-29 08:14:20 -07001402 // The non-perspective version accounts for fwidth() in the vertex shader.
csmartdaltona7f29642016-07-07 08:49:11 -07001403 // We make sure to take the derivative here, before a neighbor pixel may early accept.
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001404 f->codeAppendf("highp vec2 arcTest = %s - 0.5 * fwidth(%s);",
csmartdaltona7f29642016-07-07 08:49:11 -07001405 fArcTest.fsIn(), fArcTest.fsIn());
1406 arcTest = "arcTest";
1407 }
1408 const char* earlyAccept = fEarlyAccept.fsIn() ? fEarlyAccept.fsIn() : "SAMPLE_MASK_ALL";
1409 f->codeAppendf("if (gl_SampleMaskIn[0] == %s) {", earlyAccept);
1410 f->overrideSampleCoverage(earlyAccept);
1411 f->codeAppend ("} else {");
1412 if (arcTest) {
1413 // At this point, if the sample mask is all set it means we are inside an arc triangle.
1414 f->codeAppendf("if (gl_SampleMaskIn[0] == SAMPLE_MASK_ALL || "
1415 "all(greaterThan(%s, vec2(0)))) {", arcTest);
1416 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1417 f->codeAppend ("} else {");
1418 this->emitRect(f, shapeCoords, opts);
1419 f->codeAppend ("}");
1420 } else if (fTriangleIsArc.fsIn()) {
1421 f->codeAppendf("if (%s == 0) {", fTriangleIsArc.fsIn());
1422 this->emitRect(f, shapeCoords, opts);
1423 f->codeAppend ("} else {");
1424 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1425 f->codeAppend ("}");
Brian Salomon99ad1642016-12-16 09:50:45 -05001426 } else if (fOpInfo.fShapeTypes == kOval_ShapeFlag) {
csmartdaltona7f29642016-07-07 08:49:11 -07001427 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1428 } else {
Brian Salomon99ad1642016-12-16 09:50:45 -05001429 SkASSERT(fOpInfo.fShapeTypes == kRect_ShapeFlag);
csmartdaltona7f29642016-07-07 08:49:11 -07001430 this->emitRect(f, shapeCoords, opts);
1431 }
1432 f->codeAppend ("}");
1433 }
1434
Brian Salomon99ad1642016-12-16 09:50:45 -05001435 if (fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -07001436 f->codeAppendf("// Inner shape.\n");
1437
1438 EmitShapeCoords innerShapeCoords;
1439 innerShapeCoords.fVarying = &fInnerShapeCoords;
Brian Salomon99ad1642016-12-16 09:50:45 -05001440 if (!fOpInfo.fHasPerspective) {
csmartdaltona7f29642016-07-07 08:49:11 -07001441 innerShapeCoords.fInverseMatrix = fInnerShapeInverseMatrix.fsIn();
1442 innerShapeCoords.fFragHalfSpan = fFragInnerShapeHalfSpan.fsIn();
1443 }
1444
1445 EmitShapeOpts innerOpts;
1446 innerOpts.fIsTightGeometry = false;
1447 innerOpts.fResolveMixedSamples = false; // Mixed samples are resolved in the outer shape.
1448 innerOpts.fInvertCoverage = true;
1449
Brian Salomon99ad1642016-12-16 09:50:45 -05001450 if (kOval_ShapeFlag == fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -07001451 this->emitArc(f, innerShapeCoords, true, false, innerOpts);
1452 } else {
1453 f->codeAppendf("if (all(lessThan(abs(%s), 1.0 + %s))) {", fInnerShapeCoords.fsIn(),
Brian Salomon99ad1642016-12-16 09:50:45 -05001454 !fOpInfo.fHasPerspective ? innerShapeCoords.fFragHalfSpan
1455 : "fragInnerShapeApproxHalfSpan"); // Above.
1456 if (kRect_ShapeFlag == fOpInfo.fInnerShapeTypes) {
csmartdaltona7f29642016-07-07 08:49:11 -07001457 this->emitRect(f, innerShapeCoords, innerOpts);
1458 } else {
1459 this->emitSimpleRRect(f, innerShapeCoords, fInnerRRect.fsIn(), innerOpts);
1460 }
1461 f->codeAppend ("}");
1462 }
1463 }
1464}
1465
1466void GLSLInstanceProcessor::BackendMultisample::emitRect(GrGLSLPPFragmentBuilder* f,
1467 const EmitShapeCoords& coords,
1468 const EmitShapeOpts& opts) {
1469 // Full MSAA doesn't need to do anything to draw a rect.
1470 SkASSERT(!opts.fIsTightGeometry || opts.fResolveMixedSamples);
1471 if (coords.fFragHalfSpan) {
1472 f->codeAppendf("if (all(lessThanEqual(abs(%s), 1.0 - %s))) {",
1473 coords.fVarying->fsIn(), coords.fFragHalfSpan);
1474 // The entire pixel is inside the rect.
1475 this->acceptOrRejectWholeFragment(f, true, opts);
1476 f->codeAppend ("} else ");
1477 if (opts.fIsTightGeometry && !fRectTrianglesMaySplit) {
1478 f->codeAppendf("if (any(lessThan(abs(%s), 1.0 - %s))) {",
1479 coords.fVarying->fsIn(), coords.fFragHalfSpan);
1480 // The pixel falls on an edge of the rectangle and is known to not be on a shared edge.
1481 this->acceptCoverageMask(f, "gl_SampleMaskIn[0]", opts, false);
1482 f->codeAppend ("} else");
1483 }
1484 f->codeAppend ("{");
1485 }
1486 f->codeAppend ("int rectMask = 0;");
1487 f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001488 f->codeAppend ( "highp vec2 pt = ");
csmartdaltona7f29642016-07-07 08:49:11 -07001489 this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
1490 f->codeAppend ( ";");
1491 f->codeAppend ( "if (all(lessThan(abs(pt), vec2(1)))) rectMask |= (1 << i);");
1492 f->codeAppend ("}");
1493 this->acceptCoverageMask(f, "rectMask", opts);
1494 if (coords.fFragHalfSpan) {
1495 f->codeAppend ("}");
1496 }
1497}
1498
1499void GLSLInstanceProcessor::BackendMultisample::emitArc(GrGLSLPPFragmentBuilder* f,
1500 const EmitShapeCoords& coords,
1501 bool coordsMayBeNegative, bool clampCoords,
1502 const EmitShapeOpts& opts) {
1503 if (coords.fFragHalfSpan) {
1504 SkString absArcCoords;
1505 absArcCoords.printf(coordsMayBeNegative ? "abs(%s)" : "%s", coords.fVarying->fsIn());
1506 if (clampCoords) {
1507 f->codeAppendf("if (%s(max(%s + %s, vec2(0))) < 1.0) {",
1508 fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
1509 } else {
1510 f->codeAppendf("if (%s(%s + %s) < 1.0) {",
1511 fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
1512 }
1513 // The entire pixel is inside the arc.
1514 this->acceptOrRejectWholeFragment(f, true, opts);
1515 f->codeAppendf("} else if (%s(max(%s - %s, vec2(0))) >= 1.0) {",
1516 fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHalfSpan);
1517 // The entire pixel is outside the arc.
1518 this->acceptOrRejectWholeFragment(f, false, opts);
1519 f->codeAppend ("} else {");
1520 }
1521 f->codeAppend ( "int arcMask = 0;");
1522 f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {");
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001523 f->codeAppend ( "highp vec2 pt = ");
csmartdaltona7f29642016-07-07 08:49:11 -07001524 this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
1525 f->codeAppend ( ";");
1526 if (clampCoords) {
1527 SkASSERT(!coordsMayBeNegative);
1528 f->codeAppend ( "pt = max(pt, vec2(0));");
1529 }
1530 f->codeAppendf( "if (%s(pt) < 1.0) arcMask |= (1 << i);", fSquareFun.c_str());
1531 f->codeAppend ( "}");
1532 this->acceptCoverageMask(f, "arcMask", opts);
1533 if (coords.fFragHalfSpan) {
1534 f->codeAppend ("}");
1535 }
1536}
1537
1538void GLSLInstanceProcessor::BackendMultisample::emitSimpleRRect(GrGLSLPPFragmentBuilder* f,
1539 const EmitShapeCoords& coords,
1540 const char* rrect,
1541 const EmitShapeOpts& opts) {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001542 f->codeAppendf("highp vec2 distanceToArcEdge = abs(%s) - %s.xy;", coords.fVarying->fsIn(),
1543 rrect);
csmartdaltona7f29642016-07-07 08:49:11 -07001544 f->codeAppend ("if (any(lessThan(distanceToArcEdge, vec2(0)))) {");
1545 this->emitRect(f, coords, opts);
1546 f->codeAppend ("} else {");
1547 if (coords.fInverseMatrix && coords.fFragHalfSpan) {
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001548 f->codeAppendf("highp vec2 rrectCoords = distanceToArcEdge * %s.zw;", rrect);
1549 f->codeAppendf("highp vec2 fragRRectHalfSpan = %s * %s.zw;", coords.fFragHalfSpan, rrect);
csmartdaltona7f29642016-07-07 08:49:11 -07001550 f->codeAppendf("if (%s(rrectCoords + fragRRectHalfSpan) <= 1.0) {", fSquareFun.c_str());
1551 // The entire pixel is inside the round rect.
1552 this->acceptOrRejectWholeFragment(f, true, opts);
1553 f->codeAppendf("} else if (%s(max(rrectCoords - fragRRectHalfSpan, vec2(0))) >= 1.0) {",
1554 fSquareFun.c_str());
1555 // The entire pixel is outside the round rect.
1556 this->acceptOrRejectWholeFragment(f, false, opts);
1557 f->codeAppend ("} else {");
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001558 f->codeAppendf( "highp vec2 s = %s.zw * sign(%s);", rrect, coords.fVarying->fsIn());
1559 f->codeAppendf( "highp mat2 innerRRectInverseMatrix = %s * mat2(s.x, 0, 0, s.y);",
csmartdaltona7f29642016-07-07 08:49:11 -07001560 coords.fInverseMatrix);
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001561 f->codeAppend ( "highp int rrectMask = 0;");
csmartdaltona7f29642016-07-07 08:49:11 -07001562 f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {");
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001563 f->codeAppend ( "highp vec2 pt = rrectCoords + ");
csmartdaltona7f29642016-07-07 08:49:11 -07001564 f->appendOffsetToSample("i", GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
1565 f->codeAppend ( "* innerRRectInverseMatrix;");
1566 f->codeAppendf( "if (%s(max(pt, vec2(0))) < 1.0) rrectMask |= (1 << i);",
1567 fSquareFun.c_str());
1568 f->codeAppend ( "}");
1569 this->acceptCoverageMask(f, "rrectMask", opts);
1570 f->codeAppend ("}");
1571 } else {
1572 f->codeAppend ("int rrectMask = 0;");
1573 f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001574 f->codeAppend ( "highp vec2 shapePt = ");
csmartdaltona7f29642016-07-07 08:49:11 -07001575 this->interpolateAtSample(f, *coords.fVarying, "i", nullptr);
1576 f->codeAppend ( ";");
Ethan Nicholas1fc83b12016-11-22 09:31:35 -05001577 f->codeAppendf( "highp vec2 rrectPt = max(abs(shapePt) - %s.xy, vec2(0)) * %s.zw;",
csmartdaltona7f29642016-07-07 08:49:11 -07001578 rrect, rrect);
1579 f->codeAppendf( "if (%s(rrectPt) < 1.0) rrectMask |= (1 << i);", fSquareFun.c_str());
1580 f->codeAppend ("}");
1581 this->acceptCoverageMask(f, "rrectMask", opts);
1582 }
1583 f->codeAppend ("}");
1584}
1585
1586void GLSLInstanceProcessor::BackendMultisample::interpolateAtSample(GrGLSLPPFragmentBuilder* f,
1587 const GrGLSLVarying& varying,
1588 const char* sampleIdx,
1589 const char* interpolationMatrix) {
1590 if (interpolationMatrix) {
1591 f->codeAppendf("(%s + ", varying.fsIn());
1592 f->appendOffsetToSample(sampleIdx, GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
1593 f->codeAppendf(" * %s)", interpolationMatrix);
1594 } else {
1595 SkAssertResult(
1596 f->enableFeature(GrGLSLFragmentBuilder::kMultisampleInterpolation_GLSLFeature));
1597 f->codeAppendf("interpolateAtOffset(%s, ", varying.fsIn());
1598 f->appendOffsetToSample(sampleIdx, GrGLSLFPFragmentBuilder::kGLSLWindow_Coordinates);
1599 f->codeAppend(")");
1600 }
1601}
1602
1603void
1604GLSLInstanceProcessor::BackendMultisample::acceptOrRejectWholeFragment(GrGLSLPPFragmentBuilder* f,
1605 bool inside,
1606 const EmitShapeOpts& opts) {
1607 if (inside != opts.fInvertCoverage) { // Accept the entire fragment.
1608 if (opts.fResolveMixedSamples) {
1609 // This is a mixed sampled fragment in the interior of the shape. Reassign 100% coverage
1610 // to one fragment, and drop all other fragments that may fall on this same pixel. Since
1611 // our geometry is water tight and non-overlapping, we can take advantage of the
1612 // properties that (1) the incoming sample masks will be disjoint across fragments that
1613 // fall on a common pixel, and (2) since the entire fragment is inside the shape, each
1614 // sample's corresponding bit will be set in the incoming sample mask of exactly one
1615 // fragment.
1616 f->codeAppend("if ((gl_SampleMaskIn[0] & SAMPLE_MASK_MSB) == 0) {");
1617 // Drop this fragment.
Brian Salomon99ad1642016-12-16 09:50:45 -05001618 if (!fOpInfo.fCannotDiscard) {
csmartdaltona7f29642016-07-07 08:49:11 -07001619 f->codeAppend("discard;");
1620 } else {
1621 f->overrideSampleCoverage("0");
1622 }
1623 f->codeAppend("} else {");
1624 // Override the lone surviving fragment to full coverage.
1625 f->overrideSampleCoverage("-1");
1626 f->codeAppend("}");
1627 }
1628 } else { // Reject the entire fragment.
Brian Salomon99ad1642016-12-16 09:50:45 -05001629 if (!fOpInfo.fCannotDiscard) {
csmartdaltona7f29642016-07-07 08:49:11 -07001630 f->codeAppend("discard;");
1631 } else if (opts.fResolveMixedSamples) {
1632 f->overrideSampleCoverage("0");
1633 } else {
1634 f->maskSampleCoverage("0");
1635 }
1636 }
1637}
1638
1639void GLSLInstanceProcessor::BackendMultisample::acceptCoverageMask(GrGLSLPPFragmentBuilder* f,
1640 const char* shapeMask,
1641 const EmitShapeOpts& opts,
1642 bool maybeSharedEdge) {
1643 if (opts.fResolveMixedSamples) {
1644 if (maybeSharedEdge) {
1645 // This is a mixed sampled fragment, potentially on the outer edge of the shape, with
1646 // only partial shape coverage. Override the coverage of one fragment to "shapeMask",
1647 // and drop all other fragments that may fall on this same pixel. Since our geometry is
1648 // water tight, non-overlapping, and completely contains the shape, this means that each
1649 // "on" bit from shapeMask is guaranteed to be set in the incoming sample mask of one,
1650 // and only one, fragment that falls on this same pixel.
1651 SkASSERT(!opts.fInvertCoverage);
1652 f->codeAppendf("if ((gl_SampleMaskIn[0] & (1 << findMSB(%s))) == 0) {", shapeMask);
1653 // Drop this fragment.
Brian Salomon99ad1642016-12-16 09:50:45 -05001654 if (!fOpInfo.fCannotDiscard) {
csmartdaltona7f29642016-07-07 08:49:11 -07001655 f->codeAppend ("discard;");
1656 } else {
1657 f->overrideSampleCoverage("0");
1658 }
1659 f->codeAppend ("} else {");
1660 // Override the coverage of the lone surviving fragment to "shapeMask".
1661 f->overrideSampleCoverage(shapeMask);
1662 f->codeAppend ("}");
1663 } else {
1664 f->overrideSampleCoverage(shapeMask);
1665 }
1666 } else {
1667 f->maskSampleCoverage(shapeMask, opts.fInvertCoverage);
1668 }
1669}
1670
1671////////////////////////////////////////////////////////////////////////////////////////////////////
1672
Brian Salomon99ad1642016-12-16 09:50:45 -05001673GLSLInstanceProcessor::Backend* GLSLInstanceProcessor::Backend::Create(const GrPipeline& pipeline,
1674 OpInfo opInfo,
1675 const VertexInputs& inputs) {
1676 switch (opInfo.fAntialiasMode) {
csmartdaltona7f29642016-07-07 08:49:11 -07001677 default:
1678 SkFAIL("Unexpected antialias mode.");
1679 case AntialiasMode::kNone:
Brian Salomon99ad1642016-12-16 09:50:45 -05001680 return new BackendNonAA(opInfo, inputs);
csmartdaltona7f29642016-07-07 08:49:11 -07001681 case AntialiasMode::kCoverage:
Brian Salomon99ad1642016-12-16 09:50:45 -05001682 return new BackendCoverage(opInfo, inputs);
csmartdaltona7f29642016-07-07 08:49:11 -07001683 case AntialiasMode::kMSAA:
1684 case AntialiasMode::kMixedSamples: {
1685 const GrRenderTargetPriv& rtp = pipeline.getRenderTarget()->renderTargetPriv();
csmartdaltonc633abb2016-11-01 08:55:55 -07001686 const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline);
Brian Salomon99ad1642016-12-16 09:50:45 -05001687 return new BackendMultisample(opInfo, inputs, specs.fEffectiveSampleCnt);
csmartdaltona7f29642016-07-07 08:49:11 -07001688 }
1689 }
1690}
1691
1692////////////////////////////////////////////////////////////////////////////////////////////////////
1693
1694const 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
1789const 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
1969enum {
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
1998GR_DECLARE_STATIC_UNIQUE_KEY(gShapeVertexBufferKey);
1999
2000const GrBuffer* InstanceProcessor::FindOrCreateVertexBuffer(GrGpu* gpu) {
2001 GR_DEFINE_STATIC_UNIQUE_KEY(gShapeVertexBufferKey);
2002 GrResourceCache* cache = gpu->getContext()->getResourceCache();
2003 if (GrGpuResource* cached = cache->findAndRefUniqueResource(gShapeVertexBufferKey)) {
2004 return static_cast<GrBuffer*>(cached);
2005 }
2006 if (GrBuffer* buffer = gpu->createBuffer(sizeof(kVertexData), kVertex_GrBufferType,
2007 kStatic_GrAccessPattern, kVertexData)) {
2008 buffer->resourcePriv().setUniqueKey(gShapeVertexBufferKey);
2009 return buffer;
2010 }
2011 return nullptr;
2012}
2013
2014GR_DECLARE_STATIC_UNIQUE_KEY(gShapeIndexBufferKey);
2015
2016const GrBuffer* InstanceProcessor::FindOrCreateIndex8Buffer(GrGpu* gpu) {
2017 GR_DEFINE_STATIC_UNIQUE_KEY(gShapeIndexBufferKey);
2018 GrResourceCache* cache = gpu->getContext()->getResourceCache();
2019 if (GrGpuResource* cached = cache->findAndRefUniqueResource(gShapeIndexBufferKey)) {
2020 return static_cast<GrBuffer*>(cached);
2021 }
2022 if (GrBuffer* buffer = gpu->createBuffer(sizeof(kIndexData), kIndex_GrBufferType,
2023 kStatic_GrAccessPattern, kIndexData)) {
2024 buffer->resourcePriv().setUniqueKey(gShapeIndexBufferKey);
2025 return buffer;
2026 }
2027 return nullptr;
2028}
2029
2030IndexRange InstanceProcessor::GetIndexRangeForRect(AntialiasMode aa) {
2031 static constexpr IndexRange kRectRanges[kNumAntialiasModes] = {
2032 {kRect_FirstIndex, 3 * kRect_TriCount}, // kNone
2033 {kFramedRect_FirstIndex, 3 * kFramedRect_TriCount}, // kCoverage
2034 {kRect_FirstIndex, 3 * kRect_TriCount}, // kMSAA
2035 {kRect_FirstIndex, 3 * kRect_TriCount} // kMixedSamples
2036 };
2037
2038 SkASSERT(aa >= AntialiasMode::kNone && aa <= AntialiasMode::kMixedSamples);
2039 return kRectRanges[(int)aa];
2040
2041 GR_STATIC_ASSERT(0 == (int)AntialiasMode::kNone);
2042 GR_STATIC_ASSERT(1 == (int)AntialiasMode::kCoverage);
2043 GR_STATIC_ASSERT(2 == (int)AntialiasMode::kMSAA);
2044 GR_STATIC_ASSERT(3 == (int)AntialiasMode::kMixedSamples);
2045}
2046
2047IndexRange InstanceProcessor::GetIndexRangeForOval(AntialiasMode aa, const SkRect& devBounds) {
2048 if (AntialiasMode::kCoverage == aa && devBounds.height() * devBounds.width() >= 256 * 256) {
2049 // This threshold was chosen quasi-scientifically on Tegra X1.
2050 return {kDisjoint16Gons_FirstIndex, 3 * kDisjoint16Gons_TriCount};
2051 }
2052
2053 static constexpr IndexRange kOvalRanges[kNumAntialiasModes] = {
2054 {kOctagons_FirstIndex, 3 * kOctagons_TriCount}, // kNone
2055 {kDisjointOctagons_FirstIndex, 3 * kDisjointOctagons_TriCount}, // kCoverage
2056 {kOctagons_FirstIndex, 3 * kOctagons_TriCount}, // kMSAA
2057 {kOctagonsFanned_FirstIndex, 3 * kOctagonsFanned_TriCount} // kMixedSamples
2058 };
2059
2060 SkASSERT(aa >= AntialiasMode::kNone && aa <= AntialiasMode::kMixedSamples);
2061 return kOvalRanges[(int)aa];
2062
2063 GR_STATIC_ASSERT(0 == (int)AntialiasMode::kNone);
2064 GR_STATIC_ASSERT(1 == (int)AntialiasMode::kCoverage);
2065 GR_STATIC_ASSERT(2 == (int)AntialiasMode::kMSAA);
2066 GR_STATIC_ASSERT(3 == (int)AntialiasMode::kMixedSamples);
2067}
2068
2069IndexRange InstanceProcessor::GetIndexRangeForRRect(AntialiasMode aa) {
2070 static constexpr IndexRange kRRectRanges[kNumAntialiasModes] = {
2071 {kCorneredRect_FirstIndex, 3 * kCorneredRect_TriCount}, // kNone
2072 {kCorneredFramedRect_FirstIndex, 3 * kCorneredFramedRect_TriCount}, // kCoverage
2073 {kCorneredRect_FirstIndex, 3 * kCorneredRect_TriCount}, // kMSAA
2074 {kCorneredRectFanned_FirstIndex, 3 * kCorneredRectFanned_TriCount} // kMixedSamples
2075 };
2076
2077 SkASSERT(aa >= AntialiasMode::kNone && aa <= AntialiasMode::kMixedSamples);
2078 return kRRectRanges[(int)aa];
2079
2080 GR_STATIC_ASSERT(0 == (int)AntialiasMode::kNone);
2081 GR_STATIC_ASSERT(1 == (int)AntialiasMode::kCoverage);
2082 GR_STATIC_ASSERT(2 == (int)AntialiasMode::kMSAA);
2083 GR_STATIC_ASSERT(3 == (int)AntialiasMode::kMixedSamples);
2084}
2085
2086const char* InstanceProcessor::GetNameOfIndexRange(IndexRange range) {
2087 switch (range.fStart) {
2088 case kRect_FirstIndex: return "basic_rect";
2089 case kFramedRect_FirstIndex: return "coverage_rect";
2090
2091 case kOctagons_FirstIndex: return "basic_oval";
2092 case kDisjointOctagons_FirstIndex: return "coverage_oval";
2093 case kDisjoint16Gons_FirstIndex: return "coverage_large_oval";
2094 case kOctagonsFanned_FirstIndex: return "mixed_samples_oval";
2095
2096 case kCorneredRect_FirstIndex: return "basic_round_rect";
2097 case kCorneredFramedRect_FirstIndex: return "coverage_round_rect";
2098 case kCorneredRectFanned_FirstIndex: return "mixed_samples_round_rect";
2099
2100 default: return "unknown";
2101 }
2102}
2103
2104}