From c318d507170d1b7cec14b76647e93ab28fb93462 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 12 May 2004 16:36:30 +0000 Subject: [PATCH] Added support for GL_EXT_blend_equation_separate and GL_NV_blend_square. Fix a bug in the way the GL_MIN and GL_MAX blending modes were handled. --- src/mesa/drivers/dri/i830/i830_3d_reg.h | 2 + src/mesa/drivers/dri/i830/i830_context.c | 2 + src/mesa/drivers/dri/i830/i830_state.c | 373 +++++++++++------------ 3 files changed, 177 insertions(+), 200 deletions(-) diff --git a/src/mesa/drivers/dri/i830/i830_3d_reg.h b/src/mesa/drivers/dri/i830/i830_3d_reg.h index eab1092094c..fa6f407ef52 100644 --- a/src/mesa/drivers/dri/i830/i830_3d_reg.h +++ b/src/mesa/drivers/dri/i830/i830_3d_reg.h @@ -201,6 +201,8 @@ #define ENABLE_DST_ABLEND_FACTOR (1<<5) #define DST_ABLEND_FACT(x) (x) +#define BLEND_STATE_MASK (ALPHA_BLENDFUNC_MASK | SRC_DST_ABLEND_MASK) + #define BLENDFACT_ZERO 0x01 #define BLENDFACT_ONE 0x02 #define BLENDFACT_SRC_COLR 0x03 diff --git a/src/mesa/drivers/dri/i830/i830_context.c b/src/mesa/drivers/dri/i830/i830_context.c index b0236a5d618..d4d7c2c66dc 100644 --- a/src/mesa/drivers/dri/i830/i830_context.c +++ b/src/mesa/drivers/dri/i830/i830_context.c @@ -149,6 +149,7 @@ static const char * const card_extensions[] = "GL_ARB_texture_env_dot3", "GL_ARB_texture_mirrored_repeat", "GL_EXT_blend_color", + "GL_EXT_blend_equation_separate", "GL_EXT_blend_func_separate", "GL_EXT_blend_minmax", "GL_EXT_blend_subtract", @@ -161,6 +162,7 @@ static const char * const card_extensions[] = "GL_EXT_texture_filter_anisotropic", "GL_EXT_texture_lod_bias", "GL_EXT_texture_rectangle", + "GL_NV_blend_square", "GL_MESA_ycbcr_texture", "GL_SGIS_generate_mipmap", NULL diff --git a/src/mesa/drivers/dri/i830/i830_state.c b/src/mesa/drivers/dri/i830/i830_state.c index 2f7ff9f3a1a..3fe645aa8fd 100644 --- a/src/mesa/drivers/dri/i830/i830_state.c +++ b/src/mesa/drivers/dri/i830/i830_state.c @@ -311,30 +311,32 @@ static void i830EvalLogicOpBlendState(GLcontext *ctx) I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | + ENABLE_LOGIC_OP_MASK); + imesa->Setup[I830_CTXREG_IALPHAB] &= ~ENABLE_INDPT_ALPHA_BLEND; + if (ctx->Color.ColorLogicOpEnabled) { - imesa->Setup[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | - ENABLE_LOGIC_OP_MASK); imesa->Setup[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | ENABLE_LOGIC_OP); - imesa->Setup[I830_CTXREG_IALPHAB] &= ~ENABLE_INDPT_ALPHA_BLEND; imesa->Setup[I830_CTXREG_IALPHAB] |= DISABLE_INDPT_ALPHA_BLEND; } else if (ctx->Color.BlendEnabled) { - imesa->Setup[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | - ENABLE_LOGIC_OP_MASK); imesa->Setup[I830_CTXREG_ENABLES_1] |= (ENABLE_COLOR_BLEND | DISABLE_LOGIC_OP); - imesa->Setup[I830_CTXREG_IALPHAB] &= ~ENABLE_INDPT_ALPHA_BLEND; - if (imesa->Setup[I830_CTXREG_IALPHAB] & SRC_DST_ABLEND_MASK) { + + /* If the alpha blend state does not match the color blend state, + * enable independent alpha blending. Otherwise, leave it disabled + * and the hardware will use the color blend state for both. + */ + + if ( 0 && (imesa->Setup[I830_CTXREG_IALPHAB] & BLEND_STATE_MASK) + != (imesa->Setup[I830_CTXREG_STATE1] & BLEND_STATE_MASK) ) { imesa->Setup[I830_CTXREG_IALPHAB] |= ENABLE_INDPT_ALPHA_BLEND; } else { imesa->Setup[I830_CTXREG_IALPHAB] |= DISABLE_INDPT_ALPHA_BLEND; } } else { - imesa->Setup[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | - ENABLE_LOGIC_OP_MASK); imesa->Setup[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | DISABLE_LOGIC_OP); - imesa->Setup[I830_CTXREG_IALPHAB] &= ~ENABLE_INDPT_ALPHA_BLEND; imesa->Setup[I830_CTXREG_IALPHAB] |= DISABLE_INDPT_ALPHA_BLEND; } } @@ -359,238 +361,209 @@ static void i830BlendColor(GLcontext *ctx, const GLfloat color[4]) b); } -static void i830BlendEquationSeparate(GLcontext *ctx, - GLenum modeRGB, GLenum modeA) +/** + * Calculate the hardware blend factor setting. This same function is used + * for source and destination of both alpha and RGB. + * + * \returns + * The hardware register value for the specified blend factor. This value + * will need to be shifted into the correct position for either source or + * destination factor. + * + * \todo + * Since the two cases where source and destination are handled differently + * are essentially error cases, they should never happen. Determine if these + * cases can be removed. + */ +static int blend_factor( GLenum factor, GLboolean is_src ) { - i830ContextPtr imesa = I830_CONTEXT(ctx); - int func = ENABLE_ALPHA_BLENDFUNC; - - if (I830_DEBUG&DEBUG_DRI) - fprintf(stderr, "%s %s\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(modeRGB)); - - assert( modeRGB == modeA ); + int func; - /* This will catch a logicop blend equation */ - i830EvalLogicOpBlendState(ctx); - - switch(modeRGB) { - case GL_FUNC_ADD_EXT: - func |= BLENDFUNC_ADD; - break; - case GL_MIN_EXT: - func |= BLENDFUNC_MIN; - break; - case GL_MAX_EXT: - func |= BLENDFUNC_MAX; + switch( factor ) { + case GL_ZERO: + func = BLENDFACT_ZERO; break; - case GL_FUNC_SUBTRACT_EXT: - func |= BLENDFUNC_SUB; + case GL_ONE: + func = BLENDFACT_ONE; break; - case GL_FUNC_REVERSE_SUBTRACT_EXT: - func |= BLENDFUNC_RVRSE_SUB; + case GL_SRC_COLOR: + func = BLENDFACT_SRC_COLR; break; - default: return; - } - - I830_STATECHANGE(imesa, I830_UPLOAD_CTX); - imesa->Setup[I830_CTXREG_STATE1] &= ~BLENDFUNC_MASK; - imesa->Setup[I830_CTXREG_STATE1] |= func; - if (0) fprintf(stderr, "%s : STATE1 : 0x%08x\n", - __FUNCTION__, - imesa->Setup[I830_CTXREG_STATE1]); -} - -static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, - GLenum dfactorRGB, GLenum sfactorA, - GLenum dfactorA ) -{ - i830ContextPtr imesa = I830_CONTEXT(ctx); - int funcA = (ENABLE_SRC_ABLEND_FACTOR|ENABLE_DST_ABLEND_FACTOR); - int funcRGB = (ENABLE_SRC_BLND_FACTOR|ENABLE_DST_BLND_FACTOR); - - if (I830_DEBUG&DEBUG_DRI) - fprintf(stderr, "%s\n", __FUNCTION__); - - switch(sfactorA) { - case GL_ZERO: - funcA |= SRC_ABLEND_FACT(BLENDFACT_ZERO); + case GL_ONE_MINUS_SRC_COLOR: + func = BLENDFACT_INV_SRC_COLR; break; case GL_SRC_ALPHA: - funcA |= SRC_ABLEND_FACT(BLENDFACT_SRC_ALPHA); - break; - case GL_ONE: - funcA |= SRC_ABLEND_FACT(BLENDFACT_ONE); - break; - case GL_DST_COLOR: - funcA |= SRC_ABLEND_FACT(BLENDFACT_DST_COLR); - break; - case GL_ONE_MINUS_DST_COLOR: - funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_DST_COLR); + func = BLENDFACT_SRC_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: - funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_SRC_ALPHA); + func = BLENDFACT_INV_SRC_ALPHA; break; case GL_DST_ALPHA: - funcA |= SRC_ABLEND_FACT(BLENDFACT_DST_ALPHA); + func = BLENDFACT_DST_ALPHA; break; case GL_ONE_MINUS_DST_ALPHA: - funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_DST_ALPHA); - break; - case GL_SRC_ALPHA_SATURATE: - funcA |= SRC_ABLEND_FACT(BLENDFACT_SRC_ALPHA_SATURATE); - break; - case GL_CONSTANT_COLOR_EXT: - funcA |= SRC_ABLEND_FACT(BLENDFACT_CONST_COLOR); - break; - case GL_ONE_MINUS_CONSTANT_COLOR_EXT: - funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_CONST_COLOR); - break; - case GL_CONSTANT_ALPHA_EXT: - funcA |= SRC_ABLEND_FACT(BLENDFACT_CONST_ALPHA); - break; - case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: - funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_CONST_ALPHA); - break; - default: return; - } - - switch(dfactorA) { - case GL_SRC_ALPHA: - funcA |= DST_ABLEND_FACT(BLENDFACT_SRC_ALPHA); - break; - case GL_ONE_MINUS_SRC_ALPHA: - funcA |= DST_ABLEND_FACT(BLENDFACT_INV_SRC_ALPHA); - break; - case GL_ZERO: - funcA |= DST_ABLEND_FACT(BLENDFACT_ZERO); - break; - case GL_ONE: - funcA |= DST_ABLEND_FACT(BLENDFACT_ONE); - break; - case GL_SRC_COLOR: - funcA |= DST_ABLEND_FACT(BLENDFACT_SRC_COLR); - break; - case GL_ONE_MINUS_SRC_COLOR: - funcA |= DST_ABLEND_FACT(BLENDFACT_INV_SRC_COLR); - break; - case GL_DST_ALPHA: - funcA |= DST_ABLEND_FACT(BLENDFACT_DST_ALPHA); - break; - case GL_ONE_MINUS_DST_ALPHA: - funcA |= DST_ABLEND_FACT(BLENDFACT_INV_DST_ALPHA); - break; - case GL_CONSTANT_COLOR_EXT: - funcA |= DST_ABLEND_FACT(BLENDFACT_CONST_COLOR); - break; - case GL_ONE_MINUS_CONSTANT_COLOR_EXT: - funcA |= DST_ABLEND_FACT(BLENDFACT_INV_CONST_COLOR); - break; - case GL_CONSTANT_ALPHA_EXT: - funcA |= DST_ABLEND_FACT(BLENDFACT_CONST_ALPHA); - break; - case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: - funcA |= DST_ABLEND_FACT(BLENDFACT_INV_CONST_ALPHA); - break; - default: return; - } - - switch(sfactorRGB) { - case GL_ZERO: - funcRGB |= SRC_BLND_FACT(BLENDFACT_ZERO); - break; - case GL_SRC_ALPHA: - funcRGB |= SRC_BLND_FACT(BLENDFACT_SRC_ALPHA); - break; - case GL_ONE: - funcRGB |= SRC_BLND_FACT(BLENDFACT_ONE); + func = BLENDFACT_INV_DST_ALPHA; break; case GL_DST_COLOR: - funcRGB |= SRC_BLND_FACT(BLENDFACT_DST_COLR); + func = BLENDFACT_DST_COLR; break; case GL_ONE_MINUS_DST_COLOR: - funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_DST_COLR); - break; - case GL_ONE_MINUS_SRC_ALPHA: - funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_SRC_ALPHA); - break; - case GL_DST_ALPHA: - funcRGB |= SRC_BLND_FACT(BLENDFACT_DST_ALPHA); - break; - case GL_ONE_MINUS_DST_ALPHA: - funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_DST_ALPHA); + func = BLENDFACT_INV_DST_COLR; break; case GL_SRC_ALPHA_SATURATE: - funcRGB |= SRC_BLND_FACT(BLENDFACT_SRC_ALPHA_SATURATE); + func = (is_src) ? BLENDFACT_SRC_ALPHA_SATURATE : BLENDFACT_ZERO; break; - case GL_CONSTANT_COLOR_EXT: - funcRGB |= SRC_BLND_FACT(BLENDFACT_CONST_COLOR); + case GL_CONSTANT_COLOR: + func = BLENDFACT_CONST_COLOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR_EXT: - funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_CONST_COLOR); + case GL_ONE_MINUS_CONSTANT_COLOR: + func = BLENDFACT_INV_CONST_COLOR; break; - case GL_CONSTANT_ALPHA_EXT: - funcRGB |= SRC_BLND_FACT(BLENDFACT_CONST_ALPHA); + case GL_CONSTANT_ALPHA: + func = BLENDFACT_CONST_ALPHA; break; - case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: - funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_CONST_ALPHA); + case GL_ONE_MINUS_CONSTANT_ALPHA: + func = BLENDFACT_INV_CONST_ALPHA; break; - default: return; + default: + func = (is_src) ? BLENDFACT_ONE : BLENDFACT_ZERO; } - - switch(dfactorRGB) { - case GL_SRC_ALPHA: - funcRGB |= DST_BLND_FACT(BLENDFACT_SRC_ALPHA); - break; - case GL_ONE_MINUS_SRC_ALPHA: - funcRGB |= DST_BLND_FACT(BLENDFACT_INV_SRC_ALPHA); + + return func; +} + + +/** + * Sets both the blend equation (called "function" in i830 docs) and the + * blend function (called "factor" in i830 docs). This is done in a single + * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX) + * change the interpretation of the blend function. + */ + +static void i830_set_blend_state( GLcontext * ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int funcA; + int funcRGB; + int eqnA; + int eqnRGB; + + + funcRGB = SRC_BLND_FACT( blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) ) + | DST_BLND_FACT( blend_factor( ctx->Color.BlendDstRGB, GL_FALSE ) ); + + switch(ctx->Color.BlendEquationRGB) { + case GL_FUNC_ADD: + eqnRGB = BLENDFUNC_ADD; break; - case GL_ZERO: - funcRGB |= DST_BLND_FACT(BLENDFACT_ZERO); + case GL_MIN: + eqnRGB = BLENDFUNC_MIN; + funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); break; - case GL_ONE: - funcRGB |= DST_BLND_FACT(BLENDFACT_ONE); + case GL_MAX: + eqnRGB = BLENDFUNC_MAX; + funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); break; - case GL_SRC_COLOR: - funcRGB |= DST_BLND_FACT(BLENDFACT_SRC_COLR); + case GL_FUNC_SUBTRACT: + eqnRGB = BLENDFUNC_SUB; break; - case GL_ONE_MINUS_SRC_COLOR: - funcRGB |= DST_BLND_FACT(BLENDFACT_INV_SRC_COLR); + case GL_FUNC_REVERSE_SUBTRACT: + eqnRGB = BLENDFUNC_RVRSE_SUB; break; - case GL_DST_ALPHA: - funcRGB |= DST_BLND_FACT(BLENDFACT_DST_ALPHA); - break; - case GL_ONE_MINUS_DST_ALPHA: - funcRGB |= DST_BLND_FACT(BLENDFACT_INV_DST_ALPHA); + default: + fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n", + __func__, __LINE__, ctx->Color.BlendEquationRGB ); + return; + } + + + funcA = SRC_ABLEND_FACT( blend_factor( ctx->Color.BlendSrcA, GL_TRUE ) ) + | DST_ABLEND_FACT( blend_factor( ctx->Color.BlendDstA, GL_FALSE ) ); + + switch(ctx->Color.BlendEquationA) { + case GL_FUNC_ADD: + eqnA = BLENDFUNC_ADD; break; - case GL_CONSTANT_COLOR_EXT: - funcRGB |= DST_BLND_FACT(BLENDFACT_CONST_COLOR); + case GL_MIN: + eqnA = BLENDFUNC_MIN; + funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); break; - case GL_ONE_MINUS_CONSTANT_COLOR_EXT: - funcRGB |= DST_BLND_FACT(BLENDFACT_INV_CONST_COLOR); + case GL_MAX: + eqnA = BLENDFUNC_MAX; + funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); break; - case GL_CONSTANT_ALPHA_EXT: - funcRGB |= DST_BLND_FACT(BLENDFACT_CONST_ALPHA); + case GL_FUNC_SUBTRACT: + eqnA = BLENDFUNC_SUB; break; - case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: - funcRGB |= DST_BLND_FACT(BLENDFACT_INV_CONST_ALPHA); + case GL_FUNC_REVERSE_SUBTRACT: + eqnA = BLENDFUNC_RVRSE_SUB; break; - default: return; + default: + fprintf( stderr, "[%s:%u] Invalid alpha blend equation (0x%04x).\n", + __func__, __LINE__, ctx->Color.BlendEquationA ); + return; } I830_STATECHANGE(imesa, I830_UPLOAD_CTX); - imesa->Setup[I830_CTXREG_IALPHAB] &= ~SRC_DST_ABLEND_MASK; - imesa->Setup[I830_CTXREG_STATE1] &= ~SRC_DST_BLND_MASK; - imesa->Setup[I830_CTXREG_STATE1] |= funcRGB; - if ( (dfactorRGB != dfactorA) || (sfactorRGB != sfactorA) ) { - imesa->Setup[I830_CTXREG_IALPHAB] |= funcA; - } + imesa->Setup[I830_CTXREG_STATE1] = eqnRGB | funcRGB + | STATE3D_MODES_1_CMD + | ENABLE_SRC_BLND_FACTOR | ENABLE_DST_BLND_FACTOR + | ENABLE_COLR_BLND_FUNC; + + imesa->Setup[I830_CTXREG_IALPHAB] = eqnA | funcA + | STATE3D_INDPT_ALPHA_BLEND_CMD + | ENABLE_SRC_ABLEND_FACTOR | ENABLE_DST_ABLEND_FACTOR + | ENABLE_ALPHA_BLENDFUNC; - /* Ensure Independant Alpha Blend is really in the correct state (either - * enabled or disabled) if blending is already enabled. + + /* This will catch a logicop blend equation. It will also ensure + * independant alpha blend is really in the correct state (either enabled + * or disabled) if blending is already enabled. */ + i830EvalLogicOpBlendState(ctx); + + if (0) { + fprintf(stderr, "[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n", + __func__, __LINE__, + imesa->Setup[I830_CTXREG_STATE1], + imesa->Setup[I830_CTXREG_IALPHAB], + (ctx->Color.BlendEnabled) ? "en" : "dis"); + } +} + +static void i830BlendEquationSeparate(GLcontext *ctx, + GLenum modeRGB, GLenum modeA) +{ + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s -> %s, %s\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(modeRGB), + _mesa_lookup_enum_by_nr(modeA)); + + (void) modeRGB; + (void) modeA; + i830_set_blend_state( ctx ); +} + + + +static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, + GLenum dfactorRGB, GLenum sfactorA, + GLenum dfactorA ) +{ + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s -> RGB(%s, %s) A(%s, %s)\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(sfactorRGB), + _mesa_lookup_enum_by_nr(dfactorRGB), + _mesa_lookup_enum_by_nr(sfactorA), + _mesa_lookup_enum_by_nr(dfactorA)); + + (void) sfactorRGB; + (void) dfactorRGB; + (void) sfactorA; + (void) dfactorA; + i830_set_blend_state( ctx ); } static void i830DepthFunc(GLcontext *ctx, GLenum func) -- 2.30.2