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

Side by Side Diff: src/gpu/effects/GrInstanceProcessor.cpp

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

Powered by Google App Engine
This is Rietveld 408576698