mesa: move _mesa_valid_to_render() to api_validate.c
Almost all of the other drawing validation code is in api_validate.c so put this function there as well. Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
This commit is contained in:
parent
e99b9395be
commit
951bf44a56
|
@ -30,9 +30,198 @@
|
|||
#include "context.h"
|
||||
#include "imports.h"
|
||||
#include "mtypes.h"
|
||||
#include "pipelineobj.h"
|
||||
#include "enums.h"
|
||||
#include "vbo/vbo.h"
|
||||
#include "state.h"
|
||||
#include "transformfeedback.h"
|
||||
#include "uniforms.h"
|
||||
#include "vbo/vbo.h"
|
||||
#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) {
|
||||
/* 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_shader_program *sh_prog =
|
||||
ctx->_Shader->_CurrentFragmentProgram;
|
||||
const GLbitfield blend_support = !sh_prog ? 0 :
|
||||
sh_prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->info.BlendSupport;
|
||||
|
||||
if ((blend_support & 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
|
||||
* the current shader is valid and the framebuffer is complete.
|
||||
* It also check the current pipeline object is valid if any.
|
||||
* If an error is detected it'll be recorded here.
|
||||
* \return GL_TRUE if OK to render, GL_FALSE if not
|
||||
*/
|
||||
GLboolean
|
||||
_mesa_valid_to_render(struct gl_context *ctx, const char *where)
|
||||
{
|
||||
/* This depends on having up to date derived state (shaders) */
|
||||
if (ctx->NewState)
|
||||
_mesa_update_state(ctx);
|
||||
|
||||
if (ctx->API == API_OPENGL_COMPAT) {
|
||||
/* Any shader stages that are not supplied by the GLSL shader and have
|
||||
* assembly shaders enabled must now be validated.
|
||||
*/
|
||||
if (!ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]
|
||||
&& ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(vertex program not valid)", where);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (!ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
|
||||
if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(fragment program not valid)", where);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* If drawing to integer-valued color buffers, there must be an
|
||||
* active fragment shader (GL_EXT_texture_integer).
|
||||
*/
|
||||
if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(integer format but no fragment shader)", where);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A pipeline object is bound */
|
||||
if (ctx->_Shader->Name && !ctx->_Shader->Validated) {
|
||||
if (!_mesa_validate_program_pipeline(ctx, ctx->_Shader)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glValidateProgramPipeline failed to validate the "
|
||||
"pipeline");
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If a program is active and SSO not in use, check if validation of
|
||||
* samplers succeeded for the active program. */
|
||||
if (ctx->_Shader->ActiveProgram && ctx->_Shader != ctx->Pipeline.Current) {
|
||||
char errMsg[100];
|
||||
if (!_mesa_sampler_uniforms_are_valid(ctx->_Shader->ActiveProgram,
|
||||
errMsg, 100)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s", errMsg);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
|
||||
"%s(incomplete framebuffer)", where);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (!check_blend_func_error(ctx)) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (ctx->_Shader->Flags & GLSL_LOG) {
|
||||
struct gl_shader_program **shProg = ctx->_Shader->CurrentProgram;
|
||||
gl_shader_stage i;
|
||||
|
||||
for (i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
if (shProg[i] == NULL || shProg[i]->_Used
|
||||
|| shProg[i]->_LinkedShaders[i] == NULL)
|
||||
continue;
|
||||
|
||||
/* This is the first time this shader is being used.
|
||||
* Append shader's constants/uniforms to log file.
|
||||
*
|
||||
* Only log data for the program target that matches the shader
|
||||
* target. It's possible to have a program bound to the vertex
|
||||
* shader target that also supplied a fragment shader. If that
|
||||
* program isn't also bound to the fragment shader target we don't
|
||||
* want to log its fragment data.
|
||||
*/
|
||||
_mesa_append_uniforms_to_file(shProg[i]->_LinkedShaders[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
if (shProg[i] != NULL)
|
||||
shProg[i]->_Used = GL_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,6 +35,9 @@ struct gl_context;
|
|||
struct gl_transform_feedback_object;
|
||||
|
||||
|
||||
extern GLboolean
|
||||
_mesa_valid_to_render(struct gl_context *ctx, const char *where);
|
||||
|
||||
extern bool
|
||||
_mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode);
|
||||
|
||||
|
|
|
@ -122,7 +122,6 @@
|
|||
#include "shaderobj.h"
|
||||
#include "shaderimage.h"
|
||||
#include "util/strtod.h"
|
||||
#include "state.h"
|
||||
#include "stencil.h"
|
||||
#include "texcompress_s3tc.h"
|
||||
#include "texstate.h"
|
||||
|
@ -131,18 +130,16 @@
|
|||
#include "varray.h"
|
||||
#include "version.h"
|
||||
#include "viewport.h"
|
||||
#include "vtxfmt.h"
|
||||
#include "program/program.h"
|
||||
#include "program/prog_print.h"
|
||||
#include "math/m_matrix.h"
|
||||
#include "main/dispatch.h" /* for _gloffset_COUNT */
|
||||
#include "uniforms.h"
|
||||
#include "macros.h"
|
||||
|
||||
#ifdef USE_SPARC_ASM
|
||||
#include "sparc/sparc.h"
|
||||
#endif
|
||||
|
||||
#include "compiler/glsl_types.h"
|
||||
#include "compiler/glsl/glsl_parser_extras.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
|
@ -1857,189 +1854,6 @@ _mesa_Flush(void)
|
|||
}
|
||||
|
||||
|
||||
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) {
|
||||
/* 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_shader_program *sh_prog =
|
||||
ctx->_Shader->_CurrentFragmentProgram;
|
||||
const GLbitfield blend_support = !sh_prog ? 0 :
|
||||
sh_prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->info.BlendSupport;
|
||||
|
||||
if ((blend_support & 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
|
||||
* the current shader is valid and the framebuffer is complete.
|
||||
* It also check the current pipeline object is valid if any.
|
||||
* If an error is detected it'll be recorded here.
|
||||
* \return GL_TRUE if OK to render, GL_FALSE if not
|
||||
*/
|
||||
GLboolean
|
||||
_mesa_valid_to_render(struct gl_context *ctx, const char *where)
|
||||
{
|
||||
/* This depends on having up to date derived state (shaders) */
|
||||
if (ctx->NewState)
|
||||
_mesa_update_state(ctx);
|
||||
|
||||
if (ctx->API == API_OPENGL_COMPAT) {
|
||||
/* Any shader stages that are not supplied by the GLSL shader and have
|
||||
* assembly shaders enabled must now be validated.
|
||||
*/
|
||||
if (!ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]
|
||||
&& ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(vertex program not valid)", where);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (!ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
|
||||
if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(fragment program not valid)", where);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* If drawing to integer-valued color buffers, there must be an
|
||||
* active fragment shader (GL_EXT_texture_integer).
|
||||
*/
|
||||
if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerColor) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"%s(integer format but no fragment shader)", where);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A pipeline object is bound */
|
||||
if (ctx->_Shader->Name && !ctx->_Shader->Validated) {
|
||||
if (!_mesa_validate_program_pipeline(ctx, ctx->_Shader)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glValidateProgramPipeline failed to validate the "
|
||||
"pipeline");
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If a program is active and SSO not in use, check if validation of
|
||||
* samplers succeeded for the active program. */
|
||||
if (ctx->_Shader->ActiveProgram && ctx->_Shader != ctx->Pipeline.Current) {
|
||||
char errMsg[100];
|
||||
if (!_mesa_sampler_uniforms_are_valid(ctx->_Shader->ActiveProgram,
|
||||
errMsg, 100)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "%s", errMsg);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
_mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
|
||||
"%s(incomplete framebuffer)", where);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (!check_blend_func_error(ctx)) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (ctx->_Shader->Flags & GLSL_LOG) {
|
||||
struct gl_shader_program **shProg = ctx->_Shader->CurrentProgram;
|
||||
gl_shader_stage i;
|
||||
|
||||
for (i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
if (shProg[i] == NULL || shProg[i]->_Used
|
||||
|| shProg[i]->_LinkedShaders[i] == NULL)
|
||||
continue;
|
||||
|
||||
/* This is the first time this shader is being used.
|
||||
* Append shader's constants/uniforms to log file.
|
||||
*
|
||||
* Only log data for the program target that matches the shader
|
||||
* target. It's possible to have a program bound to the vertex
|
||||
* shader target that also supplied a fragment shader. If that
|
||||
* program isn't also bound to the fragment shader target we don't
|
||||
* want to log its fragment data.
|
||||
*/
|
||||
_mesa_append_uniforms_to_file(shProg[i]->_LinkedShaders[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
if (shProg[i] != NULL)
|
||||
shProg[i]->_Used = GL_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
|
|
@ -152,9 +152,6 @@ _mesa_get_dispatch(struct gl_context *ctx);
|
|||
extern void
|
||||
_mesa_set_context_lost_dispatch(struct gl_context *ctx);
|
||||
|
||||
extern GLboolean
|
||||
_mesa_valid_to_render(struct gl_context *ctx, const char *where);
|
||||
|
||||
|
||||
|
||||
/** \name Miscellaneous */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "glheader.h"
|
||||
#include "imports.h"
|
||||
#include "api_validate.h"
|
||||
#include "bufferobj.h"
|
||||
#include "context.h"
|
||||
#include "drawpix.h"
|
||||
|
|
Loading…
Reference in New Issue