static void blend_func_separate(struct gl_context *ctx, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA) { FLUSH_VERTICES(ctx, ctx->DriverFlags.NewBlend ? 0 : _NEW_COLOR); ctx->NewDriverState |= ctx->DriverFlags.NewBlend; const unsigned numBuffers = num_buffers(ctx); for (unsigned buf = 0; buf < numBuffers; buf++) { ctx->Color.Blend[buf].SrcRGB = sfactorRGB; ctx->Color.Blend[buf].DstRGB = dfactorRGB; ctx->Color.Blend[buf].SrcA = sfactorA; ctx->Color.Blend[buf].DstA = dfactorA; } update_uses_dual_src(ctx, 0); for (unsigned buf = 1; buf < numBuffers; buf++) { ctx->Color.Blend[buf]._UsesDualSrc = ctx->Color.Blend[0]._UsesDualSrc; } ctx->Color._BlendFuncPerBuffer = GL_FALSE; if (ctx->Driver.BlendFuncSeparate) { ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA); } }
/* Returns true if there was no change */ static bool skip_blend_state_update(const struct gl_context *ctx, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA) { /* Check if we're really changing any state. If not, return early. */ if (ctx->Color._BlendFuncPerBuffer) { const unsigned numBuffers = num_buffers(ctx); /* Check all per-buffer states */ for (unsigned buf = 0; buf < numBuffers; buf++) { if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB || ctx->Color.Blend[buf].DstRGB != dfactorRGB || ctx->Color.Blend[buf].SrcA != sfactorA || ctx->Color.Blend[buf].DstA != dfactorA) { return false; } } } else { /* only need to check 0th per-buffer state */ if (ctx->Color.Blend[0].SrcRGB != sfactorRGB || ctx->Color.Blend[0].DstRGB != dfactorRGB || ctx->Color.Blend[0].SrcA != sfactorA || ctx->Color.Blend[0].DstA != dfactorA) { return false; } } return true; }
/* This is really an extension function! */ void GLAPIENTRY _mesa_BlendEquation( GLenum mode ) { GET_CURRENT_CONTEXT(ctx); const unsigned numBuffers = num_buffers(ctx); unsigned buf; bool changed = false; enum gl_advanced_blend_mode advanced_mode = advanced_blend_mode(ctx, mode); if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBlendEquation(%s)\n", _mesa_enum_to_string(mode)); if (ctx->Color._BlendEquationPerBuffer) { /* Check all per-buffer states */ for (buf = 0; buf < numBuffers; buf++) { if (ctx->Color.Blend[buf].EquationRGB != mode || ctx->Color.Blend[buf].EquationA != mode) { changed = true; break; } } } else { /* only need to check 0th per-buffer state */ if (ctx->Color.Blend[0].EquationRGB != mode || ctx->Color.Blend[0].EquationA != mode) { changed = true; } } if (!changed) return; if (!legal_simple_blend_equation(ctx, mode) && !advanced_mode) { _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); return; } FLUSH_VERTICES(ctx, _NEW_COLOR); for (buf = 0; buf < numBuffers; buf++) { ctx->Color.Blend[buf].EquationRGB = mode; ctx->Color.Blend[buf].EquationA = mode; } ctx->Color._BlendEquationPerBuffer = GL_FALSE; ctx->Color._AdvancedBlendMode = advanced_mode; if (ctx->Driver.BlendEquationSeparate) ctx->Driver.BlendEquationSeparate(ctx, mode, mode); }
void GLAPIENTRY _mesa_BlendEquationSeparate( GLenum modeRGB, GLenum modeA ) { GET_CURRENT_CONTEXT(ctx); const unsigned numBuffers = num_buffers(ctx); unsigned buf; bool changed = false; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n", _mesa_enum_to_string(modeRGB), _mesa_enum_to_string(modeA)); if (ctx->Color._BlendEquationPerBuffer) { /* Check all per-buffer states */ for (buf = 0; buf < numBuffers; buf++) { if (ctx->Color.Blend[buf].EquationRGB != modeRGB || ctx->Color.Blend[buf].EquationA != modeA) { changed = true; break; } } } else { /* only need to check 0th per-buffer state */ if (ctx->Color.Blend[0].EquationRGB != modeRGB || ctx->Color.Blend[0].EquationA != modeA) { changed = true; } } if (!changed) return; if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendEquationSeparateEXT not supported by driver"); return; } /* Only allow simple blending equations. * The GL_KHR_blend_equation_advanced spec says: * * "NOTE: These enums are not accepted by the <modeRGB> or <modeAlpha> * parameters of BlendEquationSeparate or BlendEquationSeparatei." */ if (!legal_simple_blend_equation(ctx, modeRGB)) { _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)"); return; } if (!legal_simple_blend_equation(ctx, modeA)) { _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)"); return; } FLUSH_VERTICES(ctx, _NEW_COLOR); for (buf = 0; buf < numBuffers; buf++) { ctx->Color.Blend[buf].EquationRGB = modeRGB; ctx->Color.Blend[buf].EquationA = modeA; } ctx->Color._BlendEquationPerBuffer = GL_FALSE; ctx->Color._AdvancedBlendMode = BLEND_NONE; if (ctx->Driver.BlendEquationSeparate) ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA); }
/** * Set the separate blend source/dest factors for all draw buffers. * * \param sfactorRGB RGB source factor operator. * \param dfactorRGB RGB destination factor operator. * \param sfactorA alpha source factor operator. * \param dfactorA alpha destination factor operator. */ void GLAPIENTRY _mesa_BlendFuncSeparate( GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA ) { GET_CURRENT_CONTEXT(ctx); const unsigned numBuffers = num_buffers(ctx); unsigned buf; bool changed = false; if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n", _mesa_enum_to_string(sfactorRGB), _mesa_enum_to_string(dfactorRGB), _mesa_enum_to_string(sfactorA), _mesa_enum_to_string(dfactorA)); /* Check if we're really changing any state. If not, return early. */ if (ctx->Color._BlendFuncPerBuffer) { /* Check all per-buffer states */ for (buf = 0; buf < numBuffers; buf++) { if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB || ctx->Color.Blend[buf].DstRGB != dfactorRGB || ctx->Color.Blend[buf].SrcA != sfactorA || ctx->Color.Blend[buf].DstA != dfactorA) { changed = true; break; } } } else { /* only need to check 0th per-buffer state */ if (ctx->Color.Blend[0].SrcRGB != sfactorRGB || ctx->Color.Blend[0].DstRGB != dfactorRGB || ctx->Color.Blend[0].SrcA != sfactorA || ctx->Color.Blend[0].DstA != dfactorA) { changed = true; } } if (!changed) return; if (!validate_blend_factors(ctx, "glBlendFuncSeparate", sfactorRGB, dfactorRGB, sfactorA, dfactorA)) { return; } FLUSH_VERTICES(ctx, _NEW_COLOR); for (buf = 0; buf < numBuffers; buf++) { ctx->Color.Blend[buf].SrcRGB = sfactorRGB; ctx->Color.Blend[buf].DstRGB = dfactorRGB; ctx->Color.Blend[buf].SrcA = sfactorA; ctx->Color.Blend[buf].DstA = dfactorA; } update_uses_dual_src(ctx, 0); for (buf = 1; buf < numBuffers; buf++) { ctx->Color.Blend[buf]._UsesDualSrc = ctx->Color.Blend[0]._UsesDualSrc; } ctx->Color._BlendFuncPerBuffer = GL_FALSE; if (ctx->Driver.BlendFuncSeparate) { ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB, sfactorA, dfactorA); } }