Implement support for dual source blending in ES
Use EXT_blend_func_extended to implement dual source blending in OpenGL ES. The extension is the ES version of ARB_blend_func_extended. The extension provides gl_SecondaryFragColorEXT for ES 2.0 contexts. The extension provides glBindFragDataLocationIndexed to bind a custom fragment shader output to the secondary color for ES 3.0 contexts. For ES 3.1 contexts, the extension would also give "layout (location=0, index=1)" output varible layout modifier syntax, but it is not used in this patch. The extension needs #extension GL_EXT_blend_func_extended : require directive for the variables to be available in ES 2.0. For ES 3.0, the directive relaxes the rules for the amount of output variables without layout location qualifiers. OpenGL continues to use GL_ARB_blend_func_extended for dual source blending. Review URL: https://codereview.chromium.org/1266773003
This commit is contained in:
parent
bf49e46aca
commit
d94708e71e
@ -497,6 +497,11 @@ const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get) {
|
||||
GET_PROC(BindTexture);
|
||||
GET_PROC_SUFFIX(BindVertexArray, OES);
|
||||
|
||||
if (version >= GR_GL_VER(3,0) && extensions.has("GL_EXT_blend_func_extended")) {
|
||||
GET_PROC_SUFFIX(BindFragDataLocation, EXT);
|
||||
GET_PROC_SUFFIX(BindFragDataLocationIndexed, EXT);
|
||||
}
|
||||
|
||||
if (extensions.has("GL_KHR_blend_equation_advanced")) {
|
||||
GET_PROC_SUFFIX(BlendBarrier, KHR);
|
||||
} else if (extensions.has("GL_NV_blend_equation_advanced")) {
|
||||
|
@ -294,8 +294,14 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
|
||||
fMultisampleDisableSupport = ctxInfo.hasExtension("GL_EXT_multisample_compatibility");
|
||||
}
|
||||
|
||||
if (kGL_GrGLStandard == standard && version >= GR_GL_VER(3, 0)) {
|
||||
fBindFragDataLocationSupport = true;
|
||||
if (kGL_GrGLStandard == standard) {
|
||||
if (version >= GR_GL_VER(3, 0)) {
|
||||
fBindFragDataLocationSupport = true;
|
||||
}
|
||||
} else {
|
||||
if (version >= GR_GL_VER(3, 0) && ctxInfo.hasExtension("GL_EXT_blend_func_extended")) {
|
||||
fBindFragDataLocationSupport = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
@ -318,6 +324,8 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
|
||||
ctxInfo.glslGeneration() >= k150_GrGLSLGeneration;
|
||||
}
|
||||
else {
|
||||
glslCaps->fDualSourceBlendingSupport = ctxInfo.hasExtension("GL_EXT_blend_func_extended");
|
||||
|
||||
glslCaps->fShaderDerivativeSupport = ctxInfo.version() >= GR_GL_VER(3, 0) ||
|
||||
ctxInfo.hasExtension("GL_OES_standard_derivatives");
|
||||
}
|
||||
|
@ -390,13 +390,22 @@ bool GrGLInterface::validate() const {
|
||||
}
|
||||
|
||||
// Dual source blending
|
||||
if (kGL_GrGLStandard == fStandard &&
|
||||
(glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended"))) {
|
||||
if (NULL == fFunctions.fBindFragDataLocationIndexed) {
|
||||
RETURN_FALSE_INTERFACE
|
||||
if (kGL_GrGLStandard == fStandard) {
|
||||
if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended")) {
|
||||
if (NULL == fFunctions.fBindFragDataLocationIndexed) {
|
||||
RETURN_FALSE_INTERFACE
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (glVer >= GR_GL_VER(3,0) && fExtensions.has("GL_EXT_blend_func_extended")) {
|
||||
if (NULL == fFunctions.fBindFragDataLocation ||
|
||||
NULL == fFunctions.fBindFragDataLocationIndexed) {
|
||||
RETURN_FALSE_INTERFACE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// glGetStringi was added in version 3.0 of both desktop and ES.
|
||||
if (glVer >= GR_GL_VER(3, 0)) {
|
||||
if (NULL == fFunctions.fGetStringi) {
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
const char* GrGLFragmentShaderBuilder::kDstTextureColorName = "_dstColor";
|
||||
static const char* declared_color_output_name() { return "fsColorOut"; }
|
||||
static const char* dual_source_output_name() { return "dualSourceOut"; }
|
||||
static const char* declared_secondary_color_output_name() { return "fsSecondaryColorOut"; }
|
||||
|
||||
static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
|
||||
SkASSERT(GrBlendEquationIsAdvanced(equation));
|
||||
@ -240,8 +240,19 @@ void GrGLFragmentShaderBuilder::enableCustomOutput() {
|
||||
void GrGLFragmentShaderBuilder::enableSecondaryOutput() {
|
||||
SkASSERT(!fHasSecondaryOutput);
|
||||
fHasSecondaryOutput = true;
|
||||
fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier,
|
||||
dual_source_output_name());
|
||||
if (kGLES_GrGLStandard == fProgramBuilder->gpu()->ctxInfo().standard()) {
|
||||
this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, "GL_EXT_blend_func_extended");
|
||||
}
|
||||
|
||||
// If the primary output is declared, we must declare also the secondary output
|
||||
// and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom
|
||||
// output. The condition also co-incides with the condition in whici GLES SL 2.0
|
||||
// requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output.
|
||||
const GrGLSLCaps& caps = *fProgramBuilder->gpu()->glCaps().glslCaps();
|
||||
if (caps.mustDeclareFragmentShaderOutput()) {
|
||||
fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier,
|
||||
declared_secondary_color_output_name());
|
||||
}
|
||||
}
|
||||
|
||||
const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const {
|
||||
@ -249,7 +260,9 @@ const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const {
|
||||
}
|
||||
|
||||
const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const {
|
||||
return dual_source_output_name();
|
||||
const GrGLSLCaps& caps = *fProgramBuilder->gpu()->glCaps().glslCaps();
|
||||
return caps.mustDeclareFragmentShaderOutput() ? declared_secondary_color_output_name()
|
||||
: "gl_SecondaryFragColorEXT";
|
||||
}
|
||||
|
||||
bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
@ -270,11 +283,13 @@ bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
|
||||
}
|
||||
|
||||
void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) {
|
||||
if (fHasCustomColorOutput && fProgramBuilder->gpu()->glCaps().bindFragDataLocationSupport()) {
|
||||
const GrGLCaps& caps = fProgramBuilder->gpu()->glCaps();
|
||||
if (fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
|
||||
GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name()));
|
||||
}
|
||||
if (fHasSecondaryOutput) {
|
||||
GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name()));
|
||||
if (fHasSecondaryOutput && caps.glslCaps()->mustDeclareFragmentShaderOutput()) {
|
||||
GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
|
||||
declared_secondary_color_output_name()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,8 @@ private:
|
||||
enum GLSLPrivateFeature {
|
||||
kFragCoordConventions_GLSLPrivateFeature = kLastGLSLFeature + 1,
|
||||
kBlendEquationAdvanced_GLSLPrivateFeature,
|
||||
kLastGLSLPrivateFeature = kBlendEquationAdvanced_GLSLPrivateFeature
|
||||
kBlendFuncExtended_GLSLPrivateFeature,
|
||||
kLastGLSLPrivateFeature = kBlendFuncExtended_GLSLPrivateFeature
|
||||
};
|
||||
|
||||
// Interpretation of DstReadKey when generating code
|
||||
|
Loading…
Reference in New Issue
Block a user