GrGpuGL_program.cpp revision a04e8e842450e606dd938ddae17857849bd504d4
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 "GrCustomStage.h" 11#include "GrGLProgramStage.h" 12#include "GrGpuVertex.h" 13 14typedef GrGLUniformManager::UniformHandle UniformHandle; 15static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle; 16 17#define SKIP_CACHE_CHECK true 18#define GR_UINT32_MAX static_cast<uint32_t>(-1) 19 20GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl) 21 : fCount(0) 22 , fCurrLRUStamp(0) 23 , fGL(gl) { 24} 25 26void 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 35GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, 36 const GrCustomStage** 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 76void 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 86void 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 GrMatrix& 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 GrMatrix m; 100 m.setScale(GrIntToScalar(2) / rt->width(), GrIntToScalar(-2) / rt->height()); 101 m.postTranslate(-GR_Scalar1, GR_Scalar1); 102 m.preConcat(vm); 103 104 // GL wants a column-major 4x4. 105 GrGLfloat mv[] = { 106 // col 0 107 GrScalarToFloat(m[GrMatrix::kMScaleX]), 108 GrScalarToFloat(m[GrMatrix::kMSkewY]), 109 0, 110 GrScalarToFloat(m[GrMatrix::kMPersp0]), 111 112 // col 1 113 GrScalarToFloat(m[GrMatrix::kMSkewX]), 114 GrScalarToFloat(m[GrMatrix::kMScaleY]), 115 0, 116 GrScalarToFloat(m[GrMatrix::kMPersp1]), 117 118 // col 2 119 0, 0, 0, 0, 120 121 // col3 122 GrScalarToFloat(m[GrMatrix::kMTransX]), 123 GrScalarToFloat(m[GrMatrix::kMTransY]), 124 0.0f, 125 GrScalarToFloat(m[GrMatrix::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 GrMatrix m; 135 m.setAll( 136 GrIntToScalar(2) / viewportSize.fWidth, 0, -GR_Scalar1, 137 0,-GrIntToScalar(2) / viewportSize.fHeight, GR_Scalar1, 138 0, 0, GrMatrix::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 GrScalarToFloat(m[GrMatrix::kMScaleX]), 145 GrScalarToFloat(m[GrMatrix::kMSkewY]), 146 GrScalarToFloat(m[GrMatrix::kMPersp0]), 147 GrScalarToFloat(m[GrMatrix::kMSkewX]), 148 GrScalarToFloat(m[GrMatrix::kMScaleY]), 149 GrScalarToFloat(m[GrMatrix::kMPersp1]), 150 GrScalarToFloat(m[GrMatrix::kMTransX]), 151 GrScalarToFloat(m[GrMatrix::kMTransY]), 152 GrScalarToFloat(m[GrMatrix::kMPersp2]) 153 }; 154 fCurrentProgram->fUniformManager.setMatrix3f(fCurrentProgram->fUniforms.fViewMatrixUni, mt); 155 fCurrentProgram->fViewMatrix = vm; 156 fCurrentProgram->fViewportSize = viewportSize; 157 } 158} 159 160/////////////////////////////////////////////////////////////////////////////// 161 162// helpers for texture matrices 163 164void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture, 165 GrMatrix* matrix) { 166 GrAssert(NULL != texture); 167 GrAssert(NULL != matrix); 168 GrGLTexture::Orientation orientation = texture->orientation(); 169 if (GrGLTexture::kBottomUp_Orientation == orientation) { 170 GrMatrix invY; 171 invY.setAll(GR_Scalar1, 0, 0, 172 0, -GR_Scalar1, GR_Scalar1, 173 0, 0, GrMatrix::I()[8]); 174 matrix->postConcat(invY); 175 } else { 176 GrAssert(GrGLTexture::kTopDown_Orientation == orientation); 177 } 178} 179 180bool GrGpuGL::TextureMatrixIsIdentity(const GrGLTexture* texture, 181 const GrSamplerState& sampler) { 182 GrAssert(NULL != texture); 183 if (!sampler.getMatrix().isIdentity()) { 184 return false; 185 } 186 GrGLTexture::Orientation orientation = texture->orientation(); 187 if (GrGLTexture::kBottomUp_Orientation == orientation) { 188 return false; 189 } else { 190 GrAssert(GrGLTexture::kTopDown_Orientation == orientation); 191 } 192 return true; 193} 194 195/////////////////////////////////////////////////////////////////////////////// 196 197void GrGpuGL::flushTextureMatrix(int s) { 198 const GrDrawState& drawState = this->getDrawState(); 199 200 // FIXME: Still assuming only a single texture per custom stage 201 const GrCustomStage* stage = drawState.getSampler(s).getCustomStage(); 202 const GrGLTexture* texture = static_cast<const GrGLTexture*>(stage->texture(0)); 203 if (NULL != texture) { 204 205 bool orientationChange = fCurrentProgram->fTextureOrientation[s] != 206 texture->orientation(); 207 208 UniformHandle matrixUni = fCurrentProgram->fUniforms.fStages[s].fTextureMatrixUni; 209 210 const GrMatrix& hwMatrix = fCurrentProgram->fTextureMatrices[s]; 211 const GrMatrix& samplerMatrix = drawState.getSampler(s).getMatrix(); 212 213 if (kInvalidUniformHandle != matrixUni && 214 (orientationChange || !hwMatrix.cheapEqualTo(samplerMatrix))) { 215 216 GrMatrix m = samplerMatrix; 217 AdjustTextureMatrix(texture, &m); 218 219 // ES doesn't allow you to pass true to the transpose param, 220 // so do our own transpose 221 GrGLfloat mt[] = { 222 GrScalarToFloat(m[GrMatrix::kMScaleX]), 223 GrScalarToFloat(m[GrMatrix::kMSkewY]), 224 GrScalarToFloat(m[GrMatrix::kMPersp0]), 225 GrScalarToFloat(m[GrMatrix::kMSkewX]), 226 GrScalarToFloat(m[GrMatrix::kMScaleY]), 227 GrScalarToFloat(m[GrMatrix::kMPersp1]), 228 GrScalarToFloat(m[GrMatrix::kMTransX]), 229 GrScalarToFloat(m[GrMatrix::kMTransY]), 230 GrScalarToFloat(m[GrMatrix::kMPersp2]) 231 }; 232 233 fCurrentProgram->fUniformManager.setMatrix3f(matrixUni, mt); 234 fCurrentProgram->fTextureMatrices[s] = samplerMatrix; 235 } 236 237 fCurrentProgram->fTextureOrientation[s] = texture->orientation(); 238 } 239} 240 241 242void GrGpuGL::flushColorMatrix() { 243 UniformHandle matrixUni = fCurrentProgram->fUniforms.fColorMatrixUni; 244 UniformHandle vecUni = fCurrentProgram->fUniforms.fColorMatrixVecUni; 245 if (kInvalidUniformHandle != matrixUni && kInvalidUniformHandle != vecUni) { 246 const float* m = this->getDrawState().getColorMatrix(); 247 GrGLfloat mt[] = { 248 m[0], m[5], m[10], m[15], 249 m[1], m[6], m[11], m[16], 250 m[2], m[7], m[12], m[17], 251 m[3], m[8], m[13], m[18], 252 }; 253 static float scale = 1.0f / 255.0f; 254 GrGLfloat vec[] = { 255 m[4] * scale, m[9] * scale, m[14] * scale, m[19] * scale, 256 }; 257 fCurrentProgram->fUniformManager.setMatrix4f(matrixUni, mt); 258 fCurrentProgram->fUniformManager.set4fv(vecUni, 0, 1, vec); 259 } 260} 261 262static const float ONE_OVER_255 = 1.f / 255.f; 263 264#define GR_COLOR_TO_VEC4(color) {\ 265 GrColorUnpackR(color) * ONE_OVER_255,\ 266 GrColorUnpackG(color) * ONE_OVER_255,\ 267 GrColorUnpackB(color) * ONE_OVER_255,\ 268 GrColorUnpackA(color) * ONE_OVER_255 \ 269} 270 271void GrGpuGL::flushColor(GrColor color) { 272 const ProgramDesc& desc = fCurrentProgram->getDesc(); 273 const GrDrawState& drawState = this->getDrawState(); 274 275 if (this->getVertexLayout() & kColor_VertexLayoutBit) { 276 // color will be specified per-vertex as an attribute 277 // invalidate the const vertex attrib color 278 fHWConstAttribColor = GrColor_ILLEGAL; 279 } else { 280 switch (desc.fColorInput) { 281 case ProgramDesc::kAttribute_ColorInput: 282 if (fHWConstAttribColor != color) { 283 // OpenGL ES only supports the float varieties of 284 // glVertexAttrib 285 float c[] = GR_COLOR_TO_VEC4(color); 286 GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), 287 c)); 288 fHWConstAttribColor = color; 289 } 290 break; 291 case ProgramDesc::kUniform_ColorInput: 292 if (fCurrentProgram->fColor != color) { 293 // OpenGL ES doesn't support unsigned byte varieties of 294 // glUniform 295 float c[] = GR_COLOR_TO_VEC4(color); 296 GrAssert(kInvalidUniformHandle != fCurrentProgram->fUniforms.fColorUni); 297 fCurrentProgram->fUniformManager.set4fv(fCurrentProgram->fUniforms.fColorUni, 298 0, 1, c); 299 fCurrentProgram->fColor = color; 300 } 301 break; 302 case ProgramDesc::kSolidWhite_ColorInput: 303 case ProgramDesc::kTransBlack_ColorInput: 304 break; 305 default: 306 GrCrash("Unknown color type."); 307 } 308 } 309 UniformHandle filterColorUni = fCurrentProgram->fUniforms.fColorFilterUni; 310 if (kInvalidUniformHandle != filterColorUni && 311 fCurrentProgram->fColorFilterColor != drawState.getColorFilterColor()) { 312 float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor()); 313 fCurrentProgram->fUniformManager.set4fv(filterColorUni, 0, 1, c); 314 fCurrentProgram->fColorFilterColor = drawState.getColorFilterColor(); 315 } 316} 317 318void GrGpuGL::flushCoverage(GrColor coverage) { 319 const ProgramDesc& desc = fCurrentProgram->getDesc(); 320 // const GrDrawState& drawState = this->getDrawState(); 321 322 323 if (this->getVertexLayout() & kCoverage_VertexLayoutBit) { 324 // coverage will be specified per-vertex as an attribute 325 // invalidate the const vertex attrib coverage 326 fHWConstAttribCoverage = GrColor_ILLEGAL; 327 } else { 328 switch (desc.fCoverageInput) { 329 case ProgramDesc::kAttribute_ColorInput: 330 if (fHWConstAttribCoverage != coverage) { 331 // OpenGL ES only supports the float varieties of 332 // glVertexAttrib 333 float c[] = GR_COLOR_TO_VEC4(coverage); 334 GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(), 335 c)); 336 fHWConstAttribCoverage = coverage; 337 } 338 break; 339 case ProgramDesc::kUniform_ColorInput: 340 if (fCurrentProgram->fCoverage != coverage) { 341 // OpenGL ES doesn't support unsigned byte varieties of 342 // glUniform 343 float c[] = GR_COLOR_TO_VEC4(coverage); 344 GrAssert(kInvalidUniformHandle != fCurrentProgram->fUniforms.fCoverageUni); 345 fCurrentProgram->fUniformManager.set4fv(fCurrentProgram->fUniforms.fCoverageUni, 346 0, 1, c); 347 fCurrentProgram->fCoverage = coverage; 348 } 349 break; 350 case ProgramDesc::kSolidWhite_ColorInput: 351 case ProgramDesc::kTransBlack_ColorInput: 352 break; 353 default: 354 GrCrash("Unknown coverage type."); 355 } 356 } 357} 358 359bool GrGpuGL::flushGraphicsState(DrawType type) { 360 const GrDrawState& drawState = this->getDrawState(); 361 362 // GrGpu::setupClipAndFlushState should have already checked this 363 // and bailed if not true. 364 GrAssert(NULL != drawState.getRenderTarget()); 365 366 if (kStencilPath_DrawType != type) { 367 this->flushMiscFixedFunctionState(); 368 369 GrBlendCoeff srcCoeff; 370 GrBlendCoeff dstCoeff; 371 BlendOptFlags blendOpts = this->getBlendOpts(false, &srcCoeff, &dstCoeff); 372 if (kSkipDraw_BlendOptFlag & blendOpts) { 373 return false; 374 } 375 376 const GrCustomStage* customStages [GrDrawState::kNumStages]; 377 GrGLProgram::Desc desc; 378 this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, customStages, &desc); 379 380 fCurrentProgram.reset(fProgramCache->getProgram(desc, customStages)); 381 if (NULL == fCurrentProgram.get()) { 382 GrAssert(!"Failed to create program!"); 383 return false; 384 } 385 fCurrentProgram.get()->ref(); 386 387 if (fHWProgramID != fCurrentProgram->fProgramID) { 388 GL_CALL(UseProgram(fCurrentProgram->fProgramID)); 389 fHWProgramID = fCurrentProgram->fProgramID; 390 } 391 fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); 392 this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); 393 394 GrColor color; 395 GrColor coverage; 396 if (blendOpts & kEmitTransBlack_BlendOptFlag) { 397 color = 0; 398 coverage = 0; 399 } else if (blendOpts & kEmitCoverage_BlendOptFlag) { 400 color = 0xffffffff; 401 coverage = drawState.getCoverage(); 402 } else { 403 color = drawState.getColor(); 404 coverage = drawState.getCoverage(); 405 } 406 this->flushColor(color); 407 this->flushCoverage(coverage); 408 409 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 410 if (this->isStageEnabled(s)) { 411 this->flushBoundTextureAndParams(s); 412 413 this->flushTextureMatrix(s); 414 415 if (NULL != fCurrentProgram->fProgramStage[s]) { 416 const GrSamplerState& sampler = this->getDrawState().getSampler(s); 417 fCurrentProgram->fProgramStage[s]->setData(fCurrentProgram->fUniformManager, 418 *sampler.getCustomStage(), 419 drawState.getRenderTarget(), s); 420 } 421 } 422 } 423 this->flushColorMatrix(); 424 } 425 this->flushStencil(type); 426 this->flushViewMatrix(type); 427 this->flushScissor(); 428 this->flushAAState(type); 429 430 GrIRect* devRect = NULL; 431 GrIRect devClipBounds; 432 if (drawState.isClipState()) { 433 fClip->getConservativeBounds(drawState.getRenderTarget(), 434 &devClipBounds); 435 devRect = &devClipBounds; 436 } 437 // This must come after textures are flushed because a texture may need 438 // to be msaa-resolved (which will modify bound FBO state). 439 this->flushRenderTarget(devRect); 440 441 return true; 442} 443 444#if GR_TEXT_SCALAR_IS_USHORT 445 #define TEXT_COORDS_GL_TYPE GR_GL_UNSIGNED_SHORT 446 #define TEXT_COORDS_ARE_NORMALIZED 1 447#elif GR_TEXT_SCALAR_IS_FLOAT 448 #define TEXT_COORDS_GL_TYPE GR_GL_FLOAT 449 #define TEXT_COORDS_ARE_NORMALIZED 0 450#elif GR_TEXT_SCALAR_IS_FIXED 451 #define TEXT_COORDS_GL_TYPE GR_GL_FIXED 452 #define TEXT_COORDS_ARE_NORMALIZED 0 453#else 454 #error "unknown GR_TEXT_SCALAR type" 455#endif 456 457void GrGpuGL::setupGeometry(int* startVertex, 458 int* startIndex, 459 int vertexCount, 460 int indexCount) { 461 462 int newColorOffset; 463 int newCoverageOffset; 464 int newTexCoordOffsets[GrDrawState::kMaxTexCoords]; 465 int newEdgeOffset; 466 467 GrVertexLayout currLayout = this->getVertexLayout(); 468 469 GrGLsizei newStride = VertexSizeAndOffsetsByIdx( 470 currLayout, 471 newTexCoordOffsets, 472 &newColorOffset, 473 &newCoverageOffset, 474 &newEdgeOffset); 475 int oldColorOffset; 476 int oldCoverageOffset; 477 int oldTexCoordOffsets[GrDrawState::kMaxTexCoords]; 478 int oldEdgeOffset; 479 480 GrGLsizei oldStride = VertexSizeAndOffsetsByIdx( 481 fHWGeometryState.fVertexLayout, 482 oldTexCoordOffsets, 483 &oldColorOffset, 484 &oldCoverageOffset, 485 &oldEdgeOffset); 486 bool indexed = NULL != startIndex; 487 488 int extraVertexOffset; 489 int extraIndexOffset; 490 this->setBuffers(indexed, &extraVertexOffset, &extraIndexOffset); 491 492 GrGLenum scalarType; 493 bool texCoordNorm; 494 if (currLayout & kTextFormat_VertexLayoutBit) { 495 scalarType = TEXT_COORDS_GL_TYPE; 496 texCoordNorm = SkToBool(TEXT_COORDS_ARE_NORMALIZED); 497 } else { 498 GR_STATIC_ASSERT(GR_SCALAR_IS_FLOAT); 499 scalarType = GR_GL_FLOAT; 500 texCoordNorm = false; 501 } 502 503 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride; 504 *startVertex = 0; 505 if (indexed) { 506 *startIndex += extraIndexOffset; 507 } 508 509 // all the Pointers must be set if any of these are true 510 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || 511 vertexOffset != fHWGeometryState.fVertexOffset || 512 newStride != oldStride; 513 514 // position and tex coord offsets change if above conditions are true 515 // or the type/normalization changed based on text vs nontext type coords. 516 bool posAndTexChange = allOffsetsChange || 517 (((TEXT_COORDS_GL_TYPE != GR_GL_FLOAT) || TEXT_COORDS_ARE_NORMALIZED) && 518 (kTextFormat_VertexLayoutBit & 519 (fHWGeometryState.fVertexLayout ^ currLayout))); 520 521 if (posAndTexChange) { 522 int idx = GrGLProgram::PositionAttributeIdx(); 523 GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride, 524 (GrGLvoid*)vertexOffset)); 525 fHWGeometryState.fVertexOffset = vertexOffset; 526 } 527 528 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 529 if (newTexCoordOffsets[t] > 0) { 530 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); 531 int idx = GrGLProgram::TexCoordAttributeIdx(t); 532 if (oldTexCoordOffsets[t] <= 0) { 533 GL_CALL(EnableVertexAttribArray(idx)); 534 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, 535 newStride, texCoordOffset)); 536 } else if (posAndTexChange || 537 newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { 538 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, 539 newStride, texCoordOffset)); 540 } 541 } else if (oldTexCoordOffsets[t] > 0) { 542 GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t))); 543 } 544 } 545 546 if (newColorOffset > 0) { 547 GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); 548 int idx = GrGLProgram::ColorAttributeIdx(); 549 if (oldColorOffset <= 0) { 550 GL_CALL(EnableVertexAttribArray(idx)); 551 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 552 true, newStride, colorOffset)); 553 } else if (allOffsetsChange || newColorOffset != oldColorOffset) { 554 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 555 true, newStride, colorOffset)); 556 } 557 } else if (oldColorOffset > 0) { 558 GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx())); 559 } 560 561 if (newCoverageOffset > 0) { 562 GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset); 563 int idx = GrGLProgram::CoverageAttributeIdx(); 564 if (oldCoverageOffset <= 0) { 565 GL_CALL(EnableVertexAttribArray(idx)); 566 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 567 true, newStride, coverageOffset)); 568 } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) { 569 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 570 true, newStride, coverageOffset)); 571 } 572 } else if (oldCoverageOffset > 0) { 573 GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx())); 574 } 575 576 if (newEdgeOffset > 0) { 577 GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset); 578 int idx = GrGLProgram::EdgeAttributeIdx(); 579 if (oldEdgeOffset <= 0) { 580 GL_CALL(EnableVertexAttribArray(idx)); 581 GL_CALL(VertexAttribPointer(idx, 4, scalarType, 582 false, newStride, edgeOffset)); 583 } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) { 584 GL_CALL(VertexAttribPointer(idx, 4, scalarType, 585 false, newStride, edgeOffset)); 586 } 587 } else if (oldEdgeOffset > 0) { 588 GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx())); 589 } 590 591 fHWGeometryState.fVertexLayout = currLayout; 592 fHWGeometryState.fArrayPtrsDirty = false; 593} 594 595namespace { 596 597void setup_custom_stage(GrGLProgram::Desc::StageDesc* stage, 598 const GrSamplerState& sampler, 599 const GrGLCaps& caps, 600 const GrCustomStage** customStages, 601 GrGLProgram* program, int index) { 602 const GrCustomStage* customStage = sampler.getCustomStage(); 603 if (customStage) { 604 const GrProgramStageFactory& factory = customStage->getFactory(); 605 stage->fCustomStageKey = factory.glStageKey(*customStage, caps); 606 customStages[index] = customStage; 607 } else { 608 stage->fCustomStageKey = 0; 609 customStages[index] = NULL; 610 } 611} 612 613} 614 615void GrGpuGL::buildProgram(bool isPoints, 616 BlendOptFlags blendOpts, 617 GrBlendCoeff dstCoeff, 618 const GrCustomStage** customStages, 619 ProgramDesc* desc) { 620 const GrDrawState& drawState = this->getDrawState(); 621 622 // This should already have been caught 623 GrAssert(!(kSkipDraw_BlendOptFlag & blendOpts)); 624 625 bool skipCoverage = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag); 626 627 bool skipColor = SkToBool(blendOpts & (kEmitTransBlack_BlendOptFlag | 628 kEmitCoverage_BlendOptFlag)); 629 630 // The descriptor is used as a cache key. Thus when a field of the 631 // descriptor will not affect program generation (because of the vertex 632 // layout in use or other descriptor field settings) it should be set 633 // to a canonical value to avoid duplicate programs with different keys. 634 635 // Must initialize all fields or cache will have false negatives! 636 desc->fVertexLayout = this->getVertexLayout(); 637 638 desc->fEmitsPointSize = isPoints; 639 640 bool requiresAttributeColors = !skipColor && 641 SkToBool(desc->fVertexLayout & kColor_VertexLayoutBit); 642 bool requiresAttributeCoverage = !skipCoverage && 643 SkToBool(desc->fVertexLayout & kCoverage_VertexLayoutBit); 644 645 // fColorInput/fCoverageInput records how colors are specified for the. 646 // program. So we strip the bits from the layout to avoid false negatives 647 // when searching for an existing program in the cache. 648 desc->fVertexLayout &= ~(kColor_VertexLayoutBit | kCoverage_VertexLayoutBit); 649 650 desc->fColorFilterXfermode = skipColor ? 651 SkXfermode::kDst_Mode : 652 drawState.getColorFilterMode(); 653 654 desc->fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit); 655 656 // no reason to do edge aa or look at per-vertex coverage if coverage is 657 // ignored 658 if (skipCoverage) { 659 desc->fVertexLayout &= ~(kEdge_VertexLayoutBit | kCoverage_VertexLayoutBit); 660 } 661 662 bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag); 663 bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) || 664 (!requiresAttributeColors && 0xffffffff == drawState.getColor()); 665 if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) { 666 desc->fColorInput = ProgramDesc::kTransBlack_ColorInput; 667 } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) { 668 desc->fColorInput = ProgramDesc::kSolidWhite_ColorInput; 669 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) { 670 desc->fColorInput = ProgramDesc::kUniform_ColorInput; 671 } else { 672 desc->fColorInput = ProgramDesc::kAttribute_ColorInput; 673 } 674 675 bool covIsSolidWhite = !requiresAttributeCoverage && 0xffffffff == drawState.getCoverage(); 676 677 if (skipCoverage) { 678 desc->fCoverageInput = ProgramDesc::kTransBlack_ColorInput; 679 } else if (covIsSolidWhite) { 680 desc->fCoverageInput = ProgramDesc::kSolidWhite_ColorInput; 681 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) { 682 desc->fCoverageInput = ProgramDesc::kUniform_ColorInput; 683 } else { 684 desc->fCoverageInput = ProgramDesc::kAttribute_ColorInput; 685 } 686 687 int lastEnabledStage = -1; 688 689 if (!skipCoverage && (desc->fVertexLayout &GrDrawTarget::kEdge_VertexLayoutBit)) { 690 desc->fVertexEdgeType = drawState.getVertexEdgeType(); 691 } else { 692 // use canonical value when not set to avoid cache misses 693 desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType; 694 } 695 696 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 697 StageDesc& stage = desc->fStages[s]; 698 699 stage.fOptFlags = 0; 700 stage.setEnabled(this->isStageEnabled(s)); 701 702 bool skip = s < drawState.getFirstCoverageStage() ? skipColor : 703 skipCoverage; 704 705 if (!skip && stage.isEnabled()) { 706 lastEnabledStage = s; 707 const GrSamplerState& sampler = drawState.getSampler(s); 708 // FIXME: Still assuming one texture per custom stage 709 const GrCustomStage* customStage = drawState.getSampler(s).getCustomStage(); 710 const GrGLTexture* texture = static_cast<const GrGLTexture*>(customStage->texture(0)); 711 stage.fInConfigFlags = 0; 712 if (NULL != texture) { 713 // We call this helper function rather then simply checking the client-specified 714 // texture matrix. This is because we may have to concat a y-inversion to account 715 // for texture orientation. 716 if (TextureMatrixIsIdentity(texture, sampler)) { 717 stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit; 718 } else if (!sampler.getMatrix().hasPerspective()) { 719 stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; 720 } 721 if (!this->glCaps().textureSwizzleSupport()) { 722 if (GrPixelConfigIsAlphaOnly(texture->config())) { 723 // If we don't have texture swizzle support then the shader must smear the 724 // single channel after reading the texture. 725 if (this->glCaps().textureRedSupport()) { 726 // We can use R8 textures so use kSmearRed. 727 stage.fInConfigFlags |= StageDesc::kSmearRed_InConfigFlag; 728 } else { 729 // We can use A8 textures so use kSmearAlpha. 730 stage.fInConfigFlags |= StageDesc::kSmearAlpha_InConfigFlag; 731 } 732 } 733 } 734 } 735 736 setup_custom_stage(&stage, sampler, this->glCaps(), customStages, 737 fCurrentProgram.get(), s); 738 739 } else { 740 stage.fOptFlags = 0; 741 stage.fInConfigFlags = 0; 742 stage.fCustomStageKey = 0; 743 customStages[s] = NULL; 744 } 745 } 746 747 desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; 748 749 // Currently the experimental GS will only work with triangle prims (and it doesn't do anything 750 // other than pass through values fromthe VS to the FS anyway). 751#if 0 && GR_GL_EXPERIMENTAL_GS 752 desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport; 753#endif 754 755 // We want to avoid generating programs with different "first cov stage" values when they would 756 // compute the same result. We set field in the desc to kNumStages when either there are no 757 // coverage stages or the distinction between coverage and color is immaterial. 758 int firstCoverageStage = GrDrawState::kNumStages; 759 desc->fFirstCoverageStage = GrDrawState::kNumStages; 760 bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage; 761 if (hasCoverage) { 762 firstCoverageStage = drawState.getFirstCoverageStage(); 763 } 764 765 // other coverage inputs 766 if (!hasCoverage) { 767 hasCoverage = requiresAttributeCoverage || 768 (desc->fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit); 769 } 770 771 if (hasCoverage) { 772 // color filter is applied between color/coverage computation 773 if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) { 774 desc->fFirstCoverageStage = firstCoverageStage; 775 } 776 777 if (this->getCaps().fDualSourceBlendingSupport && 778 !(blendOpts & (kEmitCoverage_BlendOptFlag | kCoverageAsAlpha_BlendOptFlag))) { 779 if (kZero_GrBlendCoeff == dstCoeff) { 780 // write the coverage value to second color 781 desc->fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput; 782 desc->fFirstCoverageStage = firstCoverageStage; 783 } else if (kSA_GrBlendCoeff == dstCoeff) { 784 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. 785 desc->fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput; 786 desc->fFirstCoverageStage = firstCoverageStage; 787 } else if (kSC_GrBlendCoeff == dstCoeff) { 788 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. 789 desc->fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput; 790 desc->fFirstCoverageStage = firstCoverageStage; 791 } 792 } 793 } 794} 795