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:
Brian Paul 2016-09-30 10:25:05 -06:00
parent e99b9395be
commit 951bf44a56
5 changed files with 195 additions and 191 deletions

View File

@ -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;
}
/**

View File

@ -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);

View File

@ -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;
}
/*@}*/

View File

@ -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 */

View File

@ -24,6 +24,7 @@
#include "glheader.h"
#include "imports.h"
#include "api_validate.h"
#include "bufferobj.h"
#include "context.h"
#include "drawpix.h"