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

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: get mixed samples and base instance paths working again 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
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() < kNumVertexAttribs) {
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 == kShapeCoords_AttribIdx);
61 GR_STATIC_ASSERT(1 == kVertexAttrs_AttribIdx);
62 GR_STATIC_ASSERT(2 == kInstanceInfo_AttribIdx);
63 GR_STATIC_ASSERT(3 == kShapeMatrixX_AttribIdx);
64 GR_STATIC_ASSERT(4 == kShapeMatrixY_AttribIdx);
65 GR_STATIC_ASSERT(5 == kColor_AttribIdx);
66 GR_STATIC_ASSERT(6 == kLocalRect_AttribIdx);
67 GR_STATIC_ASSERT(7 == kNumVertexAttribs);
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(kInstanceInfo_AttribIdx));
116 }
117
118 const char* attr(AttribIdx idx) const { return fInstProc.getAttrib(idx).fNam e; }
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(kShape Coords_AttribIdx);
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(kShapeMatrixX_AttribIdx), inputs.attr(kShapeM atrixY_AttribIdx));
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(kShapeMatrixX_AttribIdx), inputs.attr(kShapeM atrixY_AttribIdx));
232 v->codeAppendf("if (0u != (%s & PERSPECTIVE_FLAG)) {",
233 inputs.attr(kInstanceInfo_AttribIdx));
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(kInstanceInfo_AttribIdx));
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(kInstanceInfo_AttribIdx));
290 }
291 // Here we take advantage of the fact that outerRect == localRect in rec ordDRRect.
292 v->codeAppendf("vec4 outer = %s;", inputs.attr(kLocalRect_AttribIdx));
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(kLocalRect_AttribIdx), inputs.attr(kLocalRect _AttribIdx));
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(kInstanceInfo_AttribIdx));
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;",
385 fModifiedShapeCoords, fInputs.attr(kShapeCoords_AttribIdx ));
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(kColor_AttribIdx ));
393 }
394 }
395
396 void GLSLInstanceProcessor::Backend::setupRRect(GrGLSLVertexBuilder* v) {
397 v->codeAppendf("uvec2 corner = uvec2(%s & 1, (%s >> 1) & 1);",
398 fInputs.attr(kVertexAttrs_AttribIdx), fInputs.attr(kVertexAtt rs_AttribIdx));
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(kShapeCoords_AttribI dx));
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(kShapeCoords_AttribIdx), fModifiedShapeCoord s);
494 v->codeAppendf("if (abs(%s.y) == 0.5) "
495 "%s.y = cornerSign.y * (1.0 - radii.y);",
496 fInputs.attr(kShapeCoords_AttribIdx), fModifiedShapeCoord s);
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 this->onEmitCode(v, f, fModifiesCoverage ? outCoverage : nullptr,
521 fModifiesColor ? outColor : nullptr);
522 if (!fModifiesCoverage) {
523 // Even though the subclass doesn't use coverage, we are expected to ass ign some value.
524 f->codeAppendf("%s = vec4(1);", outCoverage);
525 }
526 if (!fModifiesColor) {
527 // The subclass didn't assign a value to the output color.
528 f->codeAppendf("%s = %s;", outColor, fColor.fsIn());
529 }
530 }
531
532 //////////////////////////////////////////////////////////////////////////////// ////////////////////
533
534 class GLSLInstanceProcessor::BackendNonAA : public Backend {
535 public:
536 BackendNonAA(BatchInfo batchInfo, const VertexInputs& inputs)
537 : INHERITED(batchInfo, inputs) {
538 if (fBatchInfo.fCannotDiscard && !fBatchInfo.isSimpleRects()) {
539 fModifiesColor = !fBatchInfo.fCannotTweakAlphaForCoverage;
540 fModifiesCoverage = !fModifiesColor;
541 }
542 }
543
544 private:
545 void onInit(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
546 void setupRect(GrGLSLVertexBuilder*) override;
547 void setupOval(GrGLSLVertexBuilder*) override;
548
549 void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
550 void setupInnerRect(GrGLSLVertexBuilder*) override;
551 void setupInnerOval(GrGLSLVertexBuilder*) override;
552 void onSetupInnerRRect(GrGLSLVertexBuilder*) override;
553
554 void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char*,
555 const char*) override;
556
557 typedef Backend INHERITED;
558 };
559
560 void GLSLInstanceProcessor::BackendNonAA::onInit(GrGLSLVaryingHandler* varyingHa ndler,
561 GrGLSLVertexBuilder*) {
562 if (kRect_ShapeFlag != fBatchInfo.fShapeTypes) {
563 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kHigh_G rSLPrecision);
564 varyingHandler->addVarying("arcCoords", &fArcCoords, kMedium_GrSLPrecisi on);
565 }
566 }
567
568 void GLSLInstanceProcessor::BackendNonAA::setupRect(GrGLSLVertexBuilder* v) {
569 if (fTriangleIsArc.vsOut()) {
570 v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
571 }
572 }
573
574 void GLSLInstanceProcessor::BackendNonAA::setupOval(GrGLSLVertexBuilder* v) {
575 SkASSERT(fArcCoords.vsOut());
576 SkASSERT(fTriangleIsArc.vsOut());
577 v->codeAppendf("%s = %s;", fArcCoords.vsOut(), this->outShapeCoords());
578 v->codeAppendf("%s = %s & 1;", fTriangleIsArc.vsOut(), fInputs.attr(kVertexA ttrs_AttribIdx));
579 }
580
581 void GLSLInstanceProcessor::BackendNonAA::onInitInnerShape(GrGLSLVaryingHandler* varyingHandler,
582 GrGLSLVertexBuilder*) {
583 varyingHandler->addVarying("innerShapeCoords", &fInnerShapeCoords, kMedium_G rSLPrecision);
584 if (kRect_ShapeFlag != fBatchInfo.fInnerShapeTypes &&
585 kOval_ShapeFlag != fBatchInfo.fInnerShapeTypes) {
586 varyingHandler->addFlatVarying("innerRRect", &fInnerRRect, kMedium_GrSLP recision);
587 }
588 }
589
590 void GLSLInstanceProcessor::BackendNonAA::setupInnerRect(GrGLSLVertexBuilder* v) {
591 if (fInnerRRect.vsOut()) {
592 v->codeAppendf("%s = vec4(1);", fInnerRRect.vsOut());
593 }
594 }
595
596 void GLSLInstanceProcessor::BackendNonAA::setupInnerOval(GrGLSLVertexBuilder* v) {
597 if (fInnerRRect.vsOut()) {
598 v->codeAppendf("%s = vec4(0, 0, 1, 1);", fInnerRRect.vsOut());
599 }
600 }
601
602 void GLSLInstanceProcessor::BackendNonAA::onSetupInnerRRect(GrGLSLVertexBuilder* v) {
603 v->codeAppendf("%s = vec4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect .vsOut());
604 }
605
606 void GLSLInstanceProcessor::BackendNonAA::onEmitCode(GrGLSLVertexBuilder*,
607 GrGLSLPPFragmentBuilder* f,
608 const char* outCoverage,
609 const char* outColor) {
610 const char* dropFragment = nullptr;
611 if (!fBatchInfo.fCannotDiscard) {
612 dropFragment = "discard";
613 } else if (fModifiesCoverage) {
614 f->appendPrecisionModifier(kLow_GrSLPrecision);
615 f->codeAppend ("float covered = 1.0;");
616 dropFragment = "covered = 0.0";
617 } else if (fModifiesColor) {
618 f->appendPrecisionModifier(kLow_GrSLPrecision);
619 f->codeAppendf("vec4 color = %s;", fColor.fsIn());
620 dropFragment = "color = vec4(0)";
621 }
622 if (fTriangleIsArc.fsIn()) {
623 SkASSERT(dropFragment);
624 f->appendPrecisionModifier(kLow_GrSLPrecision);
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 fColorTimesCoverage(kVec4f_GrSLType),
667 fDistanceToEdge(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 fColorTimesCoverage;
706 GrGLSLVertToFrag fDistanceToEdge;
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);",
727 fInputs.attr(kShapeCoords_AttribIdx));
728
729 if (kOval_ShapeFlag != fBatchInfo.fShapeTypes) {
730 if (fTweakAlphaForCoverage) {
731 varyingHandler->addVarying("colorTimesCoverage", &fColorTimesCoverag e,
732 kLow_GrSLPrecision);
733 if (kRect_ShapeFlag == fBatchInfo.fShapeTypes) {
734 fColor = fColorTimesCoverage;
735 }
736 } else {
737 varyingHandler->addVarying("distanceToEdge", &fDistanceToEdge, kLow_ GrSLPrecision);
738 }
739 v->codeAppend("float distanceToEdge = 0.0;");
740 }
741 if (kRect_ShapeFlag != fBatchInfo.fShapeTypes) {
742 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc, kHigh_G rSLPrecision);
743 if (!fShapeIsCircle) {
744 varyingHandler->addVarying("ellipseCoords", &fEllipseCoords, kHigh_G rSLPrecision);
745 varyingHandler->addFlatVarying("ellipseName", &fEllipseName, kHigh_G rSLPrecision);
746 } else {
747 varyingHandler->addVarying("circleCoords", &fEllipseCoords, kMedium_ GrSLPrecision);
748 varyingHandler->addFlatVarying("bloatedRadius", &fBloatedRadius, kMe dium_GrSLPrecision);
749 }
750 }
751 }
752
753 void GLSLInstanceProcessor::BackendCoverage::setupRect(GrGLSLVertexBuilder* v) {
754 // Offset the inner and outer rects by one pixel. Inner vs outer is indicate d by coordAttrs.
755 v->codeAppendf("vec2 rectBloat = (%s != 0) ? bloat : -bloat;",
756 fInputs.attr(kVertexAttrs_AttribIdx));
757 v->codeAppendf("bloatedShapeCoords = %s * max(vec2(1.0 + rectBloat), vec2(0) );",
758 fInputs.attr(kShapeCoords_AttribIdx));
759
760 // The geometry is laid out in such a way that distanceToEdge will be 0 and 1 on the vertices,
761 // but we still need to recompute this value because when the rect gets thin ner than one pixel,
762 // the interior edge of the border will necessarily clamp.
763 v->codeAppend ("vec2 d = shapeHalfSize + 0.5 - abs(bloatedShapeCoords) * sha peHalfSize;");
764 v->codeAppend ("distanceToEdge = min(d.x, d.y);");
765
766 if (fTriangleIsArc.vsOut()) {
767 v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
768 }
769 }
770
771 void GLSLInstanceProcessor::BackendCoverage::setupOval(GrGLSLVertexBuilder* v) {
772 // Offset the inner and outer octagons by one pixel. Inner vs outer is indic ated by coordAttrs.
773 v->codeAppendf("vec2 ovalBloat = (%s != 0) ? bloat : -bloat;",
774 fInputs.attr(kVertexAttrs_AttribIdx));
775 v->codeAppendf("bloatedShapeCoords = %s * max(vec2(1.0 + ovalBloat), vec2(0) );",
776 fInputs.attr(kShapeCoords_AttribIdx));
777 v->codeAppendf("%s = bloatedShapeCoords * shapeHalfSize;", fEllipseCoords.vs Out());
778 if (fEllipseName.vsOut()) {
779 v->codeAppendf("%s = 1.0 / (shapeHalfSize * shapeHalfSize);", fEllipseNa me.vsOut());
780 }
781 if (fBloatedRadius.vsOut()) {
782 SkASSERT(fShapeIsCircle);
783 v->codeAppendf("%s = shapeHalfSize.x + bloat.x;", fBloatedRadius.vsOut() );
784 }
785 if (fTriangleIsArc.vsOut()) {
786 v->codeAppendf("%s = int(%s != 0);",
787 fTriangleIsArc.vsOut(), fInputs.attr(kVertexAttrs_AttribI dx));
788 }
789 if (fColorTimesCoverage.vsOut() || fDistanceToEdge.vsOut()) {
790 v->codeAppendf("distanceToEdge = 1.0;");
791 }
792 }
793
794 void GLSLInstanceProcessor::BackendCoverage::adjustRRectVertices(GrGLSLVertexBui lder* v) {
795 // We try to let the AA borders line up with the arc edges on their particul ar side, but we
796 // can't allow them to get closer than one half pixel to the edge or they mi ght overlap with
797 // their neighboring border.
798 v->codeAppend("vec2 innerEdge = max(1.0 - bloat, vec2(0));");
799 v->codeAppend ("vec2 borderEdge = cornerSign * clamp(1.0 - radii, -innerEdge , innerEdge);");
800 // 0.5 is a special value that indicates this vertex is an arc edge.
801 v->codeAppendf("if (abs(%s.x) == 0.5)"
802 "%s.x = borderEdge.x;",
803 fInputs.attr(kShapeCoords_AttribIdx), fModifiedShapeCoord s);
804 v->codeAppendf("if (abs(%s.y) == 0.5)"
805 "%s.y = borderEdge.y;",
806 fInputs.attr(kShapeCoords_AttribIdx), fModifiedShapeCoord s);
807
808 // Adjust the interior border vertices to make the border one pixel wide. 0. 75 is a special
809 // value to indicate these points.
810 v->codeAppendf("if (abs(%s.x) == 0.75) "
811 "%s.x = cornerSign.x * innerEdge.x;",
812 fInputs.attr(kShapeCoords_AttribIdx), fModifiedShapeCoord s);
813 v->codeAppendf("if (abs(%s.y) == 0.75) "
814 "%s.y = cornerSign.y * innerEdge.y;",
815 fInputs.attr(kShapeCoords_AttribIdx), fModifiedShapeCoord s);
816 }
817
818 void GLSLInstanceProcessor::BackendCoverage::onSetupRRect(GrGLSLVertexBuilder* v ) {
819 // The geometry is laid out in such a way that distanceToEdge will be 0 and 1 on the vertices,
820 // but we still need to recompute this value because when the rrect gets thi nner than one pixel,
821 // the interior edge of the border will necessarily clamp.
822 v->codeAppend("vec2 d = shapeHalfSize + 0.5 - abs(bloatedShapeCoords) * shap eHalfSize;");
823 v->codeAppend("distanceToEdge = min(d.x, d.y);");
824
825 SkASSERT(!fShapeIsCircle);
826 // The AA border does not get closer than one half pixel to the edge of the rect, so to get a
827 // smooth transition from flat edge to arc, we don't allow the radii to be s maller than one half
828 // pixel. (We don't worry about the transition on the opposite side when a r adius is so large
829 // that the border clamped on that side.)
830 v->codeAppendf("vec2 clampedRadii = max(radii, bloat);");
831 v->codeAppendf("%s = (cornerSign * %s + clampedRadii - vec2(1)) * shapeHalfS ize;",
832 fEllipseCoords.vsOut(), fModifiedShapeCoords);
833 v->codeAppendf("%s = 1.0 / (clampedRadii * clampedRadii * shapeHalfSize * sh apeHalfSize);",
834 fEllipseName.vsOut());
835 }
836
837 void GLSLInstanceProcessor::BackendCoverage::onInitInnerShape(GrGLSLVaryingHandl er* varyingHandler,
838 GrGLSLVertexBuilde r* v) {
839 v->codeAppend("vec2 innerShapeHalfSize = shapeHalfSize / innerCoords.xy;");
840
841 if (kOval_ShapeFlag == fBatchInfo.fInnerShapeTypes) {
842 varyingHandler->addVarying("innerEllipseCoords", &fInnerEllipseCoords,
843 kMedium_GrSLPrecision);
844 varyingHandler->addFlatVarying("innerEllipseName", &fInnerEllipseName,
845 kMedium_GrSLPrecision);
846 } else {
847 varyingHandler->addVarying("distanceToInnerEdge", &fDistanceToInnerEdge,
848 kMedium_GrSLPrecision);
849 varyingHandler->addFlatVarying("innerShapeBloatedHalfSize", &fInnerShape BloatedHalfSize,
850 kMedium_GrSLPrecision);
851 if (kRect_ShapeFlag != fBatchInfo.fInnerShapeTypes) {
852 varyingHandler->addVarying("innerShapeCoords", &fInnerShapeCoords, k High_GrSLPrecision);
853 varyingHandler->addFlatVarying("innerEllipseName", &fInnerEllipseNam e,
854 kMedium_GrSLPrecision);
855 varyingHandler->addFlatVarying("innerRRect", &fInnerRRect, kHigh_GrS LPrecision);
856 }
857 }
858 }
859
860 void GLSLInstanceProcessor::BackendCoverage::setupInnerRect(GrGLSLVertexBuilder* v) {
861 if (fInnerRRect.vsOut()) {
862 // The fragment shader will generalize every inner shape as a round rect . Since this one
863 // is a rect, we simply emit bogus parameters for the round rect (negati ve radii) that
864 // ensure the fragment shader always takes the "emitRect" codepath.
865 v->codeAppendf("%s = vec4(2.0 * (inner.zw - inner.xy) / (outer.zw - oute r.xy), vec2(0));",
866 fInnerRRect.vsOut());
867 }
868 }
869
870 void GLSLInstanceProcessor::BackendCoverage::setupInnerOval(GrGLSLVertexBuilder* v) {
871 v->codeAppendf("%s = 1.0 / (innerShapeHalfSize * innerShapeHalfSize);",
872 fInnerEllipseName.vsOut());
873 if (fInnerEllipseCoords.vsOut()) {
874 v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;", fInnerElli pseCoords.vsOut());
875 }
876 if (fInnerRRect.vsOut()) {
877 v->codeAppendf("%s = vec4(0, 0, innerShapeHalfSize);", fInnerRRect.vsOut ());
878 }
879 }
880
881 void GLSLInstanceProcessor::BackendCoverage::onSetupInnerRRect(GrGLSLVertexBuild er* v) {
882 // The distance to ellipse formula doesn't work well when the radii are less than half a pixel.
883 v->codeAppend ("innerRadii = max(innerRadii, bloat);");
884 v->codeAppendf("%s = 1.0 / (innerRadii * innerRadii * innerShapeHalfSize * "
885 "innerShapeHalfSize);",
886 fInnerEllipseName.vsOut());
887 v->codeAppendf("%s = vec4(1.0 - innerRadii, innerShapeHalfSize);", fInnerRRe ct.vsOut());
888 }
889
890 void GLSLInstanceProcessor::BackendCoverage::onEmitCode(GrGLSLVertexBuilder* v,
891 GrGLSLPPFragmentBuilder* f,
892 const char* outCoverage,
893 const char* outColor) {
894 if (fColorTimesCoverage.vsOut()) {
895 v->codeAppendf("%s = %s * distanceToEdge;",
896 fColorTimesCoverage.vsOut(), fInputs.attr(kColor_AttribId x));
897 }
898 if (fDistanceToEdge.vsOut()) {
899 v->codeAppendf("%s = distanceToEdge;", fDistanceToEdge.vsOut());
900 }
901
902 SkString coverage("float coverage");
903 if (f->getProgramBuilder()->glslCaps()->usesPrecisionModifiers()) {
904 coverage.prependf("lowp ");
905 }
906 if (fBatchInfo.fInnerShapeTypes || (!fTweakAlphaForCoverage && fTriangleIsAr c.fsIn())) {
907 f->codeAppendf("%s;", coverage.c_str());
908 coverage = "coverage";
909 }
910 if (fTriangleIsArc.fsIn()) {
911 f->codeAppendf("if (%s == 0) {", fTriangleIsArc.fsIn());
912 this->emitRect(f, coverage.c_str(), outColor);
913 f->codeAppend ("} else {");
914 if (fShapeIsCircle) {
915 this->emitCircle(f, coverage.c_str());
916 } else {
917 bool ellipseCoordsMayBeNegative = SkToBool(fBatchInfo.fShapeTypes & kOval_ShapeFlag);
918 this->emitArc(f, fEllipseCoords.fsIn(), fEllipseName.fsIn(),
919 true /*ellipseCoordsNeedClamp*/, ellipseCoordsMayBeNeg ative,
920 coverage.c_str());
921 }
922 if (fTweakAlphaForCoverage) {
923 f->codeAppendf("%s = %s * coverage;", outColor, fColor.fsIn());
924 }
925 f->codeAppend ("}");
926 } else {
927 this->emitRect(f, coverage.c_str(), outColor);
928 }
929
930 if (fBatchInfo.fInnerShapeTypes) {
931 f->codeAppendf("// Inner shape.\n");
932 SkString innerCoverage("float innerCoverage");
933 if (f->getProgramBuilder()->glslCaps()->usesPrecisionModifiers()) {
934 innerCoverage.prependf("lowp ");
935 }
936 if (kOval_ShapeFlag == fBatchInfo.fInnerShapeTypes) {
937 this->emitArc(f, fInnerEllipseCoords.fsIn(), fInnerEllipseName.fsIn( ),
938 true /*ellipseCoordsNeedClamp*/, true /*ellipseCoordsM ayBeNegative*/,
939 innerCoverage.c_str());
940 } else {
941 v->codeAppendf("%s = innerShapeCoords * innerShapeHalfSize;",
942 fDistanceToInnerEdge.vsOut());
943 v->codeAppendf("%s = innerShapeHalfSize + 0.5;", fInnerShapeBloatedH alfSize.vsOut());
944
945 if (kRect_ShapeFlag == fBatchInfo.fInnerShapeTypes) {
946 this->emitInnerRect(f, innerCoverage.c_str());
947 } else {
948 f->appendPrecisionModifier(kLow_GrSLPrecision);
949 f->codeAppend ("float innerCoverage = 0.0;");
950 f->codeAppendf("vec2 distanceToArcEdge = abs(%s) - %s.xy;",
951 fInnerShapeCoords.fsIn(), fInnerRRect.fsIn());
952 f->codeAppend ("if (any(lessThan(distanceToArcEdge, vec2(1e-5))) ) {");
953 this->emitInnerRect(f, "innerCoverage");
954 f->codeAppend ("} else {");
955 f->codeAppendf( "vec2 ellipseCoords = distanceToArcEdge * %s. zw;",
956 fInnerRRect.fsIn());
957 this->emitArc(f, "ellipseCoords", fInnerEllipseName.fsIn(),
958 false /*ellipseCoordsNeedClamp*/,
959 false /*ellipseCoordsMayBeNegative*/, "innerCovera ge");
960 f->codeAppend ("}");
961 }
962 }
963 f->codeAppendf("%s = vec4(max(coverage - innerCoverage, 0));", outCovera ge);
964 } else if (!fTweakAlphaForCoverage) {
965 f->codeAppendf("%s = vec4(coverage);", outCoverage);
966 }
967 }
968
969 void GLSLInstanceProcessor::BackendCoverage::emitRect(GrGLSLPPFragmentBuilder* f ,
970 const char* outCoverage,
971 const char* outColor) {
972 if (fColorTimesCoverage.fsIn()) {
973 f->codeAppendf("%s = %s;", outColor, fColorTimesCoverage.fsIn());
974 } else if (fTweakAlphaForCoverage) {
975 // We are drawing just ovals. The interior rect always has 100% coverage .
976 f->codeAppendf("%s = %s;", outColor, fColor.fsIn());
977 } else if (fDistanceToEdge.fsIn()) {
978 f->codeAppendf("%s = %s;", outCoverage, fDistanceToEdge.fsIn());
979 } else {
980 f->codeAppendf("%s = 1.0;", outCoverage);
981 }
982 }
983
984 void GLSLInstanceProcessor::BackendCoverage::emitCircle(GrGLSLPPFragmentBuilder* f,
985 const char* outCoverage) {
986 // TODO: circleCoords = max(circleCoords, 0) if we decide to do this optimiz ation on rrects.
987 SkASSERT(!(kRRect_ShapesMask & fBatchInfo.fShapeTypes));
988 f->codeAppendf("float distanceToEdge = %s - length(%s);",
989 fBloatedRadius.fsIn(), fEllipseCoords.fsIn());
990 f->codeAppendf("%s = clamp(distanceToEdge, 0.0, 1.0);", outCoverage);
991 }
992
993 void GLSLInstanceProcessor::BackendCoverage::emitArc(GrGLSLPPFragmentBuilder* f,
994 const char* ellipseCoords,
995 const char* ellipseName,
996 bool ellipseCoordsNeedClamp ,
997 bool ellipseCoordsMayBeNega tive,
998 const char* outCoverage) {
999 SkASSERT(!ellipseCoordsMayBeNegative || ellipseCoordsNeedClamp);
1000 if (ellipseCoordsNeedClamp) {
1001 // This serves two purposes:
1002 // - To restrict the arcs of rounded rects to their positive quadrants.
1003 // - To avoid inversesqrt(0) in the ellipse formula.
1004 if (ellipseCoordsMayBeNegative) {
1005 f->codeAppendf("vec2 ellipseClampedCoords = max(abs(%s), vec2(1e-4)) ;", ellipseCoords);
1006 } else {
1007 f->codeAppendf("vec2 ellipseClampedCoords = max(%s, vec2(1e-4));", e llipseCoords);
1008 }
1009 ellipseCoords = "ellipseClampedCoords";
1010 }
1011 // ellipseCoords are in pixel space and ellipseName is 1 / rx^2, 1 / ry^2.
1012 f->codeAppendf("vec2 Z = %s * %s;", ellipseCoords, ellipseName);
1013 // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
1014 f->codeAppendf("float implicit = dot(Z, %s) - 1.0;", ellipseCoords);
1015 // gradDot is the squared length of the gradient of the implicit.
1016 f->codeAppendf("float gradDot = 4.0 * dot(Z, Z);");
1017 f->appendPrecisionModifier(kLow_GrSLPrecision);
1018 f->codeAppend ("float approxDist = implicit * inversesqrt(gradDot);");
1019 f->codeAppendf("%s = clamp(0.5 - approxDist, 0.0, 1.0);", outCoverage);
1020 }
1021
1022 void GLSLInstanceProcessor::BackendCoverage::emitInnerRect(GrGLSLPPFragmentBuild er* f,
1023 const char* outCovera ge) {
1024 f->appendPrecisionModifier(kLow_GrSLPrecision);
1025 f->codeAppendf("vec2 c = %s - abs(%s);",
1026 fInnerShapeBloatedHalfSize.fsIn(), fDistanceToInnerEdge.fsIn( ));
1027 f->codeAppendf("%s = clamp(min(c.x, c.y), 0.0, 1.0);", outCoverage);
1028 }
1029
1030 //////////////////////////////////////////////////////////////////////////////// ////////////////////
1031
1032 class GLSLInstanceProcessor::BackendMultisample : public Backend {
1033 public:
1034 BackendMultisample(BatchInfo batchInfo, const VertexInputs& inputs, int effe ctiveSampleCnt)
1035 : INHERITED(batchInfo, inputs),
1036 fEffectiveSampleCnt(effectiveSampleCnt),
1037 fShapeCoords(kVec2f_GrSLType),
1038 fShapeInverseMatrix(kMat22f_GrSLType),
1039 fFragShapeHalfSpan(kVec2f_GrSLType),
1040 fArcTest(kVec2f_GrSLType),
1041 fArcInverseMatrix(kMat22f_GrSLType),
1042 fFragArcHalfSpan(kVec2f_GrSLType),
1043 fEarlyAccept(kInt_GrSLType),
1044 fInnerShapeInverseMatrix(kMat22f_GrSLType),
1045 fFragInnerShapeHalfSpan(kVec2f_GrSLType) {
1046 fRectTrianglesMaySplit = fBatchInfo.fHasPerspective;
1047 fNeedsNeighborRadii = this->isMixedSampled() && !fBatchInfo.fHasPerspect ive;
1048 }
1049
1050 private:
1051 bool isMixedSampled() const { return AntialiasMode::kMixedSamples == fBatchI nfo.fAntialiasMode; }
1052
1053 void onInit(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
1054 void setupRect(GrGLSLVertexBuilder*) override;
1055 void setupOval(GrGLSLVertexBuilder*) override;
1056 void adjustRRectVertices(GrGLSLVertexBuilder*) override;
1057 void onSetupRRect(GrGLSLVertexBuilder*) override;
1058
1059 void onInitInnerShape(GrGLSLVaryingHandler*, GrGLSLVertexBuilder*) override;
1060 void setupInnerRect(GrGLSLVertexBuilder*) override;
1061 void setupInnerOval(GrGLSLVertexBuilder*) override;
1062 void onSetupInnerRRect(GrGLSLVertexBuilder*) override;
1063
1064 void onEmitCode(GrGLSLVertexBuilder*, GrGLSLPPFragmentBuilder*, const char*,
1065 const char*) override;
1066
1067 struct EmitShapeCoords {
1068 const GrGLSLVarying* fVarying;
1069 const char* fInverseMatrix;
1070 const char* fFragHalfSpan;
1071 };
1072
1073 struct EmitShapeOpts {
1074 bool fIsTightGeometry;
1075 bool fResolveMixedSamples;
1076 bool fInvertCoverage;
1077 };
1078
1079 void emitRect(GrGLSLPPFragmentBuilder*, const EmitShapeCoords&, const EmitSh apeOpts&);
1080 void emitArc(GrGLSLPPFragmentBuilder*, const EmitShapeCoords&, bool coordsMa yBeNegative,
1081 bool clampCoords, const EmitShapeOpts&);
1082 void emitSimpleRRect(GrGLSLPPFragmentBuilder*, const EmitShapeCoords&, const char* rrect,
1083 const EmitShapeOpts&);
1084 void interpolateAtSample(GrGLSLPPFragmentBuilder*, const GrGLSLVarying&, con st char* sampleIdx,
1085 const char* interpolationMatrix);
1086 void acceptOrRejectWholeFragment(GrGLSLPPFragmentBuilder*, bool inside, cons t EmitShapeOpts&);
1087 void acceptCoverageMask(GrGLSLPPFragmentBuilder*, const char* shapeMask, con st EmitShapeOpts&,
1088 bool maybeSharedEdge = true);
1089
1090 int fEffectiveSampleCnt;
1091 bool fRectTrianglesMaySplit;
1092 GrGLSLVertToFrag fShapeCoords;
1093 GrGLSLVertToFrag fShapeInverseMatrix;
1094 GrGLSLVertToFrag fFragShapeHalfSpan;
1095 GrGLSLVertToFrag fArcTest;
1096 GrGLSLVertToFrag fArcInverseMatrix;
1097 GrGLSLVertToFrag fFragArcHalfSpan;
1098 GrGLSLVertToFrag fEarlyAccept;
1099 GrGLSLVertToFrag fInnerShapeInverseMatrix;
1100 GrGLSLVertToFrag fFragInnerShapeHalfSpan;
1101 SkString fSquareFun;
1102
1103 typedef Backend INHERITED;
1104 };
1105
1106 void GLSLInstanceProcessor::BackendMultisample::onInit(GrGLSLVaryingHandler* var yingHandler,
1107 GrGLSLVertexBuilder* v) {
1108 if (!this->isMixedSampled()) {
1109 if (kRect_ShapeFlag != fBatchInfo.fShapeTypes) {
1110 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc,
1111 kHigh_GrSLPrecision);
1112 varyingHandler->addVarying("arcCoords", &fArcCoords, kHigh_GrSLPreci sion);
1113 if (!fBatchInfo.fHasPerspective) {
1114 varyingHandler->addFlatVarying("arcInverseMatrix", &fArcInverseM atrix,
1115 kHigh_GrSLPrecision);
1116 varyingHandler->addFlatVarying("fragArcHalfSpan", &fFragArcHalfS pan,
1117 kHigh_GrSLPrecision);
1118 }
1119 } else if (!fBatchInfo.fInnerShapeTypes) {
1120 return;
1121 }
1122 } else {
1123 varyingHandler->addVarying("shapeCoords", &fShapeCoords, kHigh_GrSLPreci sion);
1124 if (!fBatchInfo.fHasPerspective) {
1125 varyingHandler->addFlatVarying("shapeInverseMatrix", &fShapeInverseM atrix,
1126 kHigh_GrSLPrecision);
1127 varyingHandler->addFlatVarying("fragShapeHalfSpan", &fFragShapeHalfS pan,
1128 kHigh_GrSLPrecision);
1129 }
1130 if (fBatchInfo.fShapeTypes & kRRect_ShapesMask) {
1131 varyingHandler->addVarying("arcCoords", &fArcCoords, kHigh_GrSLPreci sion);
1132 varyingHandler->addVarying("arcTest", &fArcTest, kHigh_GrSLPrecision );
1133 if (!fBatchInfo.fHasPerspective) {
1134 varyingHandler->addFlatVarying("arcInverseMatrix", &fArcInverseM atrix,
1135 kHigh_GrSLPrecision);
1136 varyingHandler->addFlatVarying("fragArcHalfSpan", &fFragArcHalfS pan,
1137 kHigh_GrSLPrecision);
1138 }
1139 } else if (fBatchInfo.fShapeTypes & kOval_ShapeFlag) {
1140 fArcCoords = fShapeCoords;
1141 fArcInverseMatrix = fShapeInverseMatrix;
1142 fFragArcHalfSpan = fFragShapeHalfSpan;
1143 if (fBatchInfo.fShapeTypes & kRect_ShapeFlag) {
1144 varyingHandler->addFlatVarying("triangleIsArc", &fTriangleIsArc,
1145 kHigh_GrSLPrecision);
1146 }
1147 }
1148 if (kRect_ShapeFlag != fBatchInfo.fShapeTypes) {
1149 v->definef("SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1) ;
1150 varyingHandler->addFlatVarying("earlyAccept", &fEarlyAccept, kHigh_Gr SLPrecision);
1151 }
1152 }
1153 if (!fBatchInfo.fHasPerspective) {
1154 v->codeAppend("mat2 shapeInverseMatrix = inverse(mat2(shapeMatrix));");
1155 v->codeAppend("vec2 fragShapeSpan = abs(vec4(shapeInverseMatrix).xz) + "
1156 "abs(vec4(shapeInverseMatrix).yw);");
1157 }
1158 }
1159
1160 void GLSLInstanceProcessor::BackendMultisample::setupRect(GrGLSLVertexBuilder* v ) {
1161 if (fShapeCoords.vsOut()) {
1162 v->codeAppendf("%s = %s;", fShapeCoords.vsOut(), this->outShapeCoords()) ;
1163 }
1164 if (fShapeInverseMatrix.vsOut()) {
1165 v->codeAppendf("%s = shapeInverseMatrix;", fShapeInverseMatrix.vsOut());
1166 }
1167 if (fFragShapeHalfSpan.vsOut()) {
1168 v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut());
1169 }
1170 if (fArcTest.vsOut()) {
1171 // Pick a value that is not > 0.
1172 v->codeAppendf("%s = vec2(0);", fArcTest.vsOut());
1173 }
1174 if (fTriangleIsArc.vsOut()) {
1175 v->codeAppendf("%s = 0;", fTriangleIsArc.vsOut());
1176 }
1177 if (fEarlyAccept.vsOut()) {
1178 v->codeAppendf("%s = SAMPLE_MASK_ALL;", fEarlyAccept.vsOut());
1179 }
1180 }
1181
1182 void GLSLInstanceProcessor::BackendMultisample::setupOval(GrGLSLVertexBuilder* v ) {
1183 v->codeAppendf("%s = abs(%s);", fArcCoords.vsOut(), this->outShapeCoords());
1184 if (fArcInverseMatrix.vsOut()) {
1185 v->codeAppendf("vec2 s = sign(%s);", this->outShapeCoords());
1186 v->codeAppendf("%s = shapeInverseMatrix * mat2(s.x, 0, 0 , s.y);",
1187 fArcInverseMatrix.vsOut());
1188 }
1189 if (fFragArcHalfSpan.vsOut()) {
1190 v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragArcHalfSpan.vsOut());
1191 }
1192 if (fArcTest.vsOut()) {
1193 // Pick a value that is > 0.
1194 v->codeAppendf("%s = vec2(1);", fArcTest.vsOut());
1195 }
1196 if (fTriangleIsArc.vsOut()) {
1197 if (!this->isMixedSampled()) {
1198 v->codeAppendf("%s = %s & 1;",
1199 fTriangleIsArc.vsOut(), fInputs.attr(kVertexAttrs_Att ribIdx));
1200 } else {
1201 v->codeAppendf("%s = 1;", fTriangleIsArc.vsOut());
1202 }
1203 }
1204 if (fEarlyAccept.vsOut()) {
1205 v->codeAppendf("%s = ~%s & SAMPLE_MASK_ALL;",
1206 fEarlyAccept.vsOut(), fInputs.attr(kVertexAttrs_AttribIdx ));
1207 }
1208 }
1209
1210 void GLSLInstanceProcessor::BackendMultisample::adjustRRectVertices(GrGLSLVertex Builder* v) {
1211 if (!this->isMixedSampled()) {
1212 INHERITED::adjustRRectVertices(v);
1213 return;
1214 }
1215
1216 if (!fBatchInfo.fHasPerspective) {
1217 // For the mixed samples algorithm it's best to bloat the corner triangl es a bit so that
1218 // more of the pixels that cross into the arc region are completely insi de the shared edges.
1219 // We also snap to a regular rect if the radii shrink smaller than a pix el.
1220 v->codeAppend ("vec2 midpt = 0.5 * (neighborRadii - radii);");
1221 v->codeAppend ("vec2 cornerSize = any(lessThan(radii, fragShapeSpan)) ? "
1222 "vec2(0) : min(radii + 0.5 * fragShapeSpan, 1.0 - mid pt);");
1223 } else {
1224 // TODO: We could still bloat the corner triangle in the perspective cas e; we would just
1225 // need to find the screen-space derivative of shape coords at this part icular point.
1226 v->codeAppend ("vec2 cornerSize = any(lessThan(radii, vec2(1e-3))) ? vec 2(0) : radii;");
1227 }
1228
1229 v->codeAppendf("if (abs(%s.x) == 0.5)"
1230 "%s.x = cornerSign.x * (1.0 - cornerSize.x);",
1231 fInputs.attr(kShapeCoords_AttribIdx), fModifiedShapeCoord s);
1232 v->codeAppendf("if (abs(%s.y) == 0.5)"
1233 "%s.y = cornerSign.y * (1.0 - cornerSize.y);",
1234 fInputs.attr(kShapeCoords_AttribIdx), fModifiedShapeCoord s);
1235 }
1236
1237 void GLSLInstanceProcessor::BackendMultisample::onSetupRRect(GrGLSLVertexBuilder * v) {
1238 if (fShapeCoords.vsOut()) {
1239 v->codeAppendf("%s = %s;", fShapeCoords.vsOut(), this->outShapeCoords()) ;
1240 }
1241 if (fShapeInverseMatrix.vsOut()) {
1242 v->codeAppendf("%s = shapeInverseMatrix;", fShapeInverseMatrix.vsOut());
1243 }
1244 if (fFragShapeHalfSpan.vsOut()) {
1245 v->codeAppendf("%s = 0.5 * fragShapeSpan;", fFragShapeHalfSpan.vsOut());
1246 }
1247 if (fArcInverseMatrix.vsOut()) {
1248 v->codeAppend ("vec2 s = cornerSign / radii;");
1249 v->codeAppendf("%s = shapeInverseMatrix * mat2(s.x, 0, 0, s.y);",
1250 fArcInverseMatrix.vsOut());
1251 }
1252 if (fFragArcHalfSpan.vsOut()) {
1253 v->codeAppendf("%s = 0.5 * (abs(vec4(%s).xz) + abs(vec4(%s).yw));",
1254 fFragArcHalfSpan.vsOut(), fArcInverseMatrix.vsOut(),
1255 fArcInverseMatrix.vsOut());
1256 }
1257 if (fArcTest.vsOut()) {
1258 // The interior triangles are laid out as a fan. fArcTest is both distan ces from shared
1259 // edges of a fan triangle to a point within that triangle. fArcTest is used to check if a
1260 // fragment is too close to either shared edge, in which case we point s ample the shape as a
1261 // rect at that point in order to guarantee the mixed samples discard lo gic works correctly.
1262 v->codeAppendf("%s = (cornerSize == vec2(0)) ? vec2(0) : "
1263 "cornerSign * %s * mat2(1, cornerSize.x - 1.0, cornerSize .y - 1.0, 1);",
1264 fArcTest.vsOut(), fModifiedShapeCoords);
1265 if (!fBatchInfo.fHasPerspective) {
1266 // Shift the point at which distances to edges are measured from the center of the pixel
1267 // to the corner. This way the sign of fArcTest will quickly tell us whether a pixel
1268 // is completely inside the shared edge. Perspective mode will accom plish this same task
1269 // by finding the derivatives in the fragment shader.
1270 v->codeAppendf("%s -= 0.5 * (fragShapeSpan.yx * abs(radii - 1.0) + f ragShapeSpan);",
1271 fArcTest.vsOut());
1272 }
1273 }
1274 if (fEarlyAccept.vsOut()) {
1275 SkASSERT(this->isMixedSampled());
1276 v->codeAppendf("%s = all(equal(vec2(1), abs(%s))) ? 0 : SAMPLE_MASK_ALL; ",
1277 fEarlyAccept.vsOut(), fInputs.attr(kShapeCoords_AttribIdx ));
1278 }
1279 }
1280
1281 void
1282 GLSLInstanceProcessor::BackendMultisample::onInitInnerShape(GrGLSLVaryingHandler * varyingHandler,
1283 GrGLSLVertexBuilder* v) {
1284 varyingHandler->addVarying("innerShapeCoords", &fInnerShapeCoords, kHigh_GrS LPrecision);
1285 if (kOval_ShapeFlag != fBatchInfo.fInnerShapeTypes &&
1286 kRect_ShapeFlag != fBatchInfo.fInnerShapeTypes) {
1287 varyingHandler->addFlatVarying("innerRRect", &fInnerRRect, kHigh_GrSLPre cision);
1288 }
1289 if (!fBatchInfo.fHasPerspective) {
1290 varyingHandler->addFlatVarying("innerShapeInverseMatrix", &fInnerShapeIn verseMatrix,
1291 kHigh_GrSLPrecision);
1292 v->codeAppendf("%s = shapeInverseMatrix * mat2(innerCoords.x, 0, 0, inne rCoords.y);",
1293 fInnerShapeInverseMatrix.vsOut());
1294 varyingHandler->addFlatVarying("fragInnerShapeHalfSpan", &fFragInnerShap eHalfSpan,
1295 kHigh_GrSLPrecision);
1296 v->codeAppendf("%s = 0.5 * fragShapeSpan * innerCoords.xy;",
1297 fFragInnerShapeHalfSpan.vsOut());
1298 }
1299 }
1300
1301 void GLSLInstanceProcessor::BackendMultisample::setupInnerRect(GrGLSLVertexBuild er* v) {
1302 if (fInnerRRect.vsOut()) {
1303 // The fragment shader will generalize every inner shape as a round rect . Since this one
1304 // is a rect, we simply emit bogus parameters for the round rect (negati ve radii) that
1305 // ensure the fragment shader always takes the "sample as rect" codepath .
1306 v->codeAppendf("%s = vec4(2.0 * (inner.zw - inner.xy) / (outer.zw - oute r.xy), vec2(0));",
1307 fInnerRRect.vsOut());
1308 }
1309 }
1310
1311 void GLSLInstanceProcessor::BackendMultisample::setupInnerOval(GrGLSLVertexBuild er* v) {
1312 if (fInnerRRect.vsOut()) {
1313 v->codeAppendf("%s = vec4(0, 0, 1, 1);", fInnerRRect.vsOut());
1314 }
1315 }
1316
1317 void GLSLInstanceProcessor::BackendMultisample::onSetupInnerRRect(GrGLSLVertexBu ilder* v) {
1318 // Avoid numeric instability by not allowing the inner radii to get smaller than 1/10th pixel.
1319 if (fFragInnerShapeHalfSpan.vsOut()) {
1320 v->codeAppendf("innerRadii = max(innerRadii, 2e-1 * %s);", fFragInnerSha peHalfSpan.vsOut());
1321 } else {
1322 v->codeAppend ("innerRadii = max(innerRadii, vec2(1e-4));");
1323 }
1324 v->codeAppendf("%s = vec4(1.0 - innerRadii, 1.0 / innerRadii);", fInnerRRect .vsOut());
1325 }
1326
1327 void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
1328 GrGLSLPPFragmentBuild er* f,
1329 const char*, const ch ar*) {
1330 f->define("SAMPLE_COUNT", fEffectiveSampleCnt);
1331 if (this->isMixedSampled()) {
1332 f->definef("SAMPLE_MASK_ALL", "0x%x", (1 << fEffectiveSampleCnt) - 1);
1333 f->definef("SAMPLE_MASK_MSB", "0x%x", 1 << (fEffectiveSampleCnt - 1));
1334 }
1335
1336 if (kRect_ShapeFlag != (fBatchInfo.fShapeTypes | fBatchInfo.fInnerShapeTypes )) {
1337 GrGLSLShaderVar x("x", kVec2f_GrSLType, GrGLSLShaderVar::kNonArray, kHig h_GrSLPrecision);
1338 f->emitFunction(kFloat_GrSLType, "square", 1, &x, "return dot(x, x);", & fSquareFun);
1339 }
1340
1341 EmitShapeCoords shapeCoords;
1342 shapeCoords.fVarying = &fShapeCoords;
1343 shapeCoords.fInverseMatrix = fShapeInverseMatrix.fsIn();
1344 shapeCoords.fFragHalfSpan = fFragShapeHalfSpan.fsIn();
1345
1346 EmitShapeCoords arcCoords;
1347 arcCoords.fVarying = &fArcCoords;
1348 arcCoords.fInverseMatrix = fArcInverseMatrix.fsIn();
1349 arcCoords.fFragHalfSpan = fFragArcHalfSpan.fsIn();
1350 bool clampArcCoords = this->isMixedSampled() && (fBatchInfo.fShapeTypes & kR Rect_ShapesMask);
1351
1352 EmitShapeOpts opts;
1353 opts.fIsTightGeometry = true;
1354 opts.fResolveMixedSamples = this->isMixedSampled();
1355 opts.fInvertCoverage = false;
1356
1357 if (fBatchInfo.fHasPerspective && fBatchInfo.fInnerShapeTypes) {
1358 // This determines if the fragment should consider the inner shape in it s sample mask.
1359 // We take the derivative early in case discards may occur before we get to the inner shape.
1360 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1361 f->codeAppendf("vec2 fragInnerShapeApproxHalfSpan = 0.5 * fwidth(%s);",
1362 fInnerShapeCoords.fsIn());
1363 }
1364
1365 if (!this->isMixedSampled()) {
1366 SkASSERT(!fArcTest.fsIn());
1367 if (fTriangleIsArc.fsIn()) {
1368 f->codeAppendf("if (%s != 0) {", fTriangleIsArc.fsIn());
1369 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1370
1371 f->codeAppend ("}");
1372 }
1373 } else {
1374 const char* arcTest = fArcTest.fsIn();
1375 if (fBatchInfo.fHasPerspective && arcTest) {
1376 // The non-perspective version accounts for fwith() in the vertex sh ader.
1377 // We make sure to take the derivative here, before a neighbor pixel may early accept.
1378 f->enableFeature(GrGLSLPPFragmentBuilder::kStandardDerivatives_GLSLF eature);
1379 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1380 f->codeAppendf("vec2 arcTest = %s - 0.5 * fwidth(%s);",
1381 fArcTest.fsIn(), fArcTest.fsIn());
1382 arcTest = "arcTest";
1383 }
1384 const char* earlyAccept = fEarlyAccept.fsIn() ? fEarlyAccept.fsIn() : "S AMPLE_MASK_ALL";
1385 f->codeAppendf("if (gl_SampleMaskIn[0] == %s) {", earlyAccept);
1386 f->overrideSampleCoverage(earlyAccept);
1387 f->codeAppend ("} else {");
1388 if (arcTest) {
1389 // At this point, if the sample mask is all set it means we are insi de an arc triangle.
1390 f->codeAppendf("if (gl_SampleMaskIn[0] == SAMPLE_MASK_ALL || "
1391 "all(greaterThan(%s, vec2(0)))) {", arcTest);
1392 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1393 f->codeAppend ("} else {");
1394 this->emitRect(f, shapeCoords, opts);
1395 f->codeAppend ("}");
1396 } else if (fTriangleIsArc.fsIn()) {
1397 f->codeAppendf("if (%s == 0) {", fTriangleIsArc.fsIn());
1398 this->emitRect(f, shapeCoords, opts);
1399 f->codeAppend ("} else {");
1400 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1401 f->codeAppend ("}");
1402 } else if (fBatchInfo.fShapeTypes == kOval_ShapeFlag) {
1403 this->emitArc(f, arcCoords, false, clampArcCoords, opts);
1404 } else {
1405 SkASSERT(fBatchInfo.fShapeTypes == kRect_ShapeFlag);
1406 this->emitRect(f, shapeCoords, opts);
1407 }
1408 f->codeAppend ("}");
1409 }
1410
1411 if (fBatchInfo.fInnerShapeTypes) {
1412 f->codeAppendf("// Inner shape.\n");
1413
1414 EmitShapeCoords innerShapeCoords;
1415 innerShapeCoords.fVarying = &fInnerShapeCoords;
1416 if (!fBatchInfo.fHasPerspective) {
1417 innerShapeCoords.fInverseMatrix = fInnerShapeInverseMatrix.fsIn();
1418 innerShapeCoords.fFragHalfSpan = fFragInnerShapeHalfSpan.fsIn();
1419 }
1420
1421 EmitShapeOpts innerOpts;
1422 innerOpts.fIsTightGeometry = false;
1423 innerOpts.fResolveMixedSamples = false; // Mixed samples are resolved in the outer shape.
1424 innerOpts.fInvertCoverage = true;
1425
1426 if (kOval_ShapeFlag == fBatchInfo.fInnerShapeTypes) {
1427 this->emitArc(f, innerShapeCoords, true, false, innerOpts);
1428 } else {
1429 f->codeAppendf("if (all(lessThan(abs(%s), 1.0 + %s))) {", fInnerShap eCoords.fsIn(),
1430 !fBatchInfo.fHasPerspective ? innerShapeCoords.fFragH alfSpan
1431 : "fragInnerShapeApproxHa lfSpan"); // Above.
1432 if (kRect_ShapeFlag == fBatchInfo.fInnerShapeTypes) {
1433 this->emitRect(f, innerShapeCoords, innerOpts);
1434 } else {
1435 this->emitSimpleRRect(f, innerShapeCoords, fInnerRRect.fsIn(), i nnerOpts);
1436 }
1437 f->codeAppend ("}");
1438 }
1439 }
1440 }
1441
1442 void GLSLInstanceProcessor::BackendMultisample::emitRect(GrGLSLPPFragmentBuilder * f,
1443 const EmitShapeCoords& coords,
1444 const EmitShapeOpts& op ts) {
1445 // Full MSAA doesn't need to do anything to draw a rect.
1446 SkASSERT(!opts.fIsTightGeometry || opts.fResolveMixedSamples);
1447 if (coords.fFragHalfSpan) {
1448 f->codeAppendf("if (all(lessThanEqual(abs(%s), 1.0 - %s))) {",
1449 coords.fVarying->fsIn(), coords.fFragHalfSpan);
1450 // The entire pixel is inside the rect.
1451 this->acceptOrRejectWholeFragment(f, true, opts);
1452 f->codeAppend ("} else ");
1453 if (opts.fIsTightGeometry && !fRectTrianglesMaySplit) {
1454 f->codeAppendf("if (any(lessThan(abs(%s), 1.0 - %s))) {",
1455 coords.fVarying->fsIn(), coords.fFragHalfSpan);
1456 // The pixel falls on an edge of the rectangle and is known to not b e on a shared edge.
1457 this->acceptCoverageMask(f, "gl_SampleMaskIn[0]", opts, false);
1458 f->codeAppend ("} else");
1459 }
1460 f->codeAppend ("{");
1461 }
1462 f->codeAppend ("int rectMask = 0;");
1463 f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
1464 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1465 f->codeAppend ( "vec2 pt = ");
1466 this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
1467 f->codeAppend ( ";");
1468 f->codeAppend ( "if (all(lessThan(abs(pt), vec2(1)))) rectMask |= (1 << i );");
1469 f->codeAppend ("}");
1470 this->acceptCoverageMask(f, "rectMask", opts);
1471 if (coords.fFragHalfSpan) {
1472 f->codeAppend ("}");
1473 }
1474 }
1475
1476 void GLSLInstanceProcessor::BackendMultisample::emitArc(GrGLSLPPFragmentBuilder* f,
1477 const EmitShapeCoords& c oords,
1478 bool coordsMayBeNegative , bool clampCoords,
1479 const EmitShapeOpts& opt s) {
1480 if (coords.fFragHalfSpan) {
1481 SkString absArcCoords;
1482 absArcCoords.printf(coordsMayBeNegative ? "abs(%s)" : "%s", coords.fVary ing->fsIn());
1483 if (clampCoords) {
1484 f->codeAppendf("if (%s(max(%s + %s, vec2(0))) < 1.0) {",
1485 fSquareFun.c_str(), absArcCoords.c_str(), coords.fFra gHalfSpan);
1486 } else {
1487 f->codeAppendf("if (%s(%s + %s) < 1.0) {",
1488 fSquareFun.c_str(), absArcCoords.c_str(), coords.fFra gHalfSpan);
1489 }
1490 // The entire pixel is inside the arc.
1491 this->acceptOrRejectWholeFragment(f, true, opts);
1492 f->codeAppendf("} else if (%s(max(%s - %s, vec2(0))) >= 1.0) {",
1493 fSquareFun.c_str(), absArcCoords.c_str(), coords.fFragHal fSpan);
1494 // The entire pixel is outside the arc.
1495 this->acceptOrRejectWholeFragment(f, false, opts);
1496 f->codeAppend ("} else {");
1497 }
1498 f->codeAppend ( "int arcMask = 0;");
1499 f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {");
1500 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1501 f->codeAppend ( "vec2 pt = ");
1502 this->interpolateAtSample(f, *coords.fVarying, "i", coords.fInverseMatrix);
1503 f->codeAppend ( ";");
1504 if (clampCoords) {
1505 SkASSERT(!coordsMayBeNegative);
1506 f->codeAppend ( "pt = max(pt, vec2(0));");
1507 }
1508 f->codeAppendf( "if (%s(pt) < 1.0) arcMask |= (1 << i);", fSquareFun. c_str());
1509 f->codeAppend ( "}");
1510 this->acceptCoverageMask(f, "arcMask", opts);
1511 if (coords.fFragHalfSpan) {
1512 f->codeAppend ("}");
1513 }
1514 }
1515
1516 void GLSLInstanceProcessor::BackendMultisample::emitSimpleRRect(GrGLSLPPFragment Builder* f,
1517 const EmitShapeC oords& coords,
1518 const char* rrec t,
1519 const EmitShapeO pts& opts) {
1520 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1521 f->codeAppendf("vec2 distanceToArcEdge = abs(%s) - %s.xy;", coords.fVarying- >fsIn(), rrect);
1522 f->codeAppend ("if (any(lessThan(distanceToArcEdge, vec2(0)))) {");
1523 this->emitRect(f, coords, opts);
1524 f->codeAppend ("} else {");
1525 if (coords.fInverseMatrix && coords.fFragHalfSpan) {
1526 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1527 f->codeAppendf("vec2 rrectCoords = distanceToArcEdge * %s.zw;", rrect);
1528 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1529 f->codeAppendf("vec2 fragRRectHalfSpan = %s * %s.zw;", coords.fFragHalfS pan, rrect);
1530 f->codeAppendf("if (%s(rrectCoords + fragRRectHalfSpan) <= 1.0) {", fSqu areFun.c_str());
1531 // The entire pixel is inside the round rect.
1532 this->acceptOrRejectWholeFragment(f, true, opts);
1533 f->codeAppendf("} else if (%s(max(rrectCoords - fragRRectHalfSpan, vec2( 0))) >= 1.0) {",
1534 fSquareFun.c_str());
1535 // The entire pixel is outside the round rect.
1536 this->acceptOrRejectWholeFragment(f, false, opts);
1537 f->codeAppend ("} else {");
1538 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1539 f->codeAppendf( "vec2 s = %s.zw * sign(%s);", rrect, coords.fVarying- >fsIn());
1540 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1541 f->codeAppendf( "mat2 innerRRectInverseMatrix = %s * mat2(s.x, 0, 0, s.y);",
1542 coords.fInverseMatrix);
1543 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1544 f->codeAppend ( "int rrectMask = 0;");
1545 f->codeAppend ( "for (int i = 0; i < SAMPLE_COUNT; i++) {");
1546 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1547 f->codeAppend ( "vec2 pt = rrectCoords + ");
1548 f->appendOffsetToSample("i", GrGLSLFPFragmentBuilder::kSkiaDevice_Coordi nates);
1549 f->codeAppend ( "* innerRRectInverseMatrix;");
1550 f->codeAppendf( "if (%s(max(pt, vec2(0))) < 1.0) rrectMask |= (1 << i);",
1551 fSquareFun.c_str());
1552 f->codeAppend ( "}");
1553 this->acceptCoverageMask(f, "rrectMask", opts);
1554 f->codeAppend ("}");
1555 } else {
1556 f->codeAppend ("int rrectMask = 0;");
1557 f->codeAppend ("for (int i = 0; i < SAMPLE_COUNT; i++) {");
1558 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1559 f->codeAppend ( "vec2 shapePt = ");
1560 this->interpolateAtSample(f, *coords.fVarying, "i", nullptr);
1561 f->codeAppend ( ";");
1562 f->appendPrecisionModifier(kHigh_GrSLPrecision);
1563 f->codeAppendf( "vec2 rrectPt = max(abs(shapePt) - %s.xy, vec2(0)) * %s.zw;",
1564 rrect, rrect);
1565 f->codeAppendf( "if (%s(rrectPt) < 1.0) rrectMask |= (1 << i);", fSqu areFun.c_str());
1566 f->codeAppend ("}");
1567 this->acceptCoverageMask(f, "rrectMask", opts);
1568 }
1569 f->codeAppend ("}");
1570 }
1571
1572 void GLSLInstanceProcessor::BackendMultisample::interpolateAtSample(GrGLSLPPFrag mentBuilder* f,
1573 const GrGLSLVa rying& varying,
1574 const char* sa mpleIdx,
1575 const char* in terpolationMatrix) {
1576 if (interpolationMatrix) {
1577 f->codeAppendf("(%s + ", varying.fsIn());
1578 f->appendOffsetToSample(sampleIdx, GrGLSLFPFragmentBuilder::kSkiaDevice_ Coordinates);
1579 f->codeAppendf(" * %s)", interpolationMatrix);
1580 } else {
1581 SkAssertResult(
1582 f->enableFeature(GrGLSLFragmentBuilder::kMultisampleInterpolation_GL SLFeature));
1583 f->codeAppendf("interpolateAtOffset(%s, ", varying.fsIn());
1584 f->appendOffsetToSample(sampleIdx, GrGLSLFPFragmentBuilder::kGLSLWindow_ Coordinates);
1585 f->codeAppend(")");
1586 }
1587 }
1588
1589 void
1590 GLSLInstanceProcessor::BackendMultisample::acceptOrRejectWholeFragment(GrGLSLPPF ragmentBuilder* f,
1591 bool insi de,
1592 const Emi tShapeOpts& opts) {
1593 if (inside != opts.fInvertCoverage) { // Accept the entire fragment.
1594 if (opts.fResolveMixedSamples) {
1595 // This is a mixed sampled fragment in the interior of the shape. Re assign 100% coverage
1596 // to one fragment, and drop all other fragments that may fall on th is same pixel. Since
1597 // our geometry is water tight and non-overlapping, we can take adva ntage of the
1598 // properties that (1) the incoming sample masks will be disjoint ac ross fragments that
1599 // fall on a common pixel, and (2) since the entire fragment is insi de the shape, each
1600 // sample's corresponding bit will be set in the incoming sample mas k of exactly one
1601 // fragment.
1602 f->codeAppend("if ((gl_SampleMaskIn[0] & SAMPLE_MASK_MSB) == 0) {");
1603 // Drop this fragment.
1604 if (!fBatchInfo.fCannotDiscard) {
1605 f->codeAppend("discard;");
1606 } else {
1607 f->overrideSampleCoverage("0");
1608 }
1609 f->codeAppend("} else {");
1610 // Override the lone surviving fragment to full coverage.
1611 f->overrideSampleCoverage("-1");
1612 f->codeAppend("}");
1613 }
1614 } else { // Reject the entire fragment.
1615 if (!fBatchInfo.fCannotDiscard) {
1616 f->codeAppend("discard;");
1617 } else if (opts.fResolveMixedSamples) {
1618 f->overrideSampleCoverage("0");
1619 } else {
1620 f->maskSampleCoverage("0");
1621 }
1622 }
1623 }
1624
1625 void GLSLInstanceProcessor::BackendMultisample::acceptCoverageMask(GrGLSLPPFragm entBuilder* f,
1626 const char* s hapeMask,
1627 const EmitSha peOpts& opts,
1628 bool maybeSha redEdge) {
1629 if (opts.fResolveMixedSamples) {
1630 if (maybeSharedEdge) {
1631 // This is a mixed sampled fragment, potentially on the outer edge o f the shape, with
1632 // only partial shape coverage. Override the coverage of one fragmen t to "shapeMask",
1633 // and drop all other fragments that may fall on this same pixel. Si nce our geometry is
1634 // water tight, non-overlapping, and completely contains the shape, this means that each
1635 // "on" bit from shapeMask is guaranteed to be set in the incoming s ample mask of one,
1636 // and only one, fragment that falls on this same pixel.
1637 SkASSERT(!opts.fInvertCoverage);
1638 f->codeAppendf("if ((gl_SampleMaskIn[0] & (1 << findMSB(%s))) == 0) {", shapeMask);
1639 // Drop this fragment.
1640 if (!fBatchInfo.fCannotDiscard) {
1641 f->codeAppend ("discard;");
1642 } else {
1643 f->overrideSampleCoverage("0");
1644 }
1645 f->codeAppend ("} else {");
1646 // Override the coverage of the lone surviving fragment to "shapeMas k".
1647 f->overrideSampleCoverage(shapeMask);
1648 f->codeAppend ("}");
1649 } else {
1650 f->overrideSampleCoverage(shapeMask);
1651 }
1652 } else {
1653 f->maskSampleCoverage(shapeMask, opts.fInvertCoverage);
1654 }
1655 }
1656
1657 //////////////////////////////////////////////////////////////////////////////// ////////////////////
1658
1659 GLSLInstanceProcessor::Backend*
1660 GLSLInstanceProcessor::Backend::Create(const GrGLSLProgramBuilder* p, BatchInfo batchInfo,
1661 const VertexInputs& inputs) {
1662 switch (batchInfo.fAntialiasMode) {
1663 default:
1664 SkFAIL("Unexpected antialias mode.");
1665 case AntialiasMode::kNone:
1666 return new BackendNonAA(batchInfo, inputs);
1667 case AntialiasMode::kCoverage:
1668 return new BackendCoverage(batchInfo, inputs);
1669 case AntialiasMode::kMSAA:
1670 case AntialiasMode::kMixedSamples: {
1671 const GrPipeline& pipeline = p->pipeline();
1672 const GrRenderTargetPriv& rtp = pipeline.getRenderTarget()->renderTa rgetPriv();
1673 const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipel ine.getStencil());
1674 return new BackendMultisample(batchInfo, inputs, specs.fEffectiveSam pleCnt);
1675 }
1676 }
1677 }
1678
1679 //////////////////////////////////////////////////////////////////////////////// ////////////////////
1680
1681 const ShapeVertex kVertexData[] = {
1682 // Rectangle.
1683 {+1, +1, ~0}, /*0*/
1684 {-1, +1, ~0}, /*1*/
1685 {-1, -1, ~0}, /*2*/
1686 {+1, -1, ~0}, /*3*/
1687 // The next 4 are for the bordered version.
1688 {+1, +1, 0}, /*4*/
1689 {-1, +1, 0}, /*5*/
1690 {-1, -1, 0}, /*6*/
1691 {+1, -1, 0}, /*7*/
1692
1693 // Octagon that inscribes the unit circle, cut by an interior unit octagon.
1694 {+1.000000f, 0.000000f, 0}, /* 8*/
1695 {+1.000000f, +0.414214f, ~0}, /* 9*/
1696 {+0.707106f, +0.707106f, 0}, /*10*/
1697 {+0.414214f, +1.000000f, ~0}, /*11*/
1698 { 0.000000f, +1.000000f, 0}, /*12*/
1699 {-0.414214f, +1.000000f, ~0}, /*13*/
1700 {-0.707106f, +0.707106f, 0}, /*14*/
1701 {-1.000000f, +0.414214f, ~0}, /*15*/
1702 {-1.000000f, 0.000000f, 0}, /*16*/
1703 {-1.000000f, -0.414214f, ~0}, /*17*/
1704 {-0.707106f, -0.707106f, 0}, /*18*/
1705 {-0.414214f, -1.000000f, ~0}, /*19*/
1706 { 0.000000f, -1.000000f, 0}, /*20*/
1707 {+0.414214f, -1.000000f, ~0}, /*21*/
1708 {+0.707106f, -0.707106f, 0}, /*22*/
1709 {+1.000000f, -0.414214f, ~0}, /*23*/
1710 // This vertex is for the fanned versions.
1711 { 0.000000f, 0.000000f, ~0}, /*24*/
1712
1713 // Rectangle with disjoint corner segments.
1714 {+1.0, +0.5, 0x3}, /*25*/
1715 {+1.0, +1.0, 0x3}, /*26*/
1716 {+0.5, +1.0, 0x3}, /*27*/
1717 {-0.5, +1.0, 0x2}, /*28*/
1718 {-1.0, +1.0, 0x2}, /*29*/
1719 {-1.0, +0.5, 0x2}, /*30*/
1720 {-1.0, -0.5, 0x0}, /*31*/
1721 {-1.0, -1.0, 0x0}, /*32*/
1722 {-0.5, -1.0, 0x0}, /*33*/
1723 {+0.5, -1.0, 0x1}, /*34*/
1724 {+1.0, -1.0, 0x1}, /*35*/
1725 {+1.0, -0.5, 0x1}, /*36*/
1726 // The next 4 are for the fanned version.
1727 { 0.0, 0.0, 0x3}, /*37*/
1728 { 0.0, 0.0, 0x2}, /*38*/
1729 { 0.0, 0.0, 0x0}, /*39*/
1730 { 0.0, 0.0, 0x1}, /*40*/
1731 // The next 8 are for the bordered version.
1732 {+0.75, +0.50, 0x3}, /*41*/
1733 {+0.50, +0.75, 0x3}, /*42*/
1734 {-0.50, +0.75, 0x2}, /*43*/
1735 {-0.75, +0.50, 0x2}, /*44*/
1736 {-0.75, -0.50, 0x0}, /*45*/
1737 {-0.50, -0.75, 0x0}, /*46*/
1738 {+0.50, -0.75, 0x1}, /*47*/
1739 {+0.75, -0.50, 0x1}, /*48*/
1740
1741 // 16-gon that inscribes the unit circle, cut by an interior unit 16-gon.
1742 {+1.000000f, +0.000000f, 0}, /*49*/
1743 {+1.000000f, +0.198913f, ~0}, /*50*/
1744 {+0.923879f, +0.382683f, 0}, /*51*/
1745 {+0.847760f, +0.566455f, ~0}, /*52*/
1746 {+0.707106f, +0.707106f, 0}, /*53*/
1747 {+0.566455f, +0.847760f, ~0}, /*54*/
1748 {+0.382683f, +0.923879f, 0}, /*55*/
1749 {+0.198913f, +1.000000f, ~0}, /*56*/
1750 {+0.000000f, +1.000000f, 0}, /*57*/
1751 {-0.198913f, +1.000000f, ~0}, /*58*/
1752 {-0.382683f, +0.923879f, 0}, /*59*/
1753 {-0.566455f, +0.847760f, ~0}, /*60*/
1754 {-0.707106f, +0.707106f, 0}, /*61*/
1755 {-0.847760f, +0.566455f, ~0}, /*62*/
1756 {-0.923879f, +0.382683f, 0}, /*63*/
1757 {-1.000000f, +0.198913f, ~0}, /*64*/
1758 {-1.000000f, +0.000000f, 0}, /*65*/
1759 {-1.000000f, -0.198913f, ~0}, /*66*/
1760 {-0.923879f, -0.382683f, 0}, /*67*/
1761 {-0.847760f, -0.566455f, ~0}, /*68*/
1762 {-0.707106f, -0.707106f, 0}, /*69*/
1763 {-0.566455f, -0.847760f, ~0}, /*70*/
1764 {-0.382683f, -0.923879f, 0}, /*71*/
1765 {-0.198913f, -1.000000f, ~0}, /*72*/
1766 {-0.000000f, -1.000000f, 0}, /*73*/
1767 {+0.198913f, -1.000000f, ~0}, /*74*/
1768 {+0.382683f, -0.923879f, 0}, /*75*/
1769 {+0.566455f, -0.847760f, ~0}, /*76*/
1770 {+0.707106f, -0.707106f, 0}, /*77*/
1771 {+0.847760f, -0.566455f, ~0}, /*78*/
1772 {+0.923879f, -0.382683f, 0}, /*79*/
1773 {+1.000000f, -0.198913f, ~0}, /*80*/
1774 };
1775
1776 const uint8_t kIndexData[] = {
1777 // Rectangle.
1778 0, 1, 2,
1779 0, 2, 3,
1780
1781 // Rectangle with a border.
1782 0, 1, 5,
1783 5, 4, 0,
1784 1, 2, 6,
1785 6, 5, 1,
1786 2, 3, 7,
1787 7, 6, 2,
1788 3, 0, 4,
1789 4, 7, 3,
1790 4, 5, 6,
1791 6, 7, 4,
1792
1793 // Octagon that inscribes the unit circle, cut by an interior unit octagon.
1794 10, 8, 9,
1795 12, 10, 11,
1796 14, 12, 13,
1797 16, 14, 15,
1798 18, 16, 17,
1799 20, 18, 19,
1800 22, 20, 21,
1801 8, 22, 23,
1802 8, 10, 12,
1803 12, 14, 16,
1804 16, 18, 20,
1805 20, 22, 8,
1806 8, 12, 16,
1807 16, 20, 8,
1808
1809 // Same octagons, but with the interior arranged as a fan. Used by mixed sam ples.
1810 10, 8, 9,
1811 12, 10, 11,
1812 14, 12, 13,
1813 16, 14, 15,
1814 18, 16, 17,
1815 20, 18, 19,
1816 22, 20, 21,
1817 8, 22, 23,
1818 24, 8, 10,
1819 12, 24, 10,
1820 24, 12, 14,
1821 16, 24, 14,
1822 24, 16, 18,
1823 20, 24, 18,
1824 24, 20, 22,
1825 8, 24, 22,
1826
1827 // Same octagons, but with the inner and outer disjoint. Used by coverage AA .
1828 8, 22, 23,
1829 9, 8, 23,
1830 10, 8, 9,
1831 11, 10, 9,
1832 12, 10, 11,
1833 13, 12, 11,
1834 14, 12, 13,
1835 15, 14, 13,
1836 16, 14, 15,
1837 17, 16, 15,
1838 18, 16, 17,
1839 19, 18, 17,
1840 20, 18, 19,
1841 21, 20, 19,
1842 22, 20, 21,
1843 23, 22, 21,
1844 22, 8, 10,
1845 10, 12, 14,
1846 14, 16, 18,
1847 18, 20, 22,
1848 22, 10, 14,
1849 14, 18, 22,
1850
1851 // Rectangle with disjoint corner segments.
1852 27, 25, 26,
1853 30, 28, 29,
1854 33, 31, 32,
1855 36, 34, 35,
1856 25, 27, 28,
1857 28, 30, 31,
1858 31, 33, 34,
1859 34, 36, 25,
1860 25, 28, 31,
1861 31, 34, 25,
1862
1863 // Same rectangle with disjoint corners, but with the interior arranged as a fan. Used by
1864 // mixed samples.
1865 27, 25, 26,
1866 30, 28, 29,
1867 33, 31, 32,
1868 36, 34, 35,
1869 27, 37, 25,
1870 28, 37, 27,
1871 30, 38, 28,
1872 31, 38, 30,
1873 33, 39, 31,
1874 34, 39, 33,
1875 36, 40, 34,
1876 25, 40, 36,
1877
1878 // Same rectangle with disjoint corners, with a border as well. Used by cove rage AA.
1879 41, 25, 26,
1880 42, 41, 26,
1881 27, 42, 26,
1882 43, 28, 29,
1883 44, 43, 29,
1884 30, 44, 29,
1885 45, 31, 32,
1886 46, 45, 32,
1887 33, 46, 32,
1888 47, 34, 35,
1889 48, 47, 35,
1890 36, 48, 35,
1891 27, 28, 42,
1892 42, 28, 43,
1893 30, 31, 44,
1894 44, 31, 45,
1895 33, 34, 46,
1896 46, 34, 47,
1897 36, 25, 48,
1898 48, 25, 41,
1899 41, 42, 43,
1900 43, 44, 45,
1901 45, 46, 47,
1902 47, 48, 41,
1903 41, 43, 45,
1904 45, 47, 41,
1905
1906 // Same as the disjoint octagons, but with 16-gons instead. Used by coverage AA when the oval is
1907 // sufficiently large.
1908 49, 79, 80,
1909 50, 49, 80,
1910 51, 49, 50,
1911 52, 51, 50,
1912 53, 51, 52,
1913 54, 53, 52,
1914 55, 53, 54,
1915 56, 55, 54,
1916 57, 55, 56,
1917 58, 57, 56,
1918 59, 57, 58,
1919 60, 59, 58,
1920 61, 59, 60,
1921 62, 61, 60,
1922 63, 61, 62,
1923 64, 63, 62,
1924 65, 63, 64,
1925 66, 65, 64,
1926 67, 65, 66,
1927 68, 67, 66,
1928 69, 67, 68,
1929 70, 69, 68,
1930 71, 69, 70,
1931 72, 71, 70,
1932 73, 71, 72,
1933 74, 73, 72,
1934 75, 73, 74,
1935 76, 75, 74,
1936 77, 75, 76,
1937 78, 77, 76,
1938 79, 77, 78,
1939 80, 79, 78,
1940 49, 51, 53,
1941 53, 55, 57,
1942 57, 59, 61,
1943 61, 63, 65,
1944 65, 67, 69,
1945 69, 71, 73,
1946 73, 75, 77,
1947 77, 79, 49,
1948 49, 53, 57,
1949 57, 61, 65,
1950 65, 69, 73,
1951 73, 77, 49,
1952 49, 57, 65,
1953 65, 73, 49,
1954 };
1955
1956 enum {
1957 kRect_FirstIndex = 0,
1958 kRect_TriCount = 2,
1959
1960 kFramedRect_FirstIndex = 6,
1961 kFramedRect_TriCount = 10,
1962
1963 kOctagons_FirstIndex = 36,
1964 kOctagons_TriCount = 14,
1965
1966 kOctagonsFanned_FirstIndex = 78,
1967 kOctagonsFanned_TriCount = 16,
1968
1969 kDisjointOctagons_FirstIndex = 126,
1970 kDisjointOctagons_TriCount = 22,
1971
1972 kCorneredRect_FirstIndex = 192,
1973 kCorneredRect_TriCount = 10,
1974
1975 kCorneredRectFanned_FirstIndex = 222,
1976 kCorneredRectFanned_TriCount = 12,
1977
1978 kCorneredFramedRect_FirstIndex = 258,
1979 kCorneredFramedRect_TriCount = 26,
1980
1981 kDisjoint16Gons_FirstIndex = 336,
1982 kDisjoint16Gons_TriCount = 46,
1983 };
1984
1985 static const GrUniqueKey::Domain kShapeBufferDomain = GrUniqueKey::GenerateDomai n();
1986
1987 template<GrBufferType Type> static const GrUniqueKey& get_shape_buffer_key() {
1988 static GrUniqueKey* kKey;
1989 if (!kKey) {
1990 kKey = new GrUniqueKey;
1991 GrUniqueKey::Builder builder(kKey, kShapeBufferDomain, 1);
1992 builder[0] = Type;
1993 }
1994 return *kKey;
1995 }
1996
1997 const GrBuffer* InstanceProcessor::FindOrCreateVertexBuffer(GrGpu* gpu) {
1998 GrResourceCache* cache = gpu->getContext()->getResourceCache();
1999 const GrUniqueKey& key = get_shape_buffer_key<kVertex_GrBufferType>();
2000 if (GrGpuResource* cached = cache->findAndRefUniqueResource(key)) {
2001 return static_cast<GrBuffer*>(cached);
2002 }
2003 if (GrBuffer* buffer = gpu->createBuffer(sizeof(kVertexData), kVertex_GrBuff erType,
2004 kStatic_GrAccessPattern, kVertexDat a)) {
2005 buffer->resourcePriv().setUniqueKey(key);
2006 return buffer;
2007 }
2008 return nullptr;
2009 }
2010
2011 const GrBuffer* InstanceProcessor::FindOrCreateIndex8Buffer(GrGpu* gpu) {
2012 GrResourceCache* cache = gpu->getContext()->getResourceCache();
2013 const GrUniqueKey& key = get_shape_buffer_key<kIndex_GrBufferType>();
2014 if (GrGpuResource* cached = cache->findAndRefUniqueResource(key)) {
2015 return static_cast<GrBuffer*>(cached);
2016 }
2017 if (GrBuffer* buffer = gpu->createBuffer(sizeof(kIndexData), kIndex_GrBuffer Type,
2018 kStatic_GrAccessPattern, kIndexData )) {
2019 buffer->resourcePriv().setUniqueKey(key);
2020 return buffer;
2021 }
2022 return nullptr;
2023 }
2024
2025 IndexRange InstanceProcessor::GetIndexRangeForRect(AntialiasMode aa) {
2026 static constexpr IndexRange kRectRanges[kNumAntialiasModes] = {
2027 {kRect_FirstIndex, 3 * kRect_TriCount}, // kNone
2028 {kFramedRect_FirstIndex, 3 * kFramedRect_TriCount}, // kCoverage
2029 {kRect_FirstIndex, 3 * kRect_TriCount}, // kMSAA
2030 {kRect_FirstIndex, 3 * kRect_TriCount} // kMixedSamples
2031 };
2032
2033 SkASSERT(aa >= AntialiasMode::kNone && aa <= AntialiasMode::kMixedSamples);
2034 return kRectRanges[(int)aa];
2035
2036 GR_STATIC_ASSERT(0 == (int)AntialiasMode::kNone);
2037 GR_STATIC_ASSERT(1 == (int)AntialiasMode::kCoverage);
2038 GR_STATIC_ASSERT(2 == (int)AntialiasMode::kMSAA);
2039 GR_STATIC_ASSERT(3 == (int)AntialiasMode::kMixedSamples);
2040 }
2041
2042 IndexRange InstanceProcessor::GetIndexRangeForOval(AntialiasMode aa, const SkRec t& devBounds) {
2043 if (AntialiasMode::kCoverage == aa && devBounds.height() * devBounds.width() >= 256 * 256) {
2044 // This threshold was chosen quasi-scientifically on Tegra X1.
2045 return {kDisjoint16Gons_FirstIndex, 3 * kDisjoint16Gons_TriCount};
2046 }
2047
2048 static constexpr IndexRange kOvalRanges[kNumAntialiasModes] = {
2049 {kOctagons_FirstIndex, 3 * kOctagons_TriCount}, // kNo ne
2050 {kDisjointOctagons_FirstIndex, 3 * kDisjointOctagons_TriCount}, // kCo verage
2051 {kOctagons_FirstIndex, 3 * kOctagons_TriCount}, // kMS AA
2052 {kOctagonsFanned_FirstIndex, 3 * kOctagonsFanned_TriCount} // kMi xedSamples
2053 };
2054
2055 SkASSERT(aa >= AntialiasMode::kNone && aa <= AntialiasMode::kMixedSamples);
2056 return kOvalRanges[(int)aa];
2057
2058 GR_STATIC_ASSERT(0 == (int)AntialiasMode::kNone);
2059 GR_STATIC_ASSERT(1 == (int)AntialiasMode::kCoverage);
2060 GR_STATIC_ASSERT(2 == (int)AntialiasMode::kMSAA);
2061 GR_STATIC_ASSERT(3 == (int)AntialiasMode::kMixedSamples);
2062 }
2063
2064 IndexRange InstanceProcessor::GetIndexRangeForRRect(AntialiasMode aa) {
2065 static constexpr IndexRange kRRectRanges[kNumAntialiasModes] = {
2066 {kCorneredRect_FirstIndex, 3 * kCorneredRect_TriCount}, // kNone
2067 {kCorneredFramedRect_FirstIndex, 3 * kCorneredFramedRect_TriCount}, // kCoverage
2068 {kCorneredRect_FirstIndex, 3 * kCorneredRect_TriCount}, // kMSAA
2069 {kCorneredRectFanned_FirstIndex, 3 * kCorneredRectFanned_TriCount} // kMixedSamples
2070 };
2071
2072 SkASSERT(aa >= AntialiasMode::kNone && aa <= AntialiasMode::kMixedSamples);
2073 return kRRectRanges[(int)aa];
2074
2075 GR_STATIC_ASSERT(0 == (int)AntialiasMode::kNone);
2076 GR_STATIC_ASSERT(1 == (int)AntialiasMode::kCoverage);
2077 GR_STATIC_ASSERT(2 == (int)AntialiasMode::kMSAA);
2078 GR_STATIC_ASSERT(3 == (int)AntialiasMode::kMixedSamples);
2079 }
2080
2081 const char* InstanceProcessor::GetNameOfIndexRange(IndexRange range) {
2082 switch (range.fStart) {
2083 case kRect_FirstIndex: return "basic_rect";
2084 case kFramedRect_FirstIndex: return "coverage_rect";
2085
2086 case kOctagons_FirstIndex: return "basic_oval";
2087 case kDisjointOctagons_FirstIndex: return "coverage_oval";
2088 case kOctagonsFanned_FirstIndex: return "mixed_samples_oval";
2089
2090 case kCorneredRect_FirstIndex: return "basic_round_rect";
2091 case kCorneredFramedRect_FirstIndex: return "coverage_round_rect";
2092 case kCorneredRectFanned_FirstIndex: return "mixed_samples_round_rect";
2093
2094 default: return "unknown";
2095 }
2096 }
2097
2098 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698