Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(204)

Side by Side Diff: src/gpu/instanced/InstanceProcessor.cpp

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

Powered by Google App Engine
This is Rietveld 408576698