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