1 /* 2 * Copyright 2011 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 "GrGpuGL.h" 9 10 #include "GrEffect.h" 11 #include "GrGLEffect.h" 12 #include "GrGpuVertex.h" 13 14 typedef GrGLUniformManager::UniformHandle UniformHandle; 15 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle; 16 17 #define SKIP_CACHE_CHECK true 18 #define GR_UINT32_MAX static_cast<uint32_t>(-1) 19 20 GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl) 21 : fCount(0) 22 , fCurrLRUStamp(0) 23 , fGL(gl) { 24 } 25 26 void GrGpuGL::ProgramCache::abandon() { 27 for (int i = 0; i < fCount; ++i) { 28 GrAssert(NULL != fEntries[i].fProgram.get()); 29 fEntries[i].fProgram->abandon(); 30 fEntries[i].fProgram.reset(NULL); 31 } 32 fCount = 0; 33 } 34 35 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, 36 const GrEffectStage* stages[]) { 37 Entry newEntry; 38 newEntry.fKey.setKeyData(desc.asKey()); 39 40 Entry* entry = fHashCache.find(newEntry.fKey); 41 if (NULL == entry) { 42 newEntry.fProgram.reset(GrGLProgram::Create(fGL, desc, stages)); 43 if (NULL == newEntry.fProgram.get()) { 44 return NULL; 45 } 46 if (fCount < kMaxEntries) { 47 entry = fEntries + fCount; 48 ++fCount; 49 } else { 50 GrAssert(kMaxEntries == fCount); 51 entry = fEntries; 52 for (int i = 1; i < kMaxEntries; ++i) { 53 if (fEntries[i].fLRUStamp < entry->fLRUStamp) { 54 entry = fEntries + i; 55 } 56 } 57 fHashCache.remove(entry->fKey, entry); 58 } 59 *entry = newEntry; 60 fHashCache.insert(entry->fKey, entry); 61 } 62 63 entry->fLRUStamp = fCurrLRUStamp; 64 if (GR_UINT32_MAX == fCurrLRUStamp) { 65 // wrap around! just trash our LRU, one time hit. 66 for (int i = 0; i < fCount; ++i) { 67 fEntries[i].fLRUStamp = 0; 68 } 69 } 70 ++fCurrLRUStamp; 71 return entry->fProgram; 72 } 73 74 //////////////////////////////////////////////////////////////////////////////// 75 76 void GrGpuGL::abandonResources(){ 77 INHERITED::abandonResources(); 78 fProgramCache->abandon(); 79 fHWProgramID = 0; 80 } 81 82 //////////////////////////////////////////////////////////////////////////////// 83 84 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) 85 86 void GrGpuGL::flushViewMatrix(DrawType type) { 87 const GrGLRenderTarget* rt = static_cast<const GrGLRenderTarget*>(this->getDrawState().getRenderTarget()); 88 SkISize viewportSize; 89 const GrGLIRect& viewport = rt->getViewport(); 90 viewportSize.set(viewport.fWidth, viewport.fHeight); 91 92 const SkMatrix& vm = this->getDrawState().getViewMatrix(); 93 94 if (kStencilPath_DrawType == type) { 95 if (fHWPathMatrixState.fViewMatrix != vm || 96 fHWPathMatrixState.fRTSize != viewportSize) { 97 // rescale the coords from skia's "device" coords to GL's normalized coords, 98 // and perform a y-flip. 99 SkMatrix m; 100 m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height()); 101 m.postTranslate(-SK_Scalar1, SK_Scalar1); 102 m.preConcat(vm); 103 104 // GL wants a column-major 4x4. 105 GrGLfloat mv[] = { 106 // col 0 107 SkScalarToFloat(m[SkMatrix::kMScaleX]), 108 SkScalarToFloat(m[SkMatrix::kMSkewY]), 109 0, 110 SkScalarToFloat(m[SkMatrix::kMPersp0]), 111 112 // col 1 113 SkScalarToFloat(m[SkMatrix::kMSkewX]), 114 SkScalarToFloat(m[SkMatrix::kMScaleY]), 115 0, 116 SkScalarToFloat(m[SkMatrix::kMPersp1]), 117 118 // col 2 119 0, 0, 0, 0, 120 121 // col3 122 SkScalarToFloat(m[SkMatrix::kMTransX]), 123 SkScalarToFloat(m[SkMatrix::kMTransY]), 124 0.0f, 125 SkScalarToFloat(m[SkMatrix::kMPersp2]) 126 }; 127 GL_CALL(MatrixMode(GR_GL_PROJECTION)); 128 GL_CALL(LoadMatrixf(mv)); 129 fHWPathMatrixState.fViewMatrix = vm; 130 fHWPathMatrixState.fRTSize = viewportSize; 131 } 132 } else if (!fCurrentProgram->fViewMatrix.cheapEqualTo(vm) || 133 fCurrentProgram->fViewportSize != viewportSize) { 134 SkMatrix m; 135 m.setAll( 136 SkIntToScalar(2) / viewportSize.fWidth, 0, -SK_Scalar1, 137 0,-SkIntToScalar(2) / viewportSize.fHeight, SK_Scalar1, 138 0, 0, SkMatrix::I()[8]); 139 m.setConcat(m, vm); 140 141 // ES doesn't allow you to pass true to the transpose param, 142 // so do our own transpose 143 GrGLfloat mt[] = { 144 SkScalarToFloat(m[SkMatrix::kMScaleX]), 145 SkScalarToFloat(m[SkMatrix::kMSkewY]), 146 SkScalarToFloat(m[SkMatrix::kMPersp0]), 147 SkScalarToFloat(m[SkMatrix::kMSkewX]), 148 SkScalarToFloat(m[SkMatrix::kMScaleY]), 149 SkScalarToFloat(m[SkMatrix::kMPersp1]), 150 SkScalarToFloat(m[SkMatrix::kMTransX]), 151 SkScalarToFloat(m[SkMatrix::kMTransY]), 152 SkScalarToFloat(m[SkMatrix::kMPersp2]) 153 }; 154 fCurrentProgram->fUniformManager.setMatrix3f( 155 fCurrentProgram->fUniformHandles.fViewMatrixUni, 156 mt); 157 fCurrentProgram->fViewMatrix = vm; 158 fCurrentProgram->fViewportSize = viewportSize; 159 } 160 } 161 162 /////////////////////////////////////////////////////////////////////////////// 163 164 void GrGpuGL::flushColor(GrColor color) { 165 const ProgramDesc& desc = fCurrentProgram->getDesc(); 166 const GrDrawState& drawState = this->getDrawState(); 167 168 if (this->getVertexLayout() & GrDrawState::kColor_VertexLayoutBit) { 169 // color will be specified per-vertex as an attribute 170 // invalidate the const vertex attrib color 171 fHWConstAttribColor = GrColor_ILLEGAL; 172 } else { 173 switch (desc.fColorInput) { 174 case ProgramDesc::kAttribute_ColorInput: 175 if (fHWConstAttribColor != color) { 176 // OpenGL ES only supports the float varieties of glVertexAttrib 177 GrGLfloat c[4]; 178 GrColorToRGBAFloat(color, c); 179 GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c)); 180 fHWConstAttribColor = color; 181 } 182 break; 183 case ProgramDesc::kUniform_ColorInput: 184 if (fCurrentProgram->fColor != color) { 185 // OpenGL ES doesn't support unsigned byte varieties of glUniform 186 GrGLfloat c[4]; 187 GrColorToRGBAFloat(color, c); 188 GrAssert(kInvalidUniformHandle != fCurrentProgram->fUniformHandles.fColorUni); 189 fCurrentProgram->fUniformManager.set4fv( 190 fCurrentProgram->fUniformHandles.fColorUni, 191 0, 1, c); 192 fCurrentProgram->fColor = color; 193 } 194 break; 195 case ProgramDesc::kSolidWhite_ColorInput: 196 case ProgramDesc::kTransBlack_ColorInput: 197 break; 198 default: 199 GrCrash("Unknown color type."); 200 } 201 } 202 UniformHandle filterColorUni = fCurrentProgram->fUniformHandles.fColorFilterUni; 203 if (kInvalidUniformHandle != filterColorUni && 204 fCurrentProgram->fColorFilterColor != drawState.getColorFilterColor()) { 205 GrGLfloat c[4]; 206 GrColorToRGBAFloat(drawState.getColorFilterColor(), c); 207 fCurrentProgram->fUniformManager.set4fv(filterColorUni, 0, 1, c); 208 fCurrentProgram->fColorFilterColor = drawState.getColorFilterColor(); 209 } 210 } 211 212 void GrGpuGL::flushCoverage(GrColor coverage) { 213 const ProgramDesc& desc = fCurrentProgram->getDesc(); 214 // const GrDrawState& drawState = this->getDrawState(); 215 216 217 if (this->getVertexLayout() & GrDrawState::kCoverage_VertexLayoutBit) { 218 // coverage will be specified per-vertex as an attribute 219 // invalidate the const vertex attrib coverage 220 fHWConstAttribCoverage = GrColor_ILLEGAL; 221 } else { 222 switch (desc.fCoverageInput) { 223 case ProgramDesc::kAttribute_ColorInput: 224 if (fHWConstAttribCoverage != coverage) { 225 // OpenGL ES only supports the float varieties of 226 // glVertexAttrib 227 GrGLfloat c[4]; 228 GrColorToRGBAFloat(coverage, c); 229 GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(), 230 c)); 231 fHWConstAttribCoverage = coverage; 232 } 233 break; 234 case ProgramDesc::kUniform_ColorInput: 235 if (fCurrentProgram->fCoverage != coverage) { 236 // OpenGL ES doesn't support unsigned byte varieties of 237 // glUniform 238 GrGLfloat c[4]; 239 GrColorToRGBAFloat(coverage, c); 240 GrAssert(kInvalidUniformHandle != 241 fCurrentProgram->fUniformHandles.fCoverageUni); 242 fCurrentProgram->fUniformManager.set4fv( 243 fCurrentProgram->fUniformHandles.fCoverageUni, 244 0, 1, c); 245 fCurrentProgram->fCoverage = coverage; 246 } 247 break; 248 case ProgramDesc::kSolidWhite_ColorInput: 249 case ProgramDesc::kTransBlack_ColorInput: 250 break; 251 default: 252 GrCrash("Unknown coverage type."); 253 } 254 } 255 } 256 257 bool GrGpuGL::flushGraphicsState(DrawType type) { 258 const GrDrawState& drawState = this->getDrawState(); 259 260 // GrGpu::setupClipAndFlushState should have already checked this 261 // and bailed if not true. 262 GrAssert(NULL != drawState.getRenderTarget()); 263 264 if (kStencilPath_DrawType != type) { 265 this->flushMiscFixedFunctionState(); 266 267 GrBlendCoeff srcCoeff; 268 GrBlendCoeff dstCoeff; 269 BlendOptFlags blendOpts = this->getBlendOpts(false, &srcCoeff, &dstCoeff); 270 if (kSkipDraw_BlendOptFlag & blendOpts) { 271 return false; 272 } 273 274 const GrEffectStage* stages[GrDrawState::kNumStages]; 275 for (int i = 0; i < GrDrawState::kNumStages; ++i) { 276 stages[i] = drawState.isStageEnabled(i) ? &drawState.getStage(i) : NULL; 277 } 278 GrGLProgram::Desc desc; 279 this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, &desc); 280 281 fCurrentProgram.reset(fProgramCache->getProgram(desc, stages)); 282 if (NULL == fCurrentProgram.get()) { 283 GrAssert(!"Failed to create program!"); 284 return false; 285 } 286 fCurrentProgram.get()->ref(); 287 288 if (fHWProgramID != fCurrentProgram->fProgramID) { 289 GL_CALL(UseProgram(fCurrentProgram->fProgramID)); 290 fHWProgramID = fCurrentProgram->fProgramID; 291 } 292 fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); 293 this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); 294 295 GrColor color; 296 GrColor coverage; 297 if (blendOpts & kEmitTransBlack_BlendOptFlag) { 298 color = 0; 299 coverage = 0; 300 } else if (blendOpts & kEmitCoverage_BlendOptFlag) { 301 color = 0xffffffff; 302 coverage = drawState.getCoverage(); 303 } else { 304 color = drawState.getColor(); 305 coverage = drawState.getCoverage(); 306 } 307 this->flushColor(color); 308 this->flushCoverage(coverage); 309 310 fCurrentProgram->setData(this); 311 } 312 this->flushStencil(type); 313 this->flushViewMatrix(type); 314 this->flushScissor(); 315 this->flushAAState(type); 316 317 GrIRect* devRect = NULL; 318 GrIRect devClipBounds; 319 if (drawState.isClipState()) { 320 this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); 321 devRect = &devClipBounds; 322 } 323 // This must come after textures are flushed because a texture may need 324 // to be msaa-resolved (which will modify bound FBO state). 325 this->flushRenderTarget(devRect); 326 327 return true; 328 } 329 330 #if GR_TEXT_SCALAR_IS_USHORT 331 #define TEXT_COORDS_GL_TYPE GR_GL_UNSIGNED_SHORT 332 #define TEXT_COORDS_ARE_NORMALIZED 1 333 #elif GR_TEXT_SCALAR_IS_FLOAT 334 #define TEXT_COORDS_GL_TYPE GR_GL_FLOAT 335 #define TEXT_COORDS_ARE_NORMALIZED 0 336 #elif GR_TEXT_SCALAR_IS_FIXED 337 #define TEXT_COORDS_GL_TYPE GR_GL_FIXED 338 #define TEXT_COORDS_ARE_NORMALIZED 0 339 #else 340 #error "unknown GR_TEXT_SCALAR type" 341 #endif 342 343 void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) { 344 345 int newColorOffset; 346 int newCoverageOffset; 347 int newTexCoordOffsets[GrDrawState::kMaxTexCoords]; 348 int newEdgeOffset; 349 350 GrVertexLayout currLayout = this->getVertexLayout(); 351 352 GrGLsizei newStride = GrDrawState::VertexSizeAndOffsetsByIdx(currLayout, 353 newTexCoordOffsets, 354 &newColorOffset, 355 &newCoverageOffset, 356 &newEdgeOffset); 357 int oldColorOffset; 358 int oldCoverageOffset; 359 int oldTexCoordOffsets[GrDrawState::kMaxTexCoords]; 360 int oldEdgeOffset; 361 362 GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout, 363 oldTexCoordOffsets, 364 &oldColorOffset, 365 &oldCoverageOffset, 366 &oldEdgeOffset); 367 368 int extraVertexOffset; 369 this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset); 370 371 GrGLenum scalarType; 372 bool texCoordNorm; 373 if (currLayout & GrDrawState::kTextFormat_VertexLayoutBit) { 374 scalarType = TEXT_COORDS_GL_TYPE; 375 texCoordNorm = SkToBool(TEXT_COORDS_ARE_NORMALIZED); 376 } else { 377 scalarType = GR_GL_FLOAT; 378 texCoordNorm = false; 379 } 380 381 size_t vertexOffset = (info.startVertex() + extraVertexOffset) * newStride; 382 383 // all the Pointers must be set if any of these are true 384 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || 385 vertexOffset != fHWGeometryState.fVertexOffset || 386 newStride != oldStride; 387 388 // position and tex coord offsets change if above conditions are true 389 // or the type/normalization changed based on text vs nontext type coords. 390 bool posAndTexChange = allOffsetsChange || 391 (((TEXT_COORDS_GL_TYPE != GR_GL_FLOAT) || TEXT_COORDS_ARE_NORMALIZED) && 392 (GrDrawState::kTextFormat_VertexLayoutBit & 393 (fHWGeometryState.fVertexLayout ^ currLayout))); 394 395 if (posAndTexChange) { 396 int idx = GrGLProgram::PositionAttributeIdx(); 397 GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride, 398 (GrGLvoid*)vertexOffset)); 399 fHWGeometryState.fVertexOffset = vertexOffset; 400 } 401 402 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 403 if (newTexCoordOffsets[t] > 0) { 404 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); 405 int idx = GrGLProgram::TexCoordAttributeIdx(t); 406 if (oldTexCoordOffsets[t] <= 0) { 407 GL_CALL(EnableVertexAttribArray(idx)); 408 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, 409 newStride, texCoordOffset)); 410 } else if (posAndTexChange || 411 newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { 412 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, 413 newStride, texCoordOffset)); 414 } 415 } else if (oldTexCoordOffsets[t] > 0) { 416 GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t))); 417 } 418 } 419 420 if (newColorOffset > 0) { 421 GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); 422 int idx = GrGLProgram::ColorAttributeIdx(); 423 if (oldColorOffset <= 0) { 424 GL_CALL(EnableVertexAttribArray(idx)); 425 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 426 true, newStride, colorOffset)); 427 } else if (allOffsetsChange || newColorOffset != oldColorOffset) { 428 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 429 true, newStride, colorOffset)); 430 } 431 } else if (oldColorOffset > 0) { 432 GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx())); 433 } 434 435 if (newCoverageOffset > 0) { 436 GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset); 437 int idx = GrGLProgram::CoverageAttributeIdx(); 438 if (oldCoverageOffset <= 0) { 439 GL_CALL(EnableVertexAttribArray(idx)); 440 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 441 true, newStride, coverageOffset)); 442 } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) { 443 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 444 true, newStride, coverageOffset)); 445 } 446 } else if (oldCoverageOffset > 0) { 447 GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx())); 448 } 449 450 if (newEdgeOffset > 0) { 451 GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset); 452 int idx = GrGLProgram::EdgeAttributeIdx(); 453 if (oldEdgeOffset <= 0) { 454 GL_CALL(EnableVertexAttribArray(idx)); 455 GL_CALL(VertexAttribPointer(idx, 4, scalarType, 456 false, newStride, edgeOffset)); 457 } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) { 458 GL_CALL(VertexAttribPointer(idx, 4, scalarType, 459 false, newStride, edgeOffset)); 460 } 461 } else if (oldEdgeOffset > 0) { 462 GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx())); 463 } 464 465 fHWGeometryState.fVertexLayout = currLayout; 466 fHWGeometryState.fArrayPtrsDirty = false; 467 } 468 469 void GrGpuGL::buildProgram(bool isPoints, 470 BlendOptFlags blendOpts, 471 GrBlendCoeff dstCoeff, 472 ProgramDesc* desc) { 473 const GrDrawState& drawState = this->getDrawState(); 474 475 // This should already have been caught 476 GrAssert(!(kSkipDraw_BlendOptFlag & blendOpts)); 477 478 bool skipCoverage = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag); 479 480 bool skipColor = SkToBool(blendOpts & (kEmitTransBlack_BlendOptFlag | 481 kEmitCoverage_BlendOptFlag)); 482 483 // The descriptor is used as a cache key. Thus when a field of the 484 // descriptor will not affect program generation (because of the vertex 485 // layout in use or other descriptor field settings) it should be set 486 // to a canonical value to avoid duplicate programs with different keys. 487 488 // Must initialize all fields or cache will have false negatives! 489 desc->fVertexLayout = this->getVertexLayout(); 490 491 desc->fEmitsPointSize = isPoints; 492 493 bool requiresAttributeColors = !skipColor && 494 SkToBool(desc->fVertexLayout & GrDrawState::kColor_VertexLayoutBit); 495 bool requiresAttributeCoverage = !skipCoverage && 496 SkToBool(desc->fVertexLayout & GrDrawState::kCoverage_VertexLayoutBit); 497 498 // fColorInput/fCoverageInput records how colors are specified for the. 499 // program. So we strip the bits from the layout to avoid false negatives 500 // when searching for an existing program in the cache. 501 desc->fVertexLayout &= ~(GrDrawState::kColor_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit); 502 503 desc->fColorFilterXfermode = skipColor ? 504 SkXfermode::kDst_Mode : 505 drawState.getColorFilterMode(); 506 507 // no reason to do edge aa or look at per-vertex coverage if coverage is 508 // ignored 509 if (skipCoverage) { 510 desc->fVertexLayout &= ~(GrDrawState::kEdge_VertexLayoutBit | GrDrawState::kCoverage_VertexLayoutBit); 511 } 512 513 bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag); 514 bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) || 515 (!requiresAttributeColors && 0xffffffff == drawState.getColor()); 516 if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) { 517 desc->fColorInput = ProgramDesc::kTransBlack_ColorInput; 518 } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) { 519 desc->fColorInput = ProgramDesc::kSolidWhite_ColorInput; 520 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) { 521 desc->fColorInput = ProgramDesc::kUniform_ColorInput; 522 } else { 523 desc->fColorInput = ProgramDesc::kAttribute_ColorInput; 524 } 525 526 bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage(); 527 528 if (skipCoverage) { 529 desc->fCoverageInput = ProgramDesc::kTransBlack_ColorInput; 530 } else if (covIsSolidWhite) { 531 desc->fCoverageInput = ProgramDesc::kSolidWhite_ColorInput; 532 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) { 533 desc->fCoverageInput = ProgramDesc::kUniform_ColorInput; 534 } else { 535 desc->fCoverageInput = ProgramDesc::kAttribute_ColorInput; 536 } 537 538 int lastEnabledStage = -1; 539 540 if (!skipCoverage && (desc->fVertexLayout &GrDrawState::kEdge_VertexLayoutBit)) { 541 desc->fVertexEdgeType = drawState.getVertexEdgeType(); 542 desc->fDiscardIfOutsideEdge = drawState.getStencil().doesWrite(); 543 } else { 544 // Use canonical values when edge-aa is not enabled to avoid program cache misses. 545 desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType; 546 desc->fDiscardIfOutsideEdge = false; 547 } 548 549 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 550 551 bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage; 552 if (!skip && drawState.isStageEnabled(s)) { 553 lastEnabledStage = s; 554 const GrEffectRef& effect = *drawState.getStage(s).getEffect(); 555 const GrBackendEffectFactory& factory = effect->getFactory(); 556 desc->fEffectKeys[s] = factory.glEffectKey(drawState.getStage(s), this->glCaps()); 557 } else { 558 desc->fEffectKeys[s] = 0; 559 } 560 } 561 562 desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; 563 564 // Currently the experimental GS will only work with triangle prims (and it doesn't do anything 565 // other than pass through values from the VS to the FS anyway). 566 #if 0 && GR_GL_EXPERIMENTAL_GS 567 desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport; 568 #endif 569 570 // We want to avoid generating programs with different "first cov stage" values when they would 571 // compute the same result. We set field in the desc to kNumStages when either there are no 572 // coverage stages or the distinction between coverage and color is immaterial. 573 int firstCoverageStage = GrDrawState::kNumStages; 574 desc->fFirstCoverageStage = GrDrawState::kNumStages; 575 bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage; 576 if (hasCoverage) { 577 firstCoverageStage = drawState.getFirstCoverageStage(); 578 } 579 580 // other coverage inputs 581 if (!hasCoverage) { 582 hasCoverage = requiresAttributeCoverage || 583 (desc->fVertexLayout & GrDrawState::kEdge_VertexLayoutBit); 584 } 585 586 if (hasCoverage) { 587 // color filter is applied between color/coverage computation 588 if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) { 589 desc->fFirstCoverageStage = firstCoverageStage; 590 } 591 592 if (this->getCaps().dualSourceBlendingSupport() && 593 !(blendOpts & (kEmitCoverage_BlendOptFlag | kCoverageAsAlpha_BlendOptFlag))) { 594 if (kZero_GrBlendCoeff == dstCoeff) { 595 // write the coverage value to second color 596 desc->fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput; 597 desc->fFirstCoverageStage = firstCoverageStage; 598 } else if (kSA_GrBlendCoeff == dstCoeff) { 599 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. 600 desc->fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput; 601 desc->fFirstCoverageStage = firstCoverageStage; 602 } else if (kSC_GrBlendCoeff == dstCoeff) { 603 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. 604 desc->fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput; 605 desc->fFirstCoverageStage = firstCoverageStage; 606 } 607 } 608 } 609 } 610