const char* GrGLShaderBuilder::fragmentPosition() { if (fCodeStage.inStageCode()) { const GrEffect* effect = fCodeStage.effectStage()->getEffect(); if (!effect->willReadFragmentPosition()) { SkDEBUGFAIL("GrGLEffect asked for frag position but its generating GrEffect " "did not request access."); return ""; } } // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the // declaration varies in earlier GLSL specs. So it is simpler to omit it. if (fTopLeftFragPosRead) { fSetupFragPosition = true; return "gl_FragCoord"; } else if (fGpu->glCaps().fragCoordConventionsSupport()) { if (!fSetupFragPosition) { if (fGpu->glslGeneration() < k150_GrGLSLGeneration) { this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature, "GL_ARB_fragment_coord_conventions"); } fFSInputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kIn_TypeModifier, "gl_FragCoord", GrGLShaderVar::kDefault_Precision, GrGLShaderVar::kUpperLeft_Origin); fSetupFragPosition = true; } return "gl_FragCoord"; } else { static const char* kCoordName = "fragCoordYDown"; if (!fSetupFragPosition) { // temporarily change the stage index because we're inserting non-stage code. CodeStage::AutoStageRestore csar(&fCodeStage, NULL); SkASSERT(!fUniformHandles.fRTHeightUni.isValid()); const char* rtHeightName; fUniformHandles.fRTHeightUni = this->addUniform(kFragment_Visibility, kFloat_GrSLType, "RTHeight", &rtHeightName); // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that // causes programs to fail to link. Making this function return a vec2() didn't fix the // problem but using 1.0 for the last two components does. this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, 1.0, " "1.0);\n", kCoordName, rtHeightName); fSetupFragPosition = true; } SkASSERT(fUniformHandles.fRTHeightUni.isValid()); return kCoordName; } }
const char* GrGLShaderBuilder::fragmentPosition() { if (fCodeStage.inStageCode()) { const GrEffectRef& effect = *fCodeStage.effectStage()->getEffect(); if (!effect->willReadFragmentPosition()) { GrDebugCrash("GrGLEffect asked for frag position but its generating GrEffect " "did not request access."); return ""; } } if (fTopLeftFragPosRead) { if (!fSetupFragPosition) { fFSInputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kIn_TypeModifier, "gl_FragCoord", GrGLShaderVar::kDefault_Precision); fSetupFragPosition = true; } return "gl_FragCoord"; } else if (fGpu->glCaps().fragCoordConventionsSupport()) { if (!fSetupFragPosition) { SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature)); fFSInputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kIn_TypeModifier, "gl_FragCoord", GrGLShaderVar::kDefault_Precision, GrGLShaderVar::kUpperLeft_Origin); fSetupFragPosition = true; } return "gl_FragCoord"; } else { static const char* kCoordName = "fragCoordYDown"; if (!fSetupFragPosition) { // temporarily change the stage index because we're inserting non-stage code. CodeStage::AutoStageRestore csar(&fCodeStage, NULL); SkASSERT(!fRTHeightUniform.isValid()); const char* rtHeightName; fRTHeightUniform = this->addUniform(kFragment_Visibility, kFloat_GrSLType, "RTHeight", &rtHeightName); this->fFSCode.prependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, gl_FragCoord.zw);\n", kCoordName, rtHeightName); fSetupFragPosition = true; } SkASSERT(fRTHeightUniform.isValid()); return kCoordName; } }
void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder, const GrEffectStage* effectStages[], int effectCnt, const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* fsInOutColor) { bool effectEmitted = false; GrGLSLExpr4 inColor = *fsInOutColor; GrGLSLExpr4 outColor; for (int e = 0; e < effectCnt; ++e) { SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect()); const GrEffectStage& stage = *effectStages[e]; CodeStage::AutoStageRestore csar(&fCodeStage, &stage); if (inColor.isZeros()) { SkString inColorName; // Effects have no way to communicate zeros, they treat an empty string as ones. this->nameVariable(&inColorName, '\0', "input"); this->fsCodeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str()); inColor = inColorName; } // create var to hold stage result SkString outColorName; this->nameVariable(&outColorName, '\0', "output"); this->fsCodeAppendf("\tvec4 %s;\n", outColorName.c_str()); outColor = outColorName; programEffectsBuilder->emitEffect(stage, keyProvider.get(e), outColor.c_str(), inColor.isOnes() ? NULL : inColor.c_str(), fCodeStage.stageIndex()); inColor = outColor; effectEmitted = true; } if (effectEmitted) { *fsInOutColor = outColor; } }