void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) const { if (fHasCustomColorOutput) { GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); } if (fHasSecondaryOutput) { GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); } }
void GrGLFragmentShaderBuilder::enableCustomOutput() { if (!fHasCustomColorOutput) { fHasCustomColorOutput = true; fCustomColorOutputIndex = fOutputs.count(); fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier, declared_color_output_name()); } }
void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) { const GrGLCaps& caps = fProgramBuilder->gpu()->glCaps(); if (fHasCustomColorOutput && caps.bindFragDataLocationSupport()) { GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name())); } if (fHasSecondaryOutput && caps.glslCaps()->mustDeclareFragmentShaderOutput()) { GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, declared_secondary_color_output_name())); } }
void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) { // ES 3.00 requires custom color output but doesn't support bindFragDataLocation if (fHasCustomColorOutput && kGLES_GrGLStandard != fProgramBuilder->gpu()->ctxInfo().standard()) { GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name())); } if (fHasSecondaryOutput) { GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name())); } }
void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) { if (fHasCustomColorOutput) { GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); } if (fHasSecondaryOutput) { GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); } // skbug.com/2056 bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; if (usingBindUniform) { int count = fUniforms.count(); for (int i = 0; i < count; ++i) { GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str())); fUniforms[i].fLocation = i; } } }
const char* GrGLFragmentShaderBuilder::dstColor() { fHasReadDstColor = true; GrGLGpu* gpu = fProgramBuilder->gpu(); if (gpu->glCaps().glslCaps()->fbFetchSupport()) { this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), gpu->glCaps().glslCaps()->fbFetchExtensionString()); // Some versions of this extension string require declaring custom color output on ES 3.0+ const char* fbFetchColorName = gpu->glCaps().glslCaps()->fbFetchColorName(); if (gpu->glCaps().glslCaps()->fbFetchNeedsCustomOutput()) { this->enableCustomOutput(); fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier); fbFetchColorName = declared_color_output_name(); } return fbFetchColorName; } else { return kDstTextureColorName; } }
const char* GrGLFragmentShaderBuilder::dstColor() { fHasReadDstColor = true; GrGLGpu* gpu = fProgramBuilder->gpu(); if (gpu->glCaps().fbFetchSupport()) { this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), gpu->glCaps().fbFetchExtensionString()); // On ES 3.0 we have to declare this, and use the custom color output name const char* fbFetchColorName = gpu->glCaps().fbFetchColorName(); if (gpu->glslGeneration() >= k330_GrGLSLGeneration) { this->enableCustomOutput(); fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier); fbFetchColorName = declared_color_output_name(); } return fbFetchColorName; } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) { return kDstCopyColorName; } else { return ""; } }
bool GrGLShaderBuilder::genProgram(const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]) { const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader(); /////////////////////////////////////////////////////////////////////////// // emit code to read the dst copy texture, if necessary if (kNoDstRead_DstReadKey != header.fDstReadKey && !fGpu->glCaps().fbFetchSupport()) { bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); const char* dstCopyTopLeftName; const char* dstCopyCoordScaleName; const char* dstCopySamplerName; uint32_t configMask; if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { configMask = kA_GrColorComponentFlag; } else { configMask = kRGBA_GrColorComponentFlags; } fUniformHandles.fDstCopySamplerUni = this->addUniform(kFragment_Visibility, kSampler2D_GrSLType, "DstCopySampler", &dstCopySamplerName); fUniformHandles.fDstCopyTopLeftUni = this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyUpperLeft", &dstCopyTopLeftName); fUniformHandles.fDstCopyScaleUni = this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyCoordScale", &dstCopyCoordScaleName); const char* fragPos = this->fragmentPosition(); this->fsCodeAppend("\t// Read color from copy of the destination.\n"); this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n", fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); if (!topDown) { this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); } this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName); append_texture_lookup(&fFSCode, fGpu, dstCopySamplerName, "_dstTexCoord", configMask, "rgba"); this->fsCodeAppend(";\n\n"); } /////////////////////////////////////////////////////////////////////////// // get the initial color and coverage to feed into the first effect in each effect chain GrGLSLExpr4 inputColor; GrGLSLExpr4 inputCoverage; if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { const char* name; fUniformHandles.fColorUni = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Color", &name); inputColor = GrGLSLExpr4(name); } if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { const char* name; fUniformHandles.fCoverageUni = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Coverage", &name); inputCoverage = GrGLSLExpr4(name); } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) { inputCoverage = GrGLSLExpr4(1); } if (k110_GrGLSLGeneration != fGpu->glslGeneration()) { fFSOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier, declared_color_output_name()); fHasCustomColorOutput = true; } this->emitCodeBeforeEffects(&inputColor, &inputCoverage); /////////////////////////////////////////////////////////////////////////// // emit the per-effect code for both color and coverage effects GrGLProgramDesc::EffectKeyProvider colorKeyProvider( &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType); fColorEffects.reset(this->createAndEmitEffects(colorStages, this->desc().numColorEffects(), colorKeyProvider, &inputColor)); GrGLProgramDesc::EffectKeyProvider coverageKeyProvider( &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType); fCoverageEffects.reset(this->createAndEmitEffects(coverageStages, this->desc().numCoverageEffects(), coverageKeyProvider, &inputCoverage)); this->emitCodeAfterEffects(); /////////////////////////////////////////////////////////////////////////// // write the secondary color output if necessary if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) { const char* secondaryOutputName = this->enableSecondaryOutput(); // default coeff to ones for kCoverage_DualSrcOutput GrGLSLExpr4 coeff(1); if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) { // Get (1-A) into coeff coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a()); } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput){ // Get (1-RGBA) into coeff coeff = GrGLSLExpr4(1) - inputColor; } // Get coeff * coverage into modulate and then write that to the dual source output. this->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str()); } /////////////////////////////////////////////////////////////////////////// // combine color and coverage as frag color // Get "color * coverage" into fragColor GrGLSLExpr4 fragColor = inputColor * inputCoverage; // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so. if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) { GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor()); fragColor = fragColor + dstContribution; } this->fsCodeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str()); if (!this->finish()) { return false; } return true; }
const char* GrGLShaderBuilder::getColorOutputName() const { return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; }
GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu, GrGLUniformManager& uniformManager, const GrGLProgramDesc& desc) : fGpu(gpu) , fUniformManager(uniformManager) , fFSFeaturesAddedMask(0) , fFSInputs(kVarsPerBlock) , fFSOutputs(kMaxFSOutputs) , fUniforms(kVarsPerBlock) , fSetupFragPosition(false) , fHasCustomColorOutput(false) , fHasSecondaryOutput(false) , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) { const GrGLProgramDesc::KeyHeader& header = desc.getHeader(); // Emit code to read the dst copy textue if necessary. if (kNoDstRead_DstReadKey != header.fDstReadKey && GrGLCaps::kNone_FBFetchType == fGpu->glCaps().fbFetchType()) { bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); const char* dstCopyTopLeftName; const char* dstCopyCoordScaleName; uint32_t configMask; if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { configMask = kA_GrColorComponentFlag; } else { configMask = kRGBA_GrColorComponentFlags; } fDstCopySamplerUniform = this->addUniform(kFragment_Visibility, kSampler2D_GrSLType, "DstCopySampler"); fDstCopyTopLeftUniform = this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyUpperLeft", &dstCopyTopLeftName); fDstCopyScaleUniform = this->addUniform(kFragment_Visibility, kVec2f_GrSLType, "DstCopyCoordScale", &dstCopyCoordScaleName); const char* fragPos = this->fragmentPosition(); this->fsCodeAppend("\t// Read color from copy of the destination.\n"); this->fsCodeAppendf("\tvec2 _dstTexCoord = (%s.xy - %s) * %s;\n", fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); if (!topDown) { this->fsCodeAppend("\t_dstTexCoord.y = 1.0 - _dstTexCoord.y;\n"); } this->fsCodeAppendf("\tvec4 %s = ", kDstCopyColorName); append_texture_lookup(&fFSCode, fGpu, this->getUniformCStr(fDstCopySamplerUniform), "_dstTexCoord", configMask, "rgba"); this->fsCodeAppend(";\n\n"); } if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) { const char* name; fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Color", &name); fInputColor = GrGLSLExpr4(name); } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) { fInputColor = GrGLSLExpr4(1); } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) { fInputColor = GrGLSLExpr4(0); } if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) { const char* name; fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec4f_GrSLType, "Coverage", &name); fInputCoverage = GrGLSLExpr4(name); } else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) { fInputCoverage = GrGLSLExpr4(1); } else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) { fInputCoverage = GrGLSLExpr4(0); } if (k110_GrGLSLGeneration != fGpu->glslGeneration()) { fFSOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier, declared_color_output_name()); fHasCustomColorOutput = true; } }