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

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

Powered by Google App Engine
This is Rietveld 408576698