mesa: add support for ARB_blend_func_extended (v4)
Add implementations of the two API functions, Add a new strings to uint mapping for index bindings Add the blending mode validation for SRC1 + SRC_ALPHA_SATURATE Add get for MAX_DUAL_SOURCE_DRAW_BUFFERS v2: Add check in valid_to_render to address case in spec ERRORS. v3: Add index to ir.h so this patch compiles on its own fixup comment v4: fixup Brian's comments The GLSL patch will setup the indices. Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
@@ -420,6 +420,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
int location;
|
int location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* output index for dual source blending.
|
||||||
|
*/
|
||||||
|
int index;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Built-in state that backs this uniform
|
* Built-in state that backs this uniform
|
||||||
*
|
*
|
||||||
|
@@ -63,6 +63,11 @@ legal_src_factor(const struct gl_context *ctx, GLenum factor)
|
|||||||
case GL_CONSTANT_ALPHA:
|
case GL_CONSTANT_ALPHA:
|
||||||
case GL_ONE_MINUS_CONSTANT_ALPHA:
|
case GL_ONE_MINUS_CONSTANT_ALPHA:
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
|
case GL_SRC1_COLOR:
|
||||||
|
case GL_SRC1_ALPHA:
|
||||||
|
case GL_ONE_MINUS_SRC1_COLOR:
|
||||||
|
case GL_ONE_MINUS_SRC1_ALPHA:
|
||||||
|
return ctx->Extensions.ARB_blend_func_extended;
|
||||||
default:
|
default:
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
@@ -93,6 +98,12 @@ legal_dst_factor(const struct gl_context *ctx, GLenum factor)
|
|||||||
case GL_CONSTANT_ALPHA:
|
case GL_CONSTANT_ALPHA:
|
||||||
case GL_ONE_MINUS_CONSTANT_ALPHA:
|
case GL_ONE_MINUS_CONSTANT_ALPHA:
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
|
case GL_SRC_ALPHA_SATURATE:
|
||||||
|
case GL_SRC1_COLOR:
|
||||||
|
case GL_SRC1_ALPHA:
|
||||||
|
case GL_ONE_MINUS_SRC1_COLOR:
|
||||||
|
case GL_ONE_MINUS_SRC1_ALPHA:
|
||||||
|
return ctx->Extensions.ARB_blend_func_extended;
|
||||||
default:
|
default:
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
@@ -1695,7 +1695,39 @@ _mesa_set_mvp_with_dp4( struct gl_context *ctx,
|
|||||||
ctx->mvp_with_dp4 = flag;
|
ctx->mvp_with_dp4 = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLboolean
|
||||||
|
blend_factor_is_dual_src(GLenum factor)
|
||||||
|
{
|
||||||
|
return factor == GL_SRC1_COLOR || factor == GL_SRC1_ALPHA ||
|
||||||
|
factor == GL_ONE_MINUS_SRC1_COLOR || factor == GL_ONE_MINUS_SRC1_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ARB_blend_func_extended - ERRORS section
|
||||||
|
* "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."
|
||||||
|
*/
|
||||||
|
static GLboolean
|
||||||
|
_mesa_check_blend_func_error(struct gl_context *ctx)
|
||||||
|
{
|
||||||
|
GLuint i;
|
||||||
|
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
|
||||||
|
if (blend_factor_is_dual_src(ctx->Color.Blend[i].SrcRGB) ||
|
||||||
|
blend_factor_is_dual_src(ctx->Color.Blend[i].DstRGB) ||
|
||||||
|
blend_factor_is_dual_src(ctx->Color.Blend[i].SrcA) ||
|
||||||
|
blend_factor_is_dual_src(ctx->Color.Blend[i].DstA)) {
|
||||||
|
if (i >= ctx->Const.MaxDualSourceDrawBuffers) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"dual source blend on illegal attachment");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prior to drawing anything with glBegin, glDrawArrays, etc. this function
|
* Prior to drawing anything with glBegin, glDrawArrays, etc. this function
|
||||||
@@ -1816,6 +1848,10 @@ _mesa_valid_to_render(struct gl_context *ctx, const char *where)
|
|||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_mesa_check_blend_func_error(ctx) == GL_FALSE) {
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (ctx->Shader.Flags & GLSL_LOG) {
|
if (ctx->Shader.Flags & GLSL_LOG) {
|
||||||
struct gl_shader_program *shProg[MESA_SHADER_TYPES];
|
struct gl_shader_program *shProg[MESA_SHADER_TYPES];
|
||||||
|
@@ -333,6 +333,7 @@ EXTRA_EXT(ARB_copy_buffer);
|
|||||||
EXTRA_EXT(EXT_framebuffer_sRGB);
|
EXTRA_EXT(EXT_framebuffer_sRGB);
|
||||||
EXTRA_EXT(ARB_texture_buffer_object);
|
EXTRA_EXT(ARB_texture_buffer_object);
|
||||||
EXTRA_EXT(OES_EGL_image_external);
|
EXTRA_EXT(OES_EGL_image_external);
|
||||||
|
EXTRA_EXT(ARB_blend_func_extended);
|
||||||
|
|
||||||
static const int
|
static const int
|
||||||
extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program[] = {
|
extra_ARB_vertex_program_ARB_fragment_program_NV_vertex_program[] = {
|
||||||
@@ -1304,6 +1305,8 @@ static const struct value_desc values[] = {
|
|||||||
{ GL_MAX_DEBUG_LOGGED_MESSAGES_ARB, CONST(MAX_DEBUG_LOGGED_MESSAGES), NO_EXTRA },
|
{ GL_MAX_DEBUG_LOGGED_MESSAGES_ARB, CONST(MAX_DEBUG_LOGGED_MESSAGES), NO_EXTRA },
|
||||||
{ GL_MAX_DEBUG_MESSAGE_LENGTH_ARB, CONST(MAX_DEBUG_MESSAGE_LENGTH), NO_EXTRA },
|
{ GL_MAX_DEBUG_MESSAGE_LENGTH_ARB, CONST(MAX_DEBUG_MESSAGE_LENGTH), NO_EXTRA },
|
||||||
|
|
||||||
|
{ GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, CONTEXT_INT(Const.MaxDualSourceDrawBuffers), extra_ARB_blend_func_extended },
|
||||||
|
|
||||||
#endif /* FEATURE_GL */
|
#endif /* FEATURE_GL */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -2263,6 +2263,7 @@ struct gl_shader_program
|
|||||||
* and they are \b not the values returned by \c glGetFragDataLocation.
|
* and they are \b not the values returned by \c glGetFragDataLocation.
|
||||||
*/
|
*/
|
||||||
struct string_to_uint_map *FragDataBindings;
|
struct string_to_uint_map *FragDataBindings;
|
||||||
|
struct string_to_uint_map *FragDataIndexBindings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform feedback varyings last specified by
|
* Transform feedback varyings last specified by
|
||||||
@@ -2814,6 +2815,9 @@ struct gl_constants
|
|||||||
/* GL_ARB_robustness */
|
/* GL_ARB_robustness */
|
||||||
GLenum ResetStrategy;
|
GLenum ResetStrategy;
|
||||||
|
|
||||||
|
/* GL_ARB_blend_func_extended */
|
||||||
|
GLuint MaxDualSourceDrawBuffers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the implementation strips out and ignores texture borders.
|
* Whether the implementation strips out and ignores texture borders.
|
||||||
*
|
*
|
||||||
|
@@ -238,11 +238,18 @@ _mesa_longest_attribute_name_length(struct gl_shader_program *shProg)
|
|||||||
void GLAPIENTRY
|
void GLAPIENTRY
|
||||||
_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
|
_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
|
||||||
const GLchar *name)
|
const GLchar *name)
|
||||||
|
{
|
||||||
|
_mesa_BindFragDataLocationIndexed(program, colorNumber, 0, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLAPIENTRY
|
||||||
|
_mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
|
||||||
|
GLuint index, const GLchar *name)
|
||||||
{
|
{
|
||||||
GET_CURRENT_CONTEXT(ctx);
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
|
||||||
struct gl_shader_program *const shProg =
|
struct gl_shader_program *const shProg =
|
||||||
_mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocation");
|
_mesa_lookup_shader_program_err(ctx, program, "glBindFragDataLocationIndexed");
|
||||||
if (!shProg)
|
if (!shProg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -250,13 +257,22 @@ _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (strncmp(name, "gl_", 3) == 0) {
|
if (strncmp(name, "gl_", 3) == 0) {
|
||||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
_mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragDataLocationIndexed(illegal name)");
|
||||||
"glBindFragDataLocation(illegal name)");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colorNumber >= ctx->Const.MaxDrawBuffers) {
|
if (index > 1) {
|
||||||
_mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocation(index)");
|
_mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(index)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 0 && colorNumber >= ctx->Const.MaxDrawBuffers) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 1 && colorNumber >= ctx->Const.MaxDualSourceDrawBuffers) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_VALUE, "glBindFragDataLocationIndexed(colorNumber)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,11 +281,68 @@ _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
|
|||||||
* between built-in attributes and user-defined attributes.
|
* between built-in attributes and user-defined attributes.
|
||||||
*/
|
*/
|
||||||
shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
|
shProg->FragDataBindings->put(colorNumber + FRAG_RESULT_DATA0, name);
|
||||||
|
shProg->FragDataIndexBindings->put(index, name);
|
||||||
/*
|
/*
|
||||||
* Note that this binding won't go into effect until
|
* Note that this binding won't go into effect until
|
||||||
* glLinkProgram is called again.
|
* glLinkProgram is called again.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint GLAPIENTRY
|
||||||
|
_mesa_GetFragDataIndex(GLuint program, const GLchar *name)
|
||||||
|
{
|
||||||
|
GET_CURRENT_CONTEXT(ctx);
|
||||||
|
struct gl_shader_program *const shProg =
|
||||||
|
_mesa_lookup_shader_program_err(ctx, program, "glGetFragDataIndex");
|
||||||
|
|
||||||
|
if (!shProg) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shProg->LinkStatus) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"glGetFragDataIndex(program not linked)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (strncmp(name, "gl_", 3) == 0) {
|
||||||
|
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||||
|
"glGetFragDataIndex(illegal name)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not having a fragment shader is not an error.
|
||||||
|
*/
|
||||||
|
if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
exec_list *ir = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
|
||||||
|
foreach_list(node, ir) {
|
||||||
|
const ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||||
|
|
||||||
|
/* The extra check against FRAG_RESULT_DATA0 is because
|
||||||
|
* glGetFragDataLocation cannot be used on "conventional" attributes.
|
||||||
|
*
|
||||||
|
* From page 95 of the OpenGL 3.0 spec:
|
||||||
|
*
|
||||||
|
* "If name is not an active attribute, if name is a conventional
|
||||||
|
* attribute, or if an error occurs, -1 will be returned."
|
||||||
|
*/
|
||||||
|
if (var == NULL
|
||||||
|
|| var->mode != ir_var_out
|
||||||
|
|| var->location == -1
|
||||||
|
|| var->location < FRAG_RESULT_DATA0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(var->name, name) == 0)
|
||||||
|
return var->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint GLAPIENTRY
|
GLint GLAPIENTRY
|
||||||
|
@@ -1748,6 +1748,9 @@ _mesa_init_shader_dispatch(struct _glapi_table *exec)
|
|||||||
SET_ReleaseShaderCompiler(exec, _mesa_ReleaseShaderCompiler);
|
SET_ReleaseShaderCompiler(exec, _mesa_ReleaseShaderCompiler);
|
||||||
SET_GetShaderPrecisionFormat(exec, _mesa_GetShaderPrecisionFormat);
|
SET_GetShaderPrecisionFormat(exec, _mesa_GetShaderPrecisionFormat);
|
||||||
|
|
||||||
|
/* GL_ARB_blend_func_extended */
|
||||||
|
SET_BindFragDataLocationIndexed(exec, _mesa_BindFragDataLocationIndexed);
|
||||||
|
SET_GetFragDataIndex(exec, _mesa_GetFragDataIndex);
|
||||||
#endif /* FEATURE_GL */
|
#endif /* FEATURE_GL */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -86,6 +86,9 @@ _mesa_GetAttachedObjectsARB(GLhandleARB, GLsizei, GLsizei *, GLhandleARB *);
|
|||||||
extern GLint GLAPIENTRY
|
extern GLint GLAPIENTRY
|
||||||
_mesa_GetFragDataLocation(GLuint program, const GLchar *name);
|
_mesa_GetFragDataLocation(GLuint program, const GLchar *name);
|
||||||
|
|
||||||
|
extern GLint GLAPIENTRY
|
||||||
|
_mesa_GetFragDataIndex(GLuint program, const GLchar *name);
|
||||||
|
|
||||||
extern GLhandleARB GLAPIENTRY
|
extern GLhandleARB GLAPIENTRY
|
||||||
_mesa_GetHandleARB(GLenum pname);
|
_mesa_GetHandleARB(GLenum pname);
|
||||||
|
|
||||||
@@ -127,6 +130,10 @@ extern void GLAPIENTRY
|
|||||||
_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
|
_mesa_BindFragDataLocation(GLuint program, GLuint colorNumber,
|
||||||
const GLchar *name);
|
const GLchar *name);
|
||||||
|
|
||||||
|
extern void GLAPIENTRY
|
||||||
|
_mesa_BindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
|
||||||
|
GLuint index, const GLchar *name);
|
||||||
|
|
||||||
extern void GLAPIENTRY
|
extern void GLAPIENTRY
|
||||||
_mesa_GetActiveAttribARB(GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *,
|
_mesa_GetActiveAttribARB(GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *,
|
||||||
GLenum *, GLcharARB *);
|
GLenum *, GLcharARB *);
|
||||||
|
@@ -242,6 +242,7 @@ _mesa_init_shader_program(struct gl_context *ctx, struct gl_shader_program *prog
|
|||||||
|
|
||||||
prog->AttributeBindings = string_to_uint_map_ctor();
|
prog->AttributeBindings = string_to_uint_map_ctor();
|
||||||
prog->FragDataBindings = string_to_uint_map_ctor();
|
prog->FragDataBindings = string_to_uint_map_ctor();
|
||||||
|
prog->FragDataIndexBindings = string_to_uint_map_ctor();
|
||||||
|
|
||||||
#if FEATURE_ARB_geometry_shader4
|
#if FEATURE_ARB_geometry_shader4
|
||||||
prog->Geom.VerticesOut = 0;
|
prog->Geom.VerticesOut = 0;
|
||||||
@@ -319,6 +320,11 @@ _mesa_free_shader_program_data(struct gl_context *ctx,
|
|||||||
shProg->FragDataBindings = NULL;
|
shProg->FragDataBindings = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shProg->FragDataIndexBindings) {
|
||||||
|
string_to_uint_map_dtor(shProg->FragDataIndexBindings);
|
||||||
|
shProg->FragDataIndexBindings = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* detach shaders */
|
/* detach shaders */
|
||||||
for (i = 0; i < shProg->NumShaders; i++) {
|
for (i = 0; i < shProg->NumShaders; i++) {
|
||||||
_mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
|
_mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
|
||||||
|
Reference in New Issue
Block a user