1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "../GrBinHashKey.h" 11 #include "GrGLProgram.h" 12 #include "GrGLSL.h" 13 #include "GrGpuGLShaders.h" 14 #include "../GrGpuVertex.h" 15 #include "GrNoncopyable.h" 16 #include "../GrStringBuilder.h" 17 #include "../GrRandom.h" 18 19 #define SKIP_CACHE_CHECK true 20 #define GR_UINT32_MAX static_cast<uint32_t>(-1) 21 22 #include "../GrTHashCache.h" 23 24 class GrGpuGLShaders::ProgramCache : public ::GrNoncopyable { 25 private: 26 class Entry; 27 28 typedef GrBinHashKey<Entry, GrGLProgram::kProgramKeySize> ProgramHashKey; 29 30 class Entry : public ::GrNoncopyable { 31 public: Entry()32 Entry() {} copyAndTakeOwnership(Entry & entry)33 void copyAndTakeOwnership(Entry& entry) { 34 fProgramData.copyAndTakeOwnership(entry.fProgramData); 35 fKey = entry.fKey; // ownership transfer 36 fLRUStamp = entry.fLRUStamp; 37 } 38 39 public: compare(const ProgramHashKey & key) const40 int compare(const ProgramHashKey& key) const { return fKey.compare(key); } 41 42 public: 43 GrGLProgram::CachedData fProgramData; 44 ProgramHashKey fKey; 45 unsigned int fLRUStamp; 46 }; 47 48 GrTHashTable<Entry, ProgramHashKey, 8> fHashCache; 49 50 // We may have kMaxEntries+1 shaders in the GL context because 51 // we create a new shader before evicting from the cache. 52 enum { 53 kMaxEntries = 32 54 }; 55 Entry fEntries[kMaxEntries]; 56 int fCount; 57 unsigned int fCurrLRUStamp; 58 const GrGLContextInfo& fGL; 59 60 public: ProgramCache(const GrGLContextInfo & gl)61 ProgramCache(const GrGLContextInfo& gl) 62 : fCount(0) 63 , fCurrLRUStamp(0) 64 , fGL(gl) { 65 } 66 ~ProgramCache()67 ~ProgramCache() { 68 for (int i = 0; i < fCount; ++i) { 69 GrGpuGLShaders::DeleteProgram(fGL.interface(), 70 &fEntries[i].fProgramData); 71 } 72 } 73 abandon()74 void abandon() { 75 fCount = 0; 76 } 77 invalidateViewMatrices()78 void invalidateViewMatrices() { 79 for (int i = 0; i < fCount; ++i) { 80 // set to illegal matrix 81 fEntries[i].fProgramData.fViewMatrix = GrMatrix::InvalidMatrix(); 82 } 83 } 84 getProgramData(const GrGLProgram & desc)85 GrGLProgram::CachedData* getProgramData(const GrGLProgram& desc) { 86 Entry newEntry; 87 newEntry.fKey.setKeyData(desc.keyData()); 88 89 Entry* entry = fHashCache.find(newEntry.fKey); 90 if (NULL == entry) { 91 if (!desc.genProgram(fGL, &newEntry.fProgramData)) { 92 return NULL; 93 } 94 if (fCount < kMaxEntries) { 95 entry = fEntries + fCount; 96 ++fCount; 97 } else { 98 GrAssert(kMaxEntries == fCount); 99 entry = fEntries; 100 for (int i = 1; i < kMaxEntries; ++i) { 101 if (fEntries[i].fLRUStamp < entry->fLRUStamp) { 102 entry = fEntries + i; 103 } 104 } 105 fHashCache.remove(entry->fKey, entry); 106 GrGpuGLShaders::DeleteProgram(fGL.interface(), 107 &entry->fProgramData); 108 } 109 entry->copyAndTakeOwnership(newEntry); 110 fHashCache.insert(entry->fKey, entry); 111 } 112 113 entry->fLRUStamp = fCurrLRUStamp; 114 if (GR_UINT32_MAX == fCurrLRUStamp) { 115 // wrap around! just trash our LRU, one time hit. 116 for (int i = 0; i < fCount; ++i) { 117 fEntries[i].fLRUStamp = 0; 118 } 119 } 120 ++fCurrLRUStamp; 121 return &entry->fProgramData; 122 } 123 }; 124 abandonResources()125 void GrGpuGLShaders::abandonResources(){ 126 INHERITED::abandonResources(); 127 fProgramCache->abandon(); 128 } 129 DeleteProgram(const GrGLInterface * gl,CachedData * programData)130 void GrGpuGLShaders::DeleteProgram(const GrGLInterface* gl, 131 CachedData* programData) { 132 GR_GL_CALL(gl, DeleteShader(programData->fVShaderID)); 133 if (programData->fGShaderID) { 134 GR_GL_CALL(gl, DeleteShader(programData->fGShaderID)); 135 } 136 GR_GL_CALL(gl, DeleteShader(programData->fFShaderID)); 137 GR_GL_CALL(gl, DeleteProgram(programData->fProgramID)); 138 GR_DEBUGCODE(memset(programData, 0, sizeof(*programData));) 139 } 140 141 //////////////////////////////////////////////////////////////////////////////// 142 143 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) 144 145 namespace { 146 147 // GrRandoms nextU() values have patterns in the low bits 148 // So using nextU() % array_count might never take some values. random_int(GrRandom * r,int count)149 int random_int(GrRandom* r, int count) { 150 return (int)(r->nextF() * count); 151 } 152 153 // min is inclusive, max is exclusive random_int(GrRandom * r,int min,int max)154 int random_int(GrRandom* r, int min, int max) { 155 return (int)(r->nextF() * (max-min)) + min; 156 } 157 random_bool(GrRandom * r)158 bool random_bool(GrRandom* r) { 159 return r->nextF() > .5f; 160 } 161 162 } 163 programUnitTest()164 bool GrGpuGLShaders::programUnitTest() { 165 166 GrGLSLGeneration glslGeneration = 167 GrGetGLSLGeneration(this->glBinding(), this->glInterface()); 168 static const int STAGE_OPTS[] = { 169 0, 170 StageDesc::kNoPerspective_OptFlagBit, 171 StageDesc::kIdentity_CoordMapping 172 }; 173 static const int IN_CONFIG_FLAGS[] = { 174 StageDesc::kNone_InConfigFlag, 175 StageDesc::kSwapRAndB_InConfigFlag, 176 StageDesc::kSwapRAndB_InConfigFlag | 177 StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag, 178 StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag, 179 StageDesc::kSmearAlpha_InConfigFlag, 180 }; 181 GrGLProgram program; 182 ProgramDesc& pdesc = program.fProgramDesc; 183 184 static const int NUM_TESTS = 512; 185 186 GrRandom random; 187 for (int t = 0; t < NUM_TESTS; ++t) { 188 189 #if 0 190 GrPrintf("\nTest Program %d\n-------------\n", t); 191 static const int stop = -1; 192 if (t == stop) { 193 int breakpointhere = 9; 194 } 195 #endif 196 197 pdesc.fVertexLayout = 0; 198 pdesc.fEmitsPointSize = random.nextF() > .5f; 199 pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt); 200 pdesc.fCoverageInput = random_int(&random, ProgramDesc::kColorInputCnt); 201 202 pdesc.fColorFilterXfermode = random_int(&random, SkXfermode::kCoeffModesCnt); 203 204 pdesc.fFirstCoverageStage = random_int(&random, GrDrawState::kNumStages); 205 206 pdesc.fVertexLayout |= random_bool(&random) ? 207 GrDrawTarget::kCoverage_VertexLayoutBit : 208 0; 209 210 #if GR_GL_EXPERIMENTAL_GS 211 pdesc.fExperimentalGS = this->getCaps().fGeometryShaderSupport && 212 random_bool(&random); 213 #endif 214 pdesc.fOutputConfig = random_int(&random, ProgramDesc::kOutputConfigCnt); 215 216 bool edgeAA = random_bool(&random); 217 if (edgeAA) { 218 bool vertexEdgeAA = random_bool(&random); 219 if (vertexEdgeAA) { 220 pdesc.fVertexLayout |= GrDrawTarget::kEdge_VertexLayoutBit; 221 if (this->getCaps().fShaderDerivativeSupport) { 222 pdesc.fVertexEdgeType = (GrDrawState::VertexEdgeType) random_int(&random, GrDrawState::kVertexEdgeTypeCnt); 223 } else { 224 pdesc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; 225 } 226 pdesc.fEdgeAANumEdges = 0; 227 } else { 228 pdesc.fEdgeAANumEdges = random_int(&random, 1, this->getMaxEdges()); 229 pdesc.fEdgeAAConcave = random_bool(&random); 230 } 231 } else { 232 pdesc.fEdgeAANumEdges = 0; 233 } 234 235 pdesc.fColorMatrixEnabled = random_bool(&random); 236 237 if (this->getCaps().fDualSourceBlendingSupport) { 238 pdesc.fDualSrcOutput = random_int(&random, ProgramDesc::kDualSrcOutputCnt); 239 } else { 240 pdesc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; 241 } 242 243 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 244 // enable the stage? 245 if (random_bool(&random)) { 246 // use separate tex coords? 247 if (random_bool(&random)) { 248 int t = random_int(&random, GrDrawState::kMaxTexCoords); 249 pdesc.fVertexLayout |= StageTexCoordVertexLayoutBit(s, t); 250 } else { 251 pdesc.fVertexLayout |= StagePosAsTexCoordVertexLayoutBit(s); 252 } 253 } 254 // use text-formatted verts? 255 if (random_bool(&random)) { 256 pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit; 257 } 258 StageDesc& stage = pdesc.fStages[s]; 259 stage.fOptFlags = STAGE_OPTS[random_int(&random, GR_ARRAY_COUNT(STAGE_OPTS))]; 260 stage.fInConfigFlags = IN_CONFIG_FLAGS[random_int(&random, GR_ARRAY_COUNT(IN_CONFIG_FLAGS))]; 261 stage.fCoordMapping = random_int(&random, StageDesc::kCoordMappingCnt); 262 stage.fFetchMode = random_int(&random, StageDesc::kFetchModeCnt); 263 // convolution shaders don't work with persp tex matrix 264 if (stage.fFetchMode == StageDesc::kConvolution_FetchMode || 265 stage.fFetchMode == StageDesc::kDilate_FetchMode || 266 stage.fFetchMode == StageDesc::kErode_FetchMode) { 267 stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; 268 } 269 stage.setEnabled(VertexUsesStage(s, pdesc.fVertexLayout)); 270 static const uint32_t kMulByAlphaMask = 271 StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag | 272 StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag; 273 switch (stage.fFetchMode) { 274 case StageDesc::kSingle_FetchMode: 275 stage.fKernelWidth = 0; 276 break; 277 case StageDesc::kConvolution_FetchMode: 278 case StageDesc::kDilate_FetchMode: 279 case StageDesc::kErode_FetchMode: 280 stage.fKernelWidth = random_int(&random, 2, 8); 281 stage.fInConfigFlags &= ~kMulByAlphaMask; 282 break; 283 case StageDesc::k2x2_FetchMode: 284 stage.fKernelWidth = 0; 285 stage.fInConfigFlags &= ~kMulByAlphaMask; 286 break; 287 } 288 } 289 CachedData cachedData; 290 if (!program.genProgram(this->glContextInfo(), &cachedData)) { 291 return false; 292 } 293 DeleteProgram(this->glInterface(), &cachedData); 294 } 295 return true; 296 } 297 GrGpuGLShaders(const GrGLContextInfo & ctxInfo)298 GrGpuGLShaders::GrGpuGLShaders(const GrGLContextInfo& ctxInfo) 299 : GrGpuGL(ctxInfo) { 300 301 // Enable supported shader-related caps 302 if (kDesktop_GrGLBinding == this->glBinding()) { 303 fCaps.fDualSourceBlendingSupport = 304 this->glVersion() >= GR_GL_VER(3,3) || 305 this->hasExtension("GL_ARB_blend_func_extended"); 306 fCaps.fShaderDerivativeSupport = true; 307 // we don't support GL_ARB_geometry_shader4, just GL 3.2+ GS 308 fCaps.fGeometryShaderSupport = 309 this->glVersion() >= GR_GL_VER(3,2) && 310 this->glslGeneration() >= k150_GrGLSLGeneration; 311 } else { 312 fCaps.fShaderDerivativeSupport = 313 this->hasExtension("GL_OES_standard_derivatives"); 314 } 315 316 GR_GL_GetIntegerv(this->glInterface(), 317 GR_GL_MAX_VERTEX_ATTRIBS, 318 &fMaxVertexAttribs); 319 320 fProgramData = NULL; 321 fProgramCache = new ProgramCache(this->glContextInfo()); 322 323 #if 0 324 this->programUnitTest(); 325 #endif 326 } 327 ~GrGpuGLShaders()328 GrGpuGLShaders::~GrGpuGLShaders() { 329 delete fProgramCache; 330 } 331 getHWViewMatrix()332 const GrMatrix& GrGpuGLShaders::getHWViewMatrix() { 333 GrAssert(fProgramData); 334 335 if (GrGLProgram::kSetAsAttribute == 336 fProgramData->fUniLocations.fViewMatrixUni) { 337 return fHWDrawState.getViewMatrix(); 338 } else { 339 return fProgramData->fViewMatrix; 340 } 341 } 342 recordHWViewMatrix(const GrMatrix & matrix)343 void GrGpuGLShaders::recordHWViewMatrix(const GrMatrix& matrix) { 344 GrAssert(fProgramData); 345 if (GrGLProgram::kSetAsAttribute == 346 fProgramData->fUniLocations.fViewMatrixUni) { 347 fHWDrawState.setViewMatrix(matrix); 348 } else { 349 fProgramData->fViewMatrix = matrix; 350 } 351 } 352 getHWSamplerMatrix(int stage)353 const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) { 354 GrAssert(fProgramData); 355 356 if (GrGLProgram::kSetAsAttribute == 357 fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) { 358 return fHWDrawState.getSampler(stage).getMatrix(); 359 } else { 360 return fProgramData->fTextureMatrices[stage]; 361 } 362 } 363 recordHWSamplerMatrix(int stage,const GrMatrix & matrix)364 void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) { 365 GrAssert(fProgramData); 366 if (GrGLProgram::kSetAsAttribute == 367 fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) { 368 *fHWDrawState.sampler(stage)->matrix() = matrix; 369 } else { 370 fProgramData->fTextureMatrices[stage] = matrix; 371 } 372 } 373 onResetContext()374 void GrGpuGLShaders::onResetContext() { 375 INHERITED::onResetContext(); 376 377 fHWGeometryState.fVertexOffset = ~0; 378 379 // Third party GL code may have left vertex attributes enabled. Some GL 380 // implementations (osmesa) may read vetex attributes that are not required 381 // by the current shader. Therefore, we have to ensure that only the 382 // attributes we require for the current draw are enabled or we may cause an 383 // invalid read. 384 385 // Disable all vertex layout bits so that next flush will assume all 386 // optional vertex attributes are disabled. 387 fHWGeometryState.fVertexLayout = 0; 388 389 // We always use the this attribute and assume it is always enabled. 390 int posAttrIdx = GrGLProgram::PositionAttributeIdx(); 391 GL_CALL(EnableVertexAttribArray(posAttrIdx)); 392 // Disable all other vertex attributes. 393 for (int va = 0; va < fMaxVertexAttribs; ++va) { 394 if (va != posAttrIdx) { 395 GL_CALL(DisableVertexAttribArray(va)); 396 } 397 } 398 399 fHWProgramID = 0; 400 } 401 flushViewMatrix()402 void GrGpuGLShaders::flushViewMatrix() { 403 const GrMatrix& vm = this->getDrawState().getViewMatrix(); 404 if (GrGpuGLShaders::getHWViewMatrix() != vm) { 405 406 const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); 407 GrAssert(NULL != rt); 408 GrMatrix m; 409 m.setAll( 410 GrIntToScalar(2) / rt->width(), 0, -GR_Scalar1, 411 0,-GrIntToScalar(2) / rt->height(), GR_Scalar1, 412 0, 0, GrMatrix::I()[8]); 413 m.setConcat(m, vm); 414 415 // ES doesn't allow you to pass true to the transpose param, 416 // so do our own transpose 417 GrGLfloat mt[] = { 418 GrScalarToFloat(m[GrMatrix::kMScaleX]), 419 GrScalarToFloat(m[GrMatrix::kMSkewY]), 420 GrScalarToFloat(m[GrMatrix::kMPersp0]), 421 GrScalarToFloat(m[GrMatrix::kMSkewX]), 422 GrScalarToFloat(m[GrMatrix::kMScaleY]), 423 GrScalarToFloat(m[GrMatrix::kMPersp1]), 424 GrScalarToFloat(m[GrMatrix::kMTransX]), 425 GrScalarToFloat(m[GrMatrix::kMTransY]), 426 GrScalarToFloat(m[GrMatrix::kMPersp2]) 427 }; 428 429 if (GrGLProgram::kSetAsAttribute == 430 fProgramData->fUniLocations.fViewMatrixUni) { 431 int baseIdx = GrGLProgram::ViewMatrixAttributeIdx(); 432 GL_CALL(VertexAttrib4fv(baseIdx + 0, mt+0)); 433 GL_CALL(VertexAttrib4fv(baseIdx + 1, mt+3)); 434 GL_CALL(VertexAttrib4fv(baseIdx + 2, mt+6)); 435 } else { 436 GrAssert(GrGLProgram::kUnusedUniform != 437 fProgramData->fUniLocations.fViewMatrixUni); 438 GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni, 439 1, false, mt)); 440 } 441 this->recordHWViewMatrix(vm); 442 } 443 } 444 flushTextureDomain(int s)445 void GrGpuGLShaders::flushTextureDomain(int s) { 446 const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni; 447 const GrDrawState& drawState = this->getDrawState(); 448 if (GrGLProgram::kUnusedUniform != uni) { 449 const GrRect &texDom = drawState.getSampler(s).getTextureDomain(); 450 451 if (((1 << s) & fDirtyFlags.fTextureChangedMask) || 452 fProgramData->fTextureDomain[s] != texDom) { 453 454 fProgramData->fTextureDomain[s] = texDom; 455 456 float values[4] = { 457 GrScalarToFloat(texDom.left()), 458 GrScalarToFloat(texDom.top()), 459 GrScalarToFloat(texDom.right()), 460 GrScalarToFloat(texDom.bottom()) 461 }; 462 463 const GrGLTexture* texture = 464 static_cast<const GrGLTexture*>(drawState.getTexture(s)); 465 GrGLTexture::Orientation orientation = texture->orientation(); 466 467 // vertical flip if necessary 468 if (GrGLTexture::kBottomUp_Orientation == orientation) { 469 values[1] = 1.0f - values[1]; 470 values[3] = 1.0f - values[3]; 471 // The top and bottom were just flipped, so correct the ordering 472 // of elements so that values = (l, t, r, b). 473 SkTSwap(values[1], values[3]); 474 } 475 476 GL_CALL(Uniform4fv(uni, 1, values)); 477 } 478 } 479 } 480 flushTextureMatrix(int s)481 void GrGpuGLShaders::flushTextureMatrix(int s) { 482 const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni; 483 const GrDrawState& drawState = this->getDrawState(); 484 const GrGLTexture* texture = 485 static_cast<const GrGLTexture*>(drawState.getTexture(s)); 486 if (NULL != texture) { 487 if (GrGLProgram::kUnusedUniform != uni && 488 (((1 << s) & fDirtyFlags.fTextureChangedMask) || 489 this->getHWSamplerMatrix(s) != drawState.getSampler(s).getMatrix())) { 490 491 GrMatrix m = drawState.getSampler(s).getMatrix(); 492 GrSamplerState::SampleMode mode = 493 drawState.getSampler(s).getSampleMode(); 494 AdjustTextureMatrix(texture, mode, &m); 495 496 // ES doesn't allow you to pass true to the transpose param, 497 // so do our own transpose 498 GrGLfloat mt[] = { 499 GrScalarToFloat(m[GrMatrix::kMScaleX]), 500 GrScalarToFloat(m[GrMatrix::kMSkewY]), 501 GrScalarToFloat(m[GrMatrix::kMPersp0]), 502 GrScalarToFloat(m[GrMatrix::kMSkewX]), 503 GrScalarToFloat(m[GrMatrix::kMScaleY]), 504 GrScalarToFloat(m[GrMatrix::kMPersp1]), 505 GrScalarToFloat(m[GrMatrix::kMTransX]), 506 GrScalarToFloat(m[GrMatrix::kMTransY]), 507 GrScalarToFloat(m[GrMatrix::kMPersp2]) 508 }; 509 510 if (GrGLProgram::kSetAsAttribute == 511 fProgramData->fUniLocations.fStages[s].fTextureMatrixUni) { 512 int baseIdx = GrGLProgram::TextureMatrixAttributeIdx(s); 513 GL_CALL(VertexAttrib4fv(baseIdx + 0, mt+0)); 514 GL_CALL(VertexAttrib4fv(baseIdx + 1, mt+3)); 515 GL_CALL(VertexAttrib4fv(baseIdx + 2, mt+6)); 516 } else { 517 GL_CALL(UniformMatrix3fv(uni, 1, false, mt)); 518 } 519 this->recordHWSamplerMatrix(s, drawState.getSampler(s).getMatrix()); 520 } 521 } 522 } 523 flushRadial2(int s)524 void GrGpuGLShaders::flushRadial2(int s) { 525 526 const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni; 527 const GrSamplerState& sampler = this->getDrawState().getSampler(s); 528 if (GrGLProgram::kUnusedUniform != uni && 529 (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() || 530 fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() || 531 fProgramData->fRadial2PosRoot[s] != sampler.isRadial2PosRoot())) { 532 533 GrScalar centerX1 = sampler.getRadial2CenterX1(); 534 GrScalar radius0 = sampler.getRadial2Radius0(); 535 536 GrScalar a = GrMul(centerX1, centerX1) - GR_Scalar1; 537 538 // when were in the degenerate (linear) case the second 539 // value will be INF but the program doesn't read it. (We 540 // use the same 6 uniforms even though we don't need them 541 // all in the linear case just to keep the code complexity 542 // down). 543 float values[6] = { 544 GrScalarToFloat(a), 545 1 / (2.f * GrScalarToFloat(a)), 546 GrScalarToFloat(centerX1), 547 GrScalarToFloat(radius0), 548 GrScalarToFloat(GrMul(radius0, radius0)), 549 sampler.isRadial2PosRoot() ? 1.f : -1.f 550 }; 551 GL_CALL(Uniform1fv(uni, 6, values)); 552 fProgramData->fRadial2CenterX1[s] = sampler.getRadial2CenterX1(); 553 fProgramData->fRadial2Radius0[s] = sampler.getRadial2Radius0(); 554 fProgramData->fRadial2PosRoot[s] = sampler.isRadial2PosRoot(); 555 } 556 } 557 flushConvolution(int s)558 void GrGpuGLShaders::flushConvolution(int s) { 559 const GrSamplerState& sampler = this->getDrawState().getSampler(s); 560 int kernelUni = fProgramData->fUniLocations.fStages[s].fKernelUni; 561 if (GrGLProgram::kUnusedUniform != kernelUni) { 562 GL_CALL(Uniform1fv(kernelUni, sampler.getKernelWidth(), 563 sampler.getKernel())); 564 } 565 int imageIncrementUni = fProgramData->fUniLocations.fStages[s].fImageIncrementUni; 566 if (GrGLProgram::kUnusedUniform != imageIncrementUni) { 567 const GrGLTexture* texture = 568 static_cast<const GrGLTexture*>(this->getDrawState().getTexture(s)); 569 float imageIncrement[2] = { 0 }; 570 switch (sampler.getFilterDirection()) { 571 case GrSamplerState::kX_FilterDirection: 572 imageIncrement[0] = 1.0f / texture->width(); 573 break; 574 case GrSamplerState::kY_FilterDirection: 575 imageIncrement[1] = 1.0f / texture->height(); 576 break; 577 default: 578 GrCrash("Unknown filter direction."); 579 } 580 GL_CALL(Uniform2fv(imageIncrementUni, 1, imageIncrement)); 581 } 582 } 583 flushTexelSize(int s)584 void GrGpuGLShaders::flushTexelSize(int s) { 585 const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni; 586 if (GrGLProgram::kUnusedUniform != uni) { 587 const GrGLTexture* texture = 588 static_cast<const GrGLTexture*>(this->getDrawState().getTexture(s)); 589 if (texture->width() != fProgramData->fTextureWidth[s] || 590 texture->height() != fProgramData->fTextureHeight[s]) { 591 592 float texelSize[] = {1.f / texture->width(), 593 1.f / texture->height()}; 594 GL_CALL(Uniform2fv(uni, 1, texelSize)); 595 fProgramData->fTextureWidth[s] = texture->width(); 596 fProgramData->fTextureHeight[s] = texture->height(); 597 } 598 } 599 } 600 flushEdgeAAData()601 void GrGpuGLShaders::flushEdgeAAData() { 602 const int& uni = fProgramData->fUniLocations.fEdgesUni; 603 if (GrGLProgram::kUnusedUniform != uni) { 604 int count = this->getDrawState().getNumAAEdges(); 605 GrDrawState::Edge edges[GrDrawState::kMaxEdges]; 606 // Flip the edges in Y 607 float height = 608 static_cast<float>(this->getDrawState().getRenderTarget()->height()); 609 for (int i = 0; i < count; ++i) { 610 edges[i] = this->getDrawState().getAAEdges()[i]; 611 float b = edges[i].fY; 612 edges[i].fY = -b; 613 edges[i].fZ += b * height; 614 } 615 GL_CALL(Uniform3fv(uni, count, &edges[0].fX)); 616 } 617 } 618 flushColorMatrix()619 void GrGpuGLShaders::flushColorMatrix() { 620 const ProgramDesc& desc = fCurrentProgram.getDesc(); 621 int matrixUni = fProgramData->fUniLocations.fColorMatrixUni; 622 int vecUni = fProgramData->fUniLocations.fColorMatrixVecUni; 623 if (GrGLProgram::kUnusedUniform != matrixUni 624 && GrGLProgram::kUnusedUniform != vecUni) { 625 const float* m = this->getDrawState().getColorMatrix(); 626 GrGLfloat mt[] = { 627 m[0], m[5], m[10], m[15], 628 m[1], m[6], m[11], m[16], 629 m[2], m[7], m[12], m[17], 630 m[3], m[8], m[13], m[18], 631 }; 632 static float scale = 1.0f / 255.0f; 633 GrGLfloat vec[] = { 634 m[4] * scale, m[9] * scale, m[14] * scale, m[19] * scale, 635 }; 636 GL_CALL(UniformMatrix4fv(matrixUni, 1, false, mt)); 637 GL_CALL(Uniform4fv(vecUni, 1, vec)); 638 } 639 } 640 641 static const float ONE_OVER_255 = 1.f / 255.f; 642 643 #define GR_COLOR_TO_VEC4(color) {\ 644 GrColorUnpackR(color) * ONE_OVER_255,\ 645 GrColorUnpackG(color) * ONE_OVER_255,\ 646 GrColorUnpackB(color) * ONE_OVER_255,\ 647 GrColorUnpackA(color) * ONE_OVER_255 \ 648 } 649 flushColor(GrColor color)650 void GrGpuGLShaders::flushColor(GrColor color) { 651 const ProgramDesc& desc = fCurrentProgram.getDesc(); 652 const GrDrawState& drawState = this->getDrawState(); 653 654 if (this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit) { 655 // color will be specified per-vertex as an attribute 656 // invalidate the const vertex attrib color 657 fHWDrawState.setColor(GrColor_ILLEGAL); 658 } else { 659 switch (desc.fColorInput) { 660 case ProgramDesc::kAttribute_ColorInput: 661 if (fHWDrawState.getColor() != color) { 662 // OpenGL ES only supports the float varieties of 663 // glVertexAttrib 664 float c[] = GR_COLOR_TO_VEC4(color); 665 GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), 666 c)); 667 fHWDrawState.setColor(color); 668 } 669 break; 670 case ProgramDesc::kUniform_ColorInput: 671 if (fProgramData->fColor != color) { 672 // OpenGL ES doesn't support unsigned byte varieties of 673 // glUniform 674 float c[] = GR_COLOR_TO_VEC4(color); 675 GrAssert(GrGLProgram::kUnusedUniform != 676 fProgramData->fUniLocations.fColorUni); 677 GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorUni, 678 1, c)); 679 fProgramData->fColor = color; 680 } 681 break; 682 case ProgramDesc::kSolidWhite_ColorInput: 683 case ProgramDesc::kTransBlack_ColorInput: 684 break; 685 default: 686 GrCrash("Unknown color type."); 687 } 688 } 689 if (fProgramData->fUniLocations.fColorFilterUni 690 != GrGLProgram::kUnusedUniform 691 && fProgramData->fColorFilterColor 692 != drawState.getColorFilterColor()) { 693 float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor()); 694 GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c)); 695 fProgramData->fColorFilterColor = drawState.getColorFilterColor(); 696 } 697 } 698 flushCoverage(GrColor coverage)699 void GrGpuGLShaders::flushCoverage(GrColor coverage) { 700 const ProgramDesc& desc = fCurrentProgram.getDesc(); 701 const GrDrawState& drawState = this->getDrawState(); 702 703 704 if (this->getGeomSrc().fVertexLayout & kCoverage_VertexLayoutBit) { 705 // coverage will be specified per-vertex as an attribute 706 // invalidate the const vertex attrib coverage 707 fHWDrawState.setCoverage4(GrColor_ILLEGAL); 708 } else { 709 switch (desc.fCoverageInput) { 710 case ProgramDesc::kAttribute_ColorInput: 711 if (fHWDrawState.getCoverage() != coverage) { 712 // OpenGL ES only supports the float varieties of 713 // glVertexAttrib 714 float c[] = GR_COLOR_TO_VEC4(coverage); 715 GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(), 716 c)); 717 fHWDrawState.setCoverage(coverage); 718 } 719 break; 720 case ProgramDesc::kUniform_ColorInput: 721 if (fProgramData->fCoverage != coverage) { 722 // OpenGL ES doesn't support unsigned byte varieties of 723 // glUniform 724 float c[] = GR_COLOR_TO_VEC4(coverage); 725 GrAssert(GrGLProgram::kUnusedUniform != 726 fProgramData->fUniLocations.fCoverageUni); 727 GL_CALL(Uniform4fv(fProgramData->fUniLocations.fCoverageUni, 728 1, c)); 729 fProgramData->fCoverage = coverage; 730 } 731 break; 732 case ProgramDesc::kSolidWhite_ColorInput: 733 case ProgramDesc::kTransBlack_ColorInput: 734 break; 735 default: 736 GrCrash("Unknown coverage type."); 737 } 738 } 739 } 740 flushGraphicsState(GrPrimitiveType type)741 bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { 742 if (!flushGLStateCommon(type)) { 743 return false; 744 } 745 746 const GrDrawState& drawState = this->getDrawState(); 747 748 if (fDirtyFlags.fRenderTargetChanged) { 749 // our coords are in pixel space and the GL matrices map to NDC 750 // so if the viewport changed, our matrix is now wrong. 751 fHWDrawState.setViewMatrix(GrMatrix::InvalidMatrix()); 752 // we assume all shader matrices may be wrong after viewport changes 753 fProgramCache->invalidateViewMatrices(); 754 } 755 756 GrBlendCoeff srcCoeff; 757 GrBlendCoeff dstCoeff; 758 BlendOptFlags blendOpts = this->getBlendOpts(false, &srcCoeff, &dstCoeff); 759 if (kSkipDraw_BlendOptFlag & blendOpts) { 760 return false; 761 } 762 763 this->buildProgram(type, blendOpts, dstCoeff); 764 fProgramData = fProgramCache->getProgramData(fCurrentProgram); 765 if (NULL == fProgramData) { 766 GrAssert(!"Failed to create program!"); 767 return false; 768 } 769 770 if (fHWProgramID != fProgramData->fProgramID) { 771 GL_CALL(UseProgram(fProgramData->fProgramID)); 772 fHWProgramID = fProgramData->fProgramID; 773 } 774 fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff); 775 this->flushBlend(type, srcCoeff, dstCoeff); 776 777 GrColor color; 778 GrColor coverage; 779 if (blendOpts & kEmitTransBlack_BlendOptFlag) { 780 color = 0; 781 coverage = 0; 782 } else if (blendOpts & kEmitCoverage_BlendOptFlag) { 783 color = 0xffffffff; 784 coverage = drawState.getCoverage(); 785 } else { 786 color = drawState.getColor(); 787 coverage = drawState.getCoverage(); 788 } 789 this->flushColor(color); 790 this->flushCoverage(coverage); 791 792 this->flushViewMatrix(); 793 794 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 795 if (this->isStageEnabled(s)) { 796 this->flushTextureMatrix(s); 797 798 this->flushRadial2(s); 799 800 this->flushConvolution(s); 801 802 this->flushTexelSize(s); 803 804 this->flushTextureDomain(s); 805 } 806 } 807 this->flushEdgeAAData(); 808 this->flushColorMatrix(); 809 resetDirtyFlags(); 810 return true; 811 } 812 postDraw()813 void GrGpuGLShaders::postDraw() { 814 } 815 setupGeometry(int * startVertex,int * startIndex,int vertexCount,int indexCount)816 void GrGpuGLShaders::setupGeometry(int* startVertex, 817 int* startIndex, 818 int vertexCount, 819 int indexCount) { 820 821 int newColorOffset; 822 int newCoverageOffset; 823 int newTexCoordOffsets[GrDrawState::kMaxTexCoords]; 824 int newEdgeOffset; 825 826 GrGLsizei newStride = VertexSizeAndOffsetsByIdx( 827 this->getGeomSrc().fVertexLayout, 828 newTexCoordOffsets, 829 &newColorOffset, 830 &newCoverageOffset, 831 &newEdgeOffset); 832 int oldColorOffset; 833 int oldCoverageOffset; 834 int oldTexCoordOffsets[GrDrawState::kMaxTexCoords]; 835 int oldEdgeOffset; 836 837 GrGLsizei oldStride = VertexSizeAndOffsetsByIdx( 838 fHWGeometryState.fVertexLayout, 839 oldTexCoordOffsets, 840 &oldColorOffset, 841 &oldCoverageOffset, 842 &oldEdgeOffset); 843 bool indexed = NULL != startIndex; 844 845 int extraVertexOffset; 846 int extraIndexOffset; 847 this->setBuffers(indexed, &extraVertexOffset, &extraIndexOffset); 848 849 GrGLenum scalarType; 850 bool texCoordNorm; 851 if (this->getGeomSrc().fVertexLayout & kTextFormat_VertexLayoutBit) { 852 scalarType = GrGLTextType; 853 texCoordNorm = GR_GL_TEXT_TEXTURE_NORMALIZED; 854 } else { 855 scalarType = GrGLType; 856 texCoordNorm = false; 857 } 858 859 size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride; 860 *startVertex = 0; 861 if (indexed) { 862 *startIndex += extraIndexOffset; 863 } 864 865 // all the Pointers must be set if any of these are true 866 bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty || 867 vertexOffset != fHWGeometryState.fVertexOffset || 868 newStride != oldStride; 869 870 // position and tex coord offsets change if above conditions are true 871 // or the type/normalization changed based on text vs nontext type coords. 872 bool posAndTexChange = allOffsetsChange || 873 (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) && 874 (kTextFormat_VertexLayoutBit & 875 (fHWGeometryState.fVertexLayout ^ 876 this->getGeomSrc().fVertexLayout))); 877 878 if (posAndTexChange) { 879 int idx = GrGLProgram::PositionAttributeIdx(); 880 GL_CALL(VertexAttribPointer(idx, 2, scalarType, false, newStride, 881 (GrGLvoid*)vertexOffset)); 882 fHWGeometryState.fVertexOffset = vertexOffset; 883 } 884 885 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) { 886 if (newTexCoordOffsets[t] > 0) { 887 GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffsets[t]); 888 int idx = GrGLProgram::TexCoordAttributeIdx(t); 889 if (oldTexCoordOffsets[t] <= 0) { 890 GL_CALL(EnableVertexAttribArray(idx)); 891 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, 892 newStride, texCoordOffset)); 893 } else if (posAndTexChange || 894 newTexCoordOffsets[t] != oldTexCoordOffsets[t]) { 895 GL_CALL(VertexAttribPointer(idx, 2, scalarType, texCoordNorm, 896 newStride, texCoordOffset)); 897 } 898 } else if (oldTexCoordOffsets[t] > 0) { 899 GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx(t))); 900 } 901 } 902 903 if (newColorOffset > 0) { 904 GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset); 905 int idx = GrGLProgram::ColorAttributeIdx(); 906 if (oldColorOffset <= 0) { 907 GL_CALL(EnableVertexAttribArray(idx)); 908 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 909 true, newStride, colorOffset)); 910 } else if (allOffsetsChange || newColorOffset != oldColorOffset) { 911 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 912 true, newStride, colorOffset)); 913 } 914 } else if (oldColorOffset > 0) { 915 GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx())); 916 } 917 918 if (newCoverageOffset > 0) { 919 GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset); 920 int idx = GrGLProgram::CoverageAttributeIdx(); 921 if (oldCoverageOffset <= 0) { 922 GL_CALL(EnableVertexAttribArray(idx)); 923 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 924 true, newStride, coverageOffset)); 925 } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) { 926 GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, 927 true, newStride, coverageOffset)); 928 } 929 } else if (oldCoverageOffset > 0) { 930 GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx())); 931 } 932 933 if (newEdgeOffset > 0) { 934 GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset); 935 int idx = GrGLProgram::EdgeAttributeIdx(); 936 if (oldEdgeOffset <= 0) { 937 GL_CALL(EnableVertexAttribArray(idx)); 938 GL_CALL(VertexAttribPointer(idx, 4, scalarType, 939 false, newStride, edgeOffset)); 940 } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) { 941 GL_CALL(VertexAttribPointer(idx, 4, scalarType, 942 false, newStride, edgeOffset)); 943 } 944 } else if (oldEdgeOffset > 0) { 945 GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx())); 946 } 947 948 fHWGeometryState.fVertexLayout = this->getGeomSrc().fVertexLayout; 949 fHWGeometryState.fArrayPtrsDirty = false; 950 } 951 buildProgram(GrPrimitiveType type,BlendOptFlags blendOpts,GrBlendCoeff dstCoeff)952 void GrGpuGLShaders::buildProgram(GrPrimitiveType type, 953 BlendOptFlags blendOpts, 954 GrBlendCoeff dstCoeff) { 955 ProgramDesc& desc = fCurrentProgram.fProgramDesc; 956 const GrDrawState& drawState = this->getDrawState(); 957 958 // This should already have been caught 959 GrAssert(!(kSkipDraw_BlendOptFlag & blendOpts)); 960 961 bool skipCoverage = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag); 962 963 bool skipColor = SkToBool(blendOpts & (kEmitTransBlack_BlendOptFlag | 964 kEmitCoverage_BlendOptFlag)); 965 966 // The descriptor is used as a cache key. Thus when a field of the 967 // descriptor will not affect program generation (because of the vertex 968 // layout in use or other descriptor field settings) it should be set 969 // to a canonical value to avoid duplicate programs with different keys. 970 971 // Must initialize all fields or cache will have false negatives! 972 desc.fVertexLayout = this->getGeomSrc().fVertexLayout; 973 974 desc.fEmitsPointSize = kPoints_PrimitiveType == type; 975 976 bool requiresAttributeColors = 977 !skipColor && SkToBool(desc.fVertexLayout & kColor_VertexLayoutBit); 978 bool requiresAttributeCoverage = 979 !skipCoverage && SkToBool(desc.fVertexLayout & 980 kCoverage_VertexLayoutBit); 981 982 // fColorInput/fCoverageInput records how colors are specified for the. 983 // program. So we strip the bits from the layout to avoid false negatives 984 // when searching for an existing program in the cache. 985 desc.fVertexLayout &= ~(kColor_VertexLayoutBit | kCoverage_VertexLayoutBit); 986 987 desc.fColorFilterXfermode = skipColor ? 988 SkXfermode::kDst_Mode : 989 drawState.getColorFilterMode(); 990 991 desc.fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit); 992 993 // no reason to do edge aa or look at per-vertex coverage if coverage is 994 // ignored 995 if (skipCoverage) { 996 desc.fVertexLayout &= ~(kEdge_VertexLayoutBit | 997 kCoverage_VertexLayoutBit); 998 } 999 1000 bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag); 1001 bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) || 1002 (!requiresAttributeColors && 1003 0xffffffff == drawState.getColor()); 1004 if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) { 1005 desc.fColorInput = ProgramDesc::kTransBlack_ColorInput; 1006 } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) { 1007 desc.fColorInput = ProgramDesc::kSolidWhite_ColorInput; 1008 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) { 1009 desc.fColorInput = ProgramDesc::kUniform_ColorInput; 1010 } else { 1011 desc.fColorInput = ProgramDesc::kAttribute_ColorInput; 1012 } 1013 1014 bool covIsSolidWhite = !requiresAttributeCoverage && 1015 0xffffffff == drawState.getCoverage(); 1016 1017 if (skipCoverage) { 1018 desc.fCoverageInput = ProgramDesc::kTransBlack_ColorInput; 1019 } else if (covIsSolidWhite) { 1020 desc.fCoverageInput = ProgramDesc::kSolidWhite_ColorInput; 1021 } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) { 1022 desc.fCoverageInput = ProgramDesc::kUniform_ColorInput; 1023 } else { 1024 desc.fCoverageInput = ProgramDesc::kAttribute_ColorInput; 1025 } 1026 1027 desc.fEdgeAANumEdges = skipCoverage ? 0 : drawState.getNumAAEdges(); 1028 desc.fEdgeAAConcave = desc.fEdgeAANumEdges > 0 && 1029 drawState.isConcaveEdgeAAState(); 1030 1031 int lastEnabledStage = -1; 1032 1033 if (!skipCoverage && (desc.fVertexLayout & 1034 GrDrawTarget::kEdge_VertexLayoutBit)) { 1035 desc.fVertexEdgeType = drawState.getVertexEdgeType(); 1036 } else { 1037 // use canonical value when not set to avoid cache misses 1038 desc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; 1039 } 1040 1041 for (int s = 0; s < GrDrawState::kNumStages; ++s) { 1042 StageDesc& stage = desc.fStages[s]; 1043 1044 stage.fOptFlags = 0; 1045 stage.setEnabled(this->isStageEnabled(s)); 1046 1047 bool skip = s < drawState.getFirstCoverageStage() ? skipColor : 1048 skipCoverage; 1049 1050 if (!skip && stage.isEnabled()) { 1051 lastEnabledStage = s; 1052 const GrGLTexture* texture = 1053 static_cast<const GrGLTexture*>(drawState.getTexture(s)); 1054 GrAssert(NULL != texture); 1055 const GrSamplerState& sampler = drawState.getSampler(s); 1056 // we matrix to invert when orientation is TopDown, so make sure 1057 // we aren't in that case before flagging as identity. 1058 if (TextureMatrixIsIdentity(texture, sampler)) { 1059 stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit; 1060 } else if (!sampler.getMatrix().hasPerspective()) { 1061 stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; 1062 } 1063 switch (sampler.getSampleMode()) { 1064 case GrSamplerState::kNormal_SampleMode: 1065 stage.fCoordMapping = StageDesc::kIdentity_CoordMapping; 1066 break; 1067 case GrSamplerState::kRadial_SampleMode: 1068 stage.fCoordMapping = StageDesc::kRadialGradient_CoordMapping; 1069 break; 1070 case GrSamplerState::kRadial2_SampleMode: 1071 if (sampler.radial2IsDegenerate()) { 1072 stage.fCoordMapping = 1073 StageDesc::kRadial2GradientDegenerate_CoordMapping; 1074 } else { 1075 stage.fCoordMapping = 1076 StageDesc::kRadial2Gradient_CoordMapping; 1077 } 1078 break; 1079 case GrSamplerState::kSweep_SampleMode: 1080 stage.fCoordMapping = StageDesc::kSweepGradient_CoordMapping; 1081 break; 1082 default: 1083 GrCrash("Unexpected sample mode!"); 1084 break; 1085 } 1086 1087 switch (sampler.getFilter()) { 1088 // these both can use a regular texture2D() 1089 case GrSamplerState::kNearest_Filter: 1090 case GrSamplerState::kBilinear_Filter: 1091 stage.fFetchMode = StageDesc::kSingle_FetchMode; 1092 break; 1093 // performs 4 texture2D()s 1094 case GrSamplerState::k4x4Downsample_Filter: 1095 stage.fFetchMode = StageDesc::k2x2_FetchMode; 1096 break; 1097 // performs fKernelWidth texture2D()s 1098 case GrSamplerState::kConvolution_Filter: 1099 stage.fFetchMode = StageDesc::kConvolution_FetchMode; 1100 break; 1101 case GrSamplerState::kDilate_Filter: 1102 stage.fFetchMode = StageDesc::kDilate_FetchMode; 1103 break; 1104 case GrSamplerState::kErode_Filter: 1105 stage.fFetchMode = StageDesc::kErode_FetchMode; 1106 break; 1107 default: 1108 GrCrash("Unexpected filter!"); 1109 break; 1110 } 1111 1112 if (sampler.hasTextureDomain()) { 1113 GrAssert(GrSamplerState::kClamp_WrapMode == 1114 sampler.getWrapX() && 1115 GrSamplerState::kClamp_WrapMode == 1116 sampler.getWrapY()); 1117 stage.fOptFlags |= StageDesc::kCustomTextureDomain_OptFlagBit; 1118 } 1119 1120 stage.fInConfigFlags = 0; 1121 if (!this->glCaps().textureSwizzleSupport()) { 1122 if (GrPixelConfigIsAlphaOnly(texture->config())) { 1123 // if we don't have texture swizzle support then 1124 // the shader must do an alpha smear after reading 1125 // the texture 1126 stage.fInConfigFlags |= StageDesc::kSmearAlpha_InConfigFlag; 1127 } else if (sampler.swapsRAndB()) { 1128 stage.fInConfigFlags |= StageDesc::kSwapRAndB_InConfigFlag; 1129 } 1130 } 1131 if (GrPixelConfigIsUnpremultiplied(texture->config())) { 1132 // The shader generator assumes that color channels are bytes 1133 // when rounding. 1134 GrAssert(4 == GrBytesPerPixel(texture->config())); 1135 if (kUpOnWrite_DownOnRead_UnpremulConversion == 1136 fUnpremulConversion) { 1137 stage.fInConfigFlags |= 1138 StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag; 1139 } else { 1140 stage.fInConfigFlags |= 1141 StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag; 1142 } 1143 } 1144 1145 if (sampler.getFilter() == GrSamplerState::kConvolution_Filter || 1146 sampler.getFilter() == GrSamplerState::kDilate_Filter || 1147 sampler.getFilter() == GrSamplerState::kErode_Filter) { 1148 stage.fKernelWidth = sampler.getKernelWidth(); 1149 } else { 1150 stage.fKernelWidth = 0; 1151 } 1152 } else { 1153 stage.fOptFlags = 0; 1154 stage.fCoordMapping = (StageDesc::CoordMapping) 0; 1155 stage.fInConfigFlags = 0; 1156 stage.fFetchMode = (StageDesc::FetchMode) 0; 1157 stage.fKernelWidth = 0; 1158 } 1159 } 1160 1161 if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) { 1162 // The shader generator assumes that color channels are bytes 1163 // when rounding. 1164 GrAssert(4 == GrBytesPerPixel(drawState.getRenderTarget()->config())); 1165 if (kUpOnWrite_DownOnRead_UnpremulConversion == fUnpremulConversion) { 1166 desc.fOutputConfig = 1167 ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig; 1168 } else { 1169 desc.fOutputConfig = 1170 ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig; 1171 } 1172 } else { 1173 desc.fOutputConfig = ProgramDesc::kPremultiplied_OutputConfig; 1174 } 1175 1176 desc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput; 1177 1178 // currently the experimental GS will only work with triangle prims 1179 // (and it doesn't do anything other than pass through values from 1180 // the VS to the FS anyway). 1181 #if 0 && GR_GL_EXPERIMENTAL_GS 1182 desc.fExperimentalGS = this->getCaps().fGeometryShaderSupport; 1183 #endif 1184 1185 // we want to avoid generating programs with different "first cov stage" 1186 // values when they would compute the same result. 1187 // We set field in the desc to kNumStages when either there are no 1188 // coverage stages or the distinction between coverage and color is 1189 // immaterial. 1190 int firstCoverageStage = GrDrawState::kNumStages; 1191 desc.fFirstCoverageStage = GrDrawState::kNumStages; 1192 bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage; 1193 if (hasCoverage) { 1194 firstCoverageStage = drawState.getFirstCoverageStage(); 1195 } 1196 1197 // other coverage inputs 1198 if (!hasCoverage) { 1199 hasCoverage = 1200 desc.fEdgeAANumEdges || 1201 requiresAttributeCoverage || 1202 (desc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit); 1203 } 1204 1205 if (hasCoverage) { 1206 // color filter is applied between color/coverage computation 1207 if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) { 1208 desc.fFirstCoverageStage = firstCoverageStage; 1209 } 1210 1211 if (this->getCaps().fDualSourceBlendingSupport && 1212 !(blendOpts & (kEmitCoverage_BlendOptFlag | 1213 kCoverageAsAlpha_BlendOptFlag))) { 1214 if (kZero_BlendCoeff == dstCoeff) { 1215 // write the coverage value to second color 1216 desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput; 1217 desc.fFirstCoverageStage = firstCoverageStage; 1218 } else if (kSA_BlendCoeff == dstCoeff) { 1219 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially 1220 // cover 1221 desc.fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput; 1222 desc.fFirstCoverageStage = firstCoverageStage; 1223 } else if (kSC_BlendCoeff == dstCoeff) { 1224 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially 1225 // cover 1226 desc.fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput; 1227 desc.fFirstCoverageStage = firstCoverageStage; 1228 } 1229 } 1230 } 1231 } 1232