mesa: move blending validation from draws to state changes

This is a step towards removing _mesa_valid_to_render.

Reviewed-by: Zoltán Böszörményi <zboszor@gmail.com>
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8798>
This commit is contained in:
Marek Olšák 2021-01-24 16:48:13 -05:00 committed by Marge Bot
parent 40341c5118
commit bf9d61a3d4
2 changed files with 75 additions and 85 deletions

View file

@ -32,6 +32,7 @@
#include "glheader.h"
#include "blend.h"
#include "context.h"
#include "draw_validate.h"
#include "enums.h"
#include "macros.h"
#include "mtypes.h"
@ -170,11 +171,16 @@ blend_factor_is_dual_src(GLenum factor)
static void
update_uses_dual_src(struct gl_context *ctx, int buf)
{
ctx->Color.Blend[buf]._UsesDualSrc =
bool uses_dual_src =
(blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcRGB) ||
blend_factor_is_dual_src(ctx->Color.Blend[buf].DstRGB) ||
blend_factor_is_dual_src(ctx->Color.Blend[buf].SrcA) ||
blend_factor_is_dual_src(ctx->Color.Blend[buf].DstA));
if (ctx->Color.Blend[buf]._UsesDualSrc != uses_dual_src) {
ctx->Color.Blend[buf]._UsesDualSrc = uses_dual_src;
_mesa_update_valid_to_render_state(ctx);
}
}
@ -497,6 +503,16 @@ advanced_blend_mode(const struct gl_context *ctx, GLenum mode)
advanced_blend_mode_from_gl_enum(mode) : BLEND_NONE;
}
static void
set_advanced_blend_mode(struct gl_context *ctx,
enum gl_advanced_blend_mode advanced_mode)
{
if (ctx->Color._AdvancedBlendMode != advanced_mode) {
ctx->Color._AdvancedBlendMode = advanced_mode;
_mesa_update_valid_to_render_state(ctx);
}
}
/* This is really an extension function! */
void GLAPIENTRY
_mesa_BlendEquation( GLenum mode )
@ -546,7 +562,7 @@ _mesa_BlendEquation( GLenum mode )
ctx->Color.Blend[buf].EquationA = mode;
}
ctx->Color._BlendEquationPerBuffer = GL_FALSE;
ctx->Color._AdvancedBlendMode = advanced_mode;
set_advanced_blend_mode(ctx, advanced_mode);
if (ctx->Driver.BlendEquationSeparate)
ctx->Driver.BlendEquationSeparate(ctx, mode, mode);
@ -571,7 +587,7 @@ blend_equationi(struct gl_context *ctx, GLuint buf, GLenum mode,
ctx->Color._BlendEquationPerBuffer = GL_TRUE;
if (buf == 0)
ctx->Color._AdvancedBlendMode = advanced_mode;
set_advanced_blend_mode(ctx, advanced_mode);
}
@ -670,7 +686,7 @@ blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA,
ctx->Color.Blend[buf].EquationA = modeA;
}
ctx->Color._BlendEquationPerBuffer = GL_FALSE;
ctx->Color._AdvancedBlendMode = BLEND_NONE;
set_advanced_blend_mode(ctx, BLEND_NONE);
if (ctx->Driver.BlendEquationSeparate)
ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA);
@ -729,7 +745,7 @@ blend_equation_separatei(struct gl_context *ctx, GLuint buf, GLenum modeRGB,
ctx->Color.Blend[buf].EquationRGB = modeRGB;
ctx->Color.Blend[buf].EquationA = modeA;
ctx->Color._BlendEquationPerBuffer = GL_TRUE;
ctx->Color._AdvancedBlendMode = BLEND_NONE;
set_advanced_blend_mode(ctx, BLEND_NONE);
}

View file

@ -38,82 +38,6 @@
#include "program/prog_print.h"
static bool
check_blend_func_error(struct gl_context *ctx)
{
/* The ARB_blend_func_extended spec's ERRORS section says:
*
* "The error INVALID_OPERATION is generated by Begin or any procedure
* that implicitly calls Begin if any draw buffer has a blend function
* requiring the second color input (SRC1_COLOR, ONE_MINUS_SRC1_COLOR,
* SRC1_ALPHA or ONE_MINUS_SRC1_ALPHA), and a framebuffer is bound that
* has more than the value of MAX_DUAL_SOURCE_DRAW_BUFFERS-1 active
* color attachements."
*/
for (unsigned i = ctx->Const.MaxDualSourceDrawBuffers;
i < ctx->DrawBuffer->_NumColorDrawBuffers;
i++) {
if (ctx->Color.Blend[i]._UsesDualSrc) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"dual source blend on illegal attachment");
return false;
}
}
if (ctx->Color.BlendEnabled &&
ctx->Color._AdvancedBlendMode != BLEND_NONE) {
/* The KHR_blend_equation_advanced spec says:
*
* "If any non-NONE draw buffer uses a blend equation found in table
* X.1 or X.2, the error INVALID_OPERATION is generated by Begin or
* any operation that implicitly calls Begin (such as DrawElements)
* if:
*
* * the draw buffer for color output zero selects multiple color
* buffers (e.g., FRONT_AND_BACK in the default framebuffer); or
*
* * the draw buffer for any other color output is not NONE."
*/
if (ctx->DrawBuffer->ColorDrawBuffer[0] == GL_FRONT_AND_BACK) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"advanced blending is active and draw buffer for color "
"output zero selects multiple color buffers");
return false;
}
for (unsigned i = 1; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
if (ctx->DrawBuffer->ColorDrawBuffer[i] != GL_NONE) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"advanced blending is active with multiple color "
"draw buffers");
return false;
}
}
/* The KHR_blend_equation_advanced spec says:
*
* "Advanced blending equations require the use of a fragment shader
* with a matching "blend_support" layout qualifier. If the current
* blend equation is found in table X.1 or X.2, and the active
* fragment shader does not include the layout qualifier matching
* the blend equation or "blend_support_all_equations", the error
* INVALID_OPERATION is generated [...]"
*/
const struct gl_program *prog = ctx->FragmentProgram._Current;
const GLbitfield blend_support = !prog ? 0 : prog->sh.fs.BlendSupport;
if ((blend_support & BITFIELD_BIT(ctx->Color._AdvancedBlendMode)) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"fragment shader does not allow advanced blending mode "
"(%s)",
_mesa_enum_to_string(ctx->Color.Blend[0].EquationRGB));
}
}
return true;
}
/**
* Prior to drawing anything with glBegin, glDrawArrays, etc. this function
* is called to see if it's valid to render. This involves checking that
@ -129,10 +53,6 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
if (ctx->NewState)
_mesa_update_state(ctx);
if (!check_blend_func_error(ctx)) {
return GL_FALSE;
}
return GL_TRUE;
}
@ -186,6 +106,60 @@ _mesa_update_valid_to_render_state(struct gl_context *ctx)
!_mesa_sampler_uniforms_are_valid(shader->ActiveProgram, NULL, 0))
return;
/* The ARB_blend_func_extended spec's ERRORS section says:
*
* "The error INVALID_OPERATION is generated by Begin or any procedure
* that implicitly calls Begin if any draw buffer has a blend function
* requiring the second color input (SRC1_COLOR, ONE_MINUS_SRC1_COLOR,
* SRC1_ALPHA or ONE_MINUS_SRC1_ALPHA), and a framebuffer is bound that
* has more than the value of MAX_DUAL_SOURCE_DRAW_BUFFERS-1 active
* color attachements."
*/
for (unsigned i = ctx->Const.MaxDualSourceDrawBuffers;
i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
if (ctx->Color.Blend[i]._UsesDualSrc)
return;
}
if (ctx->Color.BlendEnabled &&
ctx->Color._AdvancedBlendMode != BLEND_NONE) {
/* The KHR_blend_equation_advanced spec says:
*
* "If any non-NONE draw buffer uses a blend equation found in table
* X.1 or X.2, the error INVALID_OPERATION is generated by Begin or
* any operation that implicitly calls Begin (such as DrawElements)
* if:
*
* * the draw buffer for color output zero selects multiple color
* buffers (e.g., FRONT_AND_BACK in the default framebuffer); or
*
* * the draw buffer for any other color output is not NONE."
*/
if (ctx->DrawBuffer->ColorDrawBuffer[0] == GL_FRONT_AND_BACK)
return;
for (unsigned i = 1; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
if (ctx->DrawBuffer->ColorDrawBuffer[i] != GL_NONE)
return;
}
/* The KHR_blend_equation_advanced spec says:
*
* "Advanced blending equations require the use of a fragment shader
* with a matching "blend_support" layout qualifier. If the current
* blend equation is found in table X.1 or X.2, and the active
* fragment shader does not include the layout qualifier matching
* the blend equation or "blend_support_all_equations", the error
* INVALID_OPERATION is generated [...]"
*/
const struct gl_program *prog =
ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
const GLbitfield blend_support = !prog ? 0 : prog->sh.fs.BlendSupport;
if ((blend_support & BITFIELD_BIT(ctx->Color._AdvancedBlendMode)) == 0)
return;
}
if (ctx->API == API_OPENGL_COMPAT) {
if (!shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
if (ctx->FragmentProgram.Enabled &&