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