diff options
author | Brian Paul <brianp@vmware.com> | 2011-01-11 15:07:38 -0700 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2011-01-15 18:35:39 -0700 |
commit | 74713e2d293f9e796a4053a5a99ee5cb7df5c740 (patch) | |
tree | 0c3ad404ba3a090e53801f93b1cd0649370cead2 /src/mesa/main | |
parent | 3dab2b1795e9f9ff3584f612397d118459b12731 (diff) |
mesa: begin implementation of GL_ARB_draw_buffers_blend
Diffstat (limited to 'src/mesa/main')
-rw-r--r-- | src/mesa/main/attrib.c | 47 | ||||
-rw-r--r-- | src/mesa/main/blend.c | 503 | ||||
-rw-r--r-- | src/mesa/main/blend.h | 17 | ||||
-rw-r--r-- | src/mesa/main/context.h | 2 | ||||
-rw-r--r-- | src/mesa/main/dd.h | 5 | ||||
-rw-r--r-- | src/mesa/main/extensions.c | 1 | ||||
-rw-r--r-- | src/mesa/main/get.c | 16 | ||||
-rw-r--r-- | src/mesa/main/mtypes.h | 20 |
8 files changed, 423 insertions, 188 deletions
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index adfec3b0d5..7fd1287368 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -954,20 +954,39 @@ _mesa_PopAttrib(void) _mesa_set_enable(ctx, GL_BLEND, (color->BlendEnabled & 1)); } } - _mesa_BlendFuncSeparateEXT(color->BlendSrcRGB, - color->BlendDstRGB, - color->BlendSrcA, - color->BlendDstA); - /* This special case is because glBlendEquationSeparateEXT - * cannot take GL_LOGIC_OP as a parameter. - */ - if ( color->BlendEquationRGB == color->BlendEquationA ) { - _mesa_BlendEquation(color->BlendEquationRGB); - } - else { - _mesa_BlendEquationSeparateEXT(color->BlendEquationRGB, - color->BlendEquationA); - } + if (ctx->Color._BlendFuncPerBuffer || + ctx->Color._BlendEquationPerBuffer) { + /* set blend per buffer */ + GLuint buf; + for (buf = 0; buf < ctx->Const.MaxDrawBuffers; buf++) { + _mesa_BlendFuncSeparatei(buf, color->Blend[buf].SrcRGB, + color->Blend[buf].DstRGB, + color->Blend[buf].SrcA, + color->Blend[buf].DstA); + _mesa_BlendEquationSeparatei(buf, + color->Blend[buf].EquationRGB, + color->Blend[buf].EquationA); + } + } + else { + /* set same blend modes for all buffers */ + _mesa_BlendFuncSeparateEXT(color->Blend[0].SrcRGB, + color->Blend[0].DstRGB, + color->Blend[0].SrcA, + color->Blend[0].DstA); + /* This special case is because glBlendEquationSeparateEXT + * cannot take GL_LOGIC_OP as a parameter. + */ + if (color->Blend[0].EquationRGB == + color->Blend[0].EquationA) { + _mesa_BlendEquation(color->Blend[0].EquationRGB); + } + else { + _mesa_BlendEquationSeparateEXT( + color->Blend[0].EquationRGB, + color->Blend[0].EquationA); + } + } _mesa_BlendColor(color->BlendColor[0], color->BlendColor[1], color->BlendColor[2], diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c index ec778b7244..43e2f7f861 100644 --- a/src/mesa/main/blend.c +++ b/src/mesa/main/blend.c @@ -37,6 +37,110 @@ #include "mtypes.h" + +/** + * Check if given blend source factor is legal. + * \return GL_TRUE if legal, GL_FALSE otherwise. + */ +static GLboolean +legal_src_factor(const struct gl_context *ctx, GLenum factor) +{ + switch (factor) { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + return ctx->Extensions.NV_blend_square; + case GL_ZERO: + case GL_ONE: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_SRC_ALPHA_SATURATE: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Check if given blend destination factor is legal. + * \return GL_TRUE if legal, GL_FALSE otherwise. + */ +static GLboolean +legal_dst_factor(const struct gl_context *ctx, GLenum factor) +{ + switch (factor) { + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + return ctx->Extensions.NV_blend_square; + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Check if src/dest RGB/A blend factors are legal. If not generate + * a GL error. + * \return GL_TRUE if factors are legal, GL_FALSE otherwise. + */ +static GLboolean +validate_blend_factors(struct gl_context *ctx, const char *func, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + if (!legal_src_factor(ctx, sfactorRGB)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(sfactorRGB = %s)", func, + _mesa_lookup_enum_by_nr(sfactorRGB)); + return GL_FALSE; + } + + if (!legal_dst_factor(ctx, dfactorRGB)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(dfactorRGB = %s)", func, + _mesa_lookup_enum_by_nr(dfactorRGB)); + return GL_FALSE; + } + + if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(sfactorA = %s)", func, + _mesa_lookup_enum_by_nr(sfactorA)); + return GL_FALSE; + } + + if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(dfactorA = %s)", func, + _mesa_lookup_enum_by_nr(dfactorA)); + return GL_FALSE; + } + + return GL_TRUE; +} + + /** * Specify the blending operation. * @@ -53,21 +157,19 @@ _mesa_BlendFunc( GLenum sfactor, GLenum dfactor ) /** - * Process GL_EXT_blend_func_separate(). + * 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. - * - * Verifies the parameters and updates gl_colorbuffer_attrib. - * On a change, flush the vertices and notify the driver via - * dd_function_table::BlendFuncSeparate. */ void GLAPIENTRY _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA ) { + GLuint buf, numBuffers; + GLboolean changed; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -78,165 +180,130 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, _mesa_lookup_enum_by_nr(sfactorA), _mesa_lookup_enum_by_nr(dfactorA)); - switch (sfactorRGB) { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - if (!ctx->Extensions.NV_blend_square) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)"); - return; - } - /* fall-through */ - case GL_ZERO: - case GL_ONE: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_SRC_ALPHA_SATURATE: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorRGB)"); - return; + if (!validate_blend_factors(ctx, "glBlendFuncSeparate", + sfactorRGB, dfactorRGB, + sfactorA, dfactorA)) { + return; } - switch (dfactorRGB) { - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - if (!ctx->Extensions.NV_blend_square) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)"); - return; - } - /* fall-through */ - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: + numBuffers = ctx->Extensions.ARB_draw_buffers_blend + ? ctx->Const.MaxDrawBuffers : 1; + + changed = GL_FALSE; + 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 = GL_TRUE; break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorRGB)"); - return; + } } + if (!changed) + return; - switch (sfactorA) { - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - if (!ctx->Extensions.NV_blend_square) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)"); - return; - } - /* fall-through */ - case GL_ZERO: - case GL_ONE: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_SRC_ALPHA_SATURATE: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (sfactorA)"); - 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; } + ctx->Color._BlendFuncPerBuffer = GL_FALSE; - switch (dfactorA) { - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - if (!ctx->Extensions.NV_blend_square) { - _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)"); - return; - } - /* fall-through */ - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - break; - default: - _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc or glBlendFuncSeparate (dfactorA)" ); - return; + if (ctx->Driver.BlendFuncSeparate) { + ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB, + sfactorA, dfactorA); } +} + - if (ctx->Color.BlendSrcRGB == sfactorRGB && - ctx->Color.BlendDstRGB == dfactorRGB && - ctx->Color.BlendSrcA == sfactorA && - ctx->Color.BlendDstA == dfactorA) +#if _HAVE_FULL_GL + + +/** + * Set blend source/dest factors for one color buffer/target. + */ +void GLAPIENTRY +_mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor) +{ + _mesa_BlendFuncSeparatei(buf, sfactor, dfactor, sfactor, dfactor); +} + + +/** + * Set separate blend source/dest factors for one color buffer/target. + */ +void GLAPIENTRY +_mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.ARB_draw_buffers_blend) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()"); + return; + } + + if (buf >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)", + buf); return; + } + + if (!validate_blend_factors(ctx, "glBlendFuncSeparatei", + sfactorRGB, dfactorRGB, + sfactorA, dfactorA)) { + return; + } + + 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; /* no change */ FLUSH_VERTICES(ctx, _NEW_COLOR); - ctx->Color.BlendSrcRGB = sfactorRGB; - ctx->Color.BlendDstRGB = dfactorRGB; - ctx->Color.BlendSrcA = sfactorA; - ctx->Color.BlendDstA = dfactorA; + ctx->Color.Blend[buf].SrcRGB = sfactorRGB; + ctx->Color.Blend[buf].DstRGB = dfactorRGB; + ctx->Color.Blend[buf].SrcA = sfactorA; + ctx->Color.Blend[buf].DstA = dfactorA; + ctx->Color._BlendFuncPerBuffer = GL_TRUE; - if (ctx->Driver.BlendFuncSeparate) { - (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB, - sfactorA, dfactorA ); + if (ctx->Driver.BlendFuncSeparatei) { + ctx->Driver.BlendFuncSeparatei(ctx, buf, sfactorRGB, dfactorRGB, + sfactorA, dfactorA); } } -#if _HAVE_FULL_GL - +/** + * Check if given blend equation is legal. + * \return GL_TRUE if legal, GL_FALSE otherwise. + */ static GLboolean -_mesa_validate_blend_equation( struct gl_context *ctx, - GLenum mode, GLboolean is_separate ) +legal_blend_equation(const struct gl_context *ctx, + GLenum mode, GLboolean is_separate) { switch (mode) { - case GL_FUNC_ADD: - break; - case GL_MIN: - case GL_MAX: - if (!ctx->Extensions.EXT_blend_minmax) { - return GL_FALSE; - } - break; + case GL_FUNC_ADD: + return GL_TRUE; + case GL_MIN: + case GL_MAX: + return ctx->Extensions.EXT_blend_minmax; + case GL_LOGIC_OP: /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter. */ - case GL_LOGIC_OP: - if (!ctx->Extensions.EXT_blend_logic_op || is_separate) { - return GL_FALSE; - } - break; - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - if (!ctx->Extensions.EXT_blend_subtract) { - return GL_FALSE; - } - break; - default: - return GL_FALSE; + return ctx->Extensions.EXT_blend_logic_op && !is_separate; + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + return ctx->Extensions.EXT_blend_subtract; + default: + return GL_FALSE; } - - return GL_TRUE; } @@ -244,6 +311,8 @@ _mesa_validate_blend_equation( struct gl_context *ctx, void GLAPIENTRY _mesa_BlendEquation( GLenum mode ) { + GLuint buf, numBuffers; + GLboolean changed; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -251,27 +320,80 @@ _mesa_BlendEquation( GLenum mode ) _mesa_debug(ctx, "glBlendEquation %s\n", _mesa_lookup_enum_by_nr(mode)); - if ( ! _mesa_validate_blend_equation( ctx, mode, GL_FALSE ) ) { + if (!legal_blend_equation(ctx, mode, GL_FALSE)) { _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); return; } - if ( (ctx->Color.BlendEquationRGB == mode) && - (ctx->Color.BlendEquationA == mode) ) + numBuffers = ctx->Extensions.ARB_draw_buffers_blend + ? ctx->Const.MaxDrawBuffers : 1; + + changed = GL_FALSE; + for (buf = 0; buf < numBuffers; buf++) { + if (ctx->Color.Blend[buf].EquationRGB != mode || + ctx->Color.Blend[buf].EquationA != mode) { + changed = GL_TRUE; + break; + } + } + if (!changed) return; FLUSH_VERTICES(ctx, _NEW_COLOR); - ctx->Color.BlendEquationRGB = mode; - ctx->Color.BlendEquationA = mode; + for (buf = 0; buf < numBuffers; buf++) { + ctx->Color.Blend[buf].EquationRGB = mode; + ctx->Color.Blend[buf].EquationA = mode; + } + ctx->Color._BlendEquationPerBuffer = GL_FALSE; if (ctx->Driver.BlendEquationSeparate) (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode ); } +/** + * Set blend equation for one color buffer/target. + */ +void GLAPIENTRY +_mesa_BlendEquationi(GLuint buf, GLenum mode) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n", + buf, _mesa_lookup_enum_by_nr(mode)); + + if (buf >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)", + buf); + return; + } + + if (!legal_blend_equation(ctx, mode, GL_FALSE)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi"); + return; + } + + if (ctx->Color.Blend[buf].EquationRGB == mode && + ctx->Color.Blend[buf].EquationA == mode) + return; /* no change */ + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.Blend[buf].EquationRGB = mode; + ctx->Color.Blend[buf].EquationA = mode; + ctx->Color._BlendEquationPerBuffer = GL_TRUE; + + if (ctx->Driver.BlendEquationSeparatei) + ctx->Driver.BlendEquationSeparatei(ctx, buf, mode, mode); +} + + void GLAPIENTRY _mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA ) { + GLuint buf, numBuffers; + GLboolean changed; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -286,29 +408,88 @@ _mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA ) return; } - if ( ! _mesa_validate_blend_equation( ctx, modeRGB, GL_TRUE ) ) { + if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) { _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)"); return; } - if ( ! _mesa_validate_blend_equation( ctx, modeA, GL_TRUE ) ) { + if (!legal_blend_equation(ctx, modeA, GL_TRUE)) { _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)"); return; } + numBuffers = ctx->Extensions.ARB_draw_buffers_blend + ? ctx->Const.MaxDrawBuffers : 1; - if ( (ctx->Color.BlendEquationRGB == modeRGB) && - (ctx->Color.BlendEquationA == modeA) ) + changed = GL_FALSE; + for (buf = 0; buf < numBuffers; buf++) { + if (ctx->Color.Blend[buf].EquationRGB != modeRGB || + ctx->Color.Blend[buf].EquationA != modeA) { + changed = GL_TRUE; + break; + } + } + if (!changed) return; FLUSH_VERTICES(ctx, _NEW_COLOR); - ctx->Color.BlendEquationRGB = modeRGB; - ctx->Color.BlendEquationA = modeA; + for (buf = 0; buf < numBuffers; buf++) { + ctx->Color.Blend[buf].EquationRGB = modeRGB; + ctx->Color.Blend[buf].EquationA = modeA; + } + ctx->Color._BlendEquationPerBuffer = GL_FALSE; if (ctx->Driver.BlendEquationSeparate) - (*ctx->Driver.BlendEquationSeparate)( ctx, modeRGB, modeA ); + ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA); } -#endif + + +/** + * Set separate blend equations for one color buffer/target. + */ +void +_mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBlendEquationSeparatei %u, %s %s\n", buf, + _mesa_lookup_enum_by_nr(modeRGB), + _mesa_lookup_enum_by_nr(modeA)); + + if (buf >= ctx->Const.MaxDrawBuffers) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)", + buf); + return; + } + + if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)"); + return; + } + + if (!legal_blend_equation(ctx, modeA, GL_TRUE)) { + _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)"); + return; + } + + if (ctx->Color.Blend[buf].EquationRGB == modeRGB && + ctx->Color.Blend[buf].EquationA == modeA) + return; /* no change */ + + FLUSH_VERTICES(ctx, _NEW_COLOR); + ctx->Color.Blend[buf].EquationRGB = modeRGB; + ctx->Color.Blend[buf].EquationA = modeA; + ctx->Color._BlendEquationPerBuffer = GL_TRUE; + + if (ctx->Driver.BlendEquationSeparatei) + ctx->Driver.BlendEquationSeparatei(ctx, buf, modeRGB, modeA); +} + + + +#endif /* _HAVE_FULL_GL */ /** @@ -593,6 +774,8 @@ _mesa_ClampColorARB(GLenum target, GLenum clamp) */ void _mesa_init_color( struct gl_context * ctx ) { + GLuint i; + /* Color buffer group */ ctx->Color.IndexMask = ~0u; memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask)); @@ -602,12 +785,14 @@ void _mesa_init_color( struct gl_context * ctx ) ctx->Color.AlphaFunc = GL_ALWAYS; ctx->Color.AlphaRef = 0; ctx->Color.BlendEnabled = 0x0; - ctx->Color.BlendSrcRGB = GL_ONE; - ctx->Color.BlendDstRGB = GL_ZERO; - ctx->Color.BlendSrcA = GL_ONE; - ctx->Color.BlendDstA = GL_ZERO; - ctx->Color.BlendEquationRGB = GL_FUNC_ADD; - ctx->Color.BlendEquationA = GL_FUNC_ADD; + for (i = 0; i < Elements(ctx->Color.Blend); i++) { + ctx->Color.Blend[i].SrcRGB = GL_ONE; + ctx->Color.Blend[i].DstRGB = GL_ZERO; + ctx->Color.Blend[i].SrcA = GL_ONE; + ctx->Color.Blend[i].DstA = GL_ZERO; + ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD; + ctx->Color.Blend[i].EquationA = GL_FUNC_ADD; + } ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 ); ctx->Color.IndexLogicOpEnabled = GL_FALSE; ctx->Color.ColorLogicOpEnabled = GL_FALSE; diff --git a/src/mesa/main/blend.h b/src/mesa/main/blend.h index f72c779f1a..39e7c9fd49 100644 --- a/src/mesa/main/blend.h +++ b/src/mesa/main/blend.h @@ -48,13 +48,30 @@ _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, extern void GLAPIENTRY +_mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor); + + +extern void GLAPIENTRY +_mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA); + + +extern void GLAPIENTRY _mesa_BlendEquation( GLenum mode ); extern void GLAPIENTRY +_mesa_BlendEquationi(GLuint buf, GLenum mode); + + +extern void GLAPIENTRY _mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA ); +extern void +_mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA); + + extern void GLAPIENTRY _mesa_BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h index 42d98a33a8..8fb9b4c6b7 100644 --- a/src/mesa/main/context.h +++ b/src/mesa/main/context.h @@ -320,7 +320,7 @@ do { \ */ #define RGBA_LOGICOP_ENABLED(CTX) \ ((CTX)->Color.ColorLogicOpEnabled || \ - ((CTX)->Color.BlendEnabled && (CTX)->Color.BlendEquationRGB == GL_LOGIC_OP)) + ((CTX)->Color.BlendEnabled && (CTX)->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) #endif /* CONTEXT_H */ diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index c62969e9b7..2eede4268c 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -635,10 +635,15 @@ struct dd_function_table { void (*BlendColor)(struct gl_context *ctx, const GLfloat color[4]); /** Set the blend equation */ void (*BlendEquationSeparate)(struct gl_context *ctx, GLenum modeRGB, GLenum modeA); + void (*BlendEquationSeparatei)(struct gl_context *ctx, GLuint buffer, + GLenum modeRGB, GLenum modeA); /** Specify pixel arithmetic */ void (*BlendFuncSeparate)(struct gl_context *ctx, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA); + void (*BlendFuncSeparatei)(struct gl_context *ctx, GLuint buffer, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA); /** Specify clear values for the color buffers */ void (*ClearColor)(struct gl_context *ctx, const GLfloat color[4]); /** Specify the clear value for the depth buffer */ diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 24404993c6..8ca1339c66 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -80,6 +80,7 @@ static const struct extension extension_table[] = { { "GL_ARB_depth_clamp", o(ARB_depth_clamp), GL }, { "GL_ARB_depth_texture", o(ARB_depth_texture), GL }, { "GL_ARB_draw_buffers", o(ARB_draw_buffers), GL }, + { "GL_ARB_draw_buffers_blend", o(ARB_draw_buffers_blend), GL }, { "GL_ARB_draw_elements_base_vertex", o(ARB_draw_elements_base_vertex), GL }, { "GL_ARB_draw_instanced", o(ARB_draw_instanced), GL }, { "GL_ARB_explicit_attrib_location", o(ARB_explicit_attrib_location), GL }, diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index ba273cef46..6f47eca28c 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -372,7 +372,7 @@ static const struct value_desc values[] = { API_OPENGL_BIT | API_OPENGLES_BIT | API_OPENGLES2_BIT, NO_EXTRA}, { GL_ALPHA_BITS, BUFFER_INT(Visual.alphaBits), extra_new_buffers }, { GL_BLEND, CONTEXT_BIT0(Color.BlendEnabled), NO_EXTRA }, - { GL_BLEND_SRC, CONTEXT_ENUM(Color.BlendSrcRGB), NO_EXTRA }, + { GL_BLEND_SRC, CONTEXT_ENUM(Color.Blend[0].SrcRGB), NO_EXTRA }, { GL_BLUE_BITS, BUFFER_INT(Visual.blueBits), extra_new_buffers }, { GL_COLOR_CLEAR_VALUE, CONTEXT_FIELD(Color.ClearColor[0], TYPE_FLOATN_4), NO_EXTRA }, { GL_COLOR_WRITEMASK, LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA }, @@ -435,15 +435,15 @@ static const struct value_desc values[] = { extra_ARB_texture_cube_map }, /* XXX: OES_texture_cube_map */ /* XXX: OES_blend_subtract */ - { GL_BLEND_SRC_RGB_EXT, CONTEXT_ENUM(Color.BlendSrcRGB), NO_EXTRA }, - { GL_BLEND_DST_RGB_EXT, CONTEXT_ENUM(Color.BlendDstRGB), NO_EXTRA }, - { GL_BLEND_SRC_ALPHA_EXT, CONTEXT_ENUM(Color.BlendSrcA), NO_EXTRA }, - { GL_BLEND_DST_ALPHA_EXT, CONTEXT_ENUM(Color.BlendDstA), NO_EXTRA }, + { GL_BLEND_SRC_RGB_EXT, CONTEXT_ENUM(Color.Blend[0].SrcRGB), NO_EXTRA }, + { GL_BLEND_DST_RGB_EXT, CONTEXT_ENUM(Color.Blend[0].DstRGB), NO_EXTRA }, + { GL_BLEND_SRC_ALPHA_EXT, CONTEXT_ENUM(Color.Blend[0].SrcA), NO_EXTRA }, + { GL_BLEND_DST_ALPHA_EXT, CONTEXT_ENUM(Color.Blend[0].DstA), NO_EXTRA }, /* GL_BLEND_EQUATION_RGB, which is what we're really after, is * defined identically to GL_BLEND_EQUATION. */ - { GL_BLEND_EQUATION, CONTEXT_ENUM(Color.BlendEquationRGB), NO_EXTRA }, - { GL_BLEND_EQUATION_ALPHA_EXT, CONTEXT_ENUM(Color.BlendEquationA), NO_EXTRA }, + { GL_BLEND_EQUATION, CONTEXT_ENUM(Color.Blend[0].EquationRGB), NO_EXTRA }, + { GL_BLEND_EQUATION_ALPHA_EXT, CONTEXT_ENUM(Color.Blend[0].EquationA), NO_EXTRA }, /* GL_ARB_texture_compression */ { GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA }, @@ -512,7 +512,7 @@ static const struct value_desc values[] = { { GL_ALPHA_TEST, CONTEXT_BOOL(Color.AlphaEnabled), NO_EXTRA }, { GL_ALPHA_TEST_FUNC, CONTEXT_ENUM(Color.AlphaFunc), NO_EXTRA }, { GL_ALPHA_TEST_REF, CONTEXT_FIELD(Color.AlphaRef, TYPE_FLOATN), NO_EXTRA }, - { GL_BLEND_DST, CONTEXT_ENUM(Color.BlendDstRGB), NO_EXTRA }, + { GL_BLEND_DST, CONTEXT_ENUM(Color.Blend[0].DstRGB), NO_EXTRA }, { GL_CLIP_PLANE0, CONTEXT_BIT0(Transform.ClipPlanesEnabled), NO_EXTRA }, { GL_CLIP_PLANE1, CONTEXT_BIT1(Transform.ClipPlanesEnabled), NO_EXTRA }, { GL_CLIP_PLANE2, CONTEXT_BIT2(Transform.ClipPlanesEnabled), NO_EXTRA }, diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 7b4c1161f5..55c5fd2b84 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -719,13 +719,20 @@ struct gl_colorbuffer_attrib */ /*@{*/ GLbitfield BlendEnabled; /**< Per-buffer blend enable flags */ - GLenum BlendSrcRGB; /**< Blending source operator */ - GLenum BlendDstRGB; /**< Blending destination operator */ - GLenum BlendSrcA; /**< GL_INGR_blend_func_separate */ - GLenum BlendDstA; /**< GL_INGR_blend_func_separate */ - GLenum BlendEquationRGB; /**< Blending equation */ - GLenum BlendEquationA; /**< GL_EXT_blend_equation_separate */ GLfloat BlendColor[4]; /**< Blending color */ + struct + { + GLenum SrcRGB; /**< RGB blend source term */ + GLenum DstRGB; /**< RGB blend dest term */ + GLenum SrcA; /**< Alpha blend source term */ + GLenum DstA; /**< Alpha blend dest term */ + GLenum EquationRGB; /**< GL_ADD, GL_SUBTRACT, etc. */ + GLenum EquationA; /**< GL_ADD, GL_SUBTRACT, etc. */ + } Blend[MAX_DRAW_BUFFERS]; + /** Are the blend func terms currently different for each buffer/target? */ + GLboolean _BlendFuncPerBuffer; + /** Are the blend equations currently different for each buffer/target? */ + GLboolean _BlendEquationPerBuffer; /*@}*/ /** @@ -2679,6 +2686,7 @@ struct gl_extensions GLboolean ARB_depth_clamp; GLboolean ARB_depth_texture; GLboolean ARB_draw_buffers; + GLboolean ARB_draw_buffers_blend; GLboolean ARB_draw_elements_base_vertex; GLboolean ARB_draw_instanced; GLboolean ARB_fragment_coord_conventions; |