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