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

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

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