Roland Scheidegger wrote:Here's a patch. That << 8 is a bit ugly, though. Should I add theAh, missed that in the spec. Seems to be unnecessarily restrictive to not have a weighting factor for GL_MIN/MAX, apparently common hardware could do it just fine (or maybe it doesn't make enough sense to allow it?).
Modern hardware can, but that extension is almost 10 years old. I don't think hardware was quite as orthogonal back then. :)
unshifted blend func values to r200_reg.h, together with some proper defined shifts? I like the blend func value selection better than before (where there was a huge function where the second half is (almost) identical to the first). Fixes blendminmax indeed...
I've looked into it a bit further, it's strange. That R200_ENABLE_ALPHA_BLEND surely DOES something, but not quite what I'd expect. It doesn't affect the "logic op blending" (which is not unexpected probably), and not enabling it indeed seems to prevent actual blending calculations. But, if GL_MIN and GL_FUNC_REVERSE_SUBTRACT blending functions are used, the result seems to be always 0 (black) in that case. Odd.This does not explain though why the results are wrong if blending isn't enabled in the first place, since neither blend function nor blend equation should change anything if blending is disabled, I think.
Yeah, that's probably a different problem. :( The r200 may not have a way to actually disable blending. It might be that the hardware has to be set to an equation of GL_ADD and functions of GL_ONE and GL_ZERO. Dunno.
Someone (maybe with documentation) has any ideas?
If not I'll try Ian's suggestion and basically just set it back to the default blend func/equation whenever blending gets disabled (needs of course other minor code modifications).
Roland
Index: r200_state.c =================================================================== RCS file: /cvs/mesa/Mesa/src/mesa/drivers/dri/r200/r200_state.c,v retrieving revision 1.18 diff -u -r1.18 r200_state.c --- r200_state.c 21 Mar 2004 17:05:03 -0000 1.18 +++ r200_state.c 13 May 2004 00:19:29 -0000 @@ -104,156 +104,146 @@ rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc; } -static void r200BlendEquationSeparate( GLcontext *ctx, - GLenum modeRGB, GLenum modeA ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~R200_COMB_FCN_MASK; - - assert( modeRGB == modeA ); - - switch ( modeRGB ) { - case GL_FUNC_ADD: - case GL_LOGIC_OP: - b |= R200_COMB_FCN_ADD_CLAMP; - break; - - case GL_FUNC_SUBTRACT: - b |= R200_COMB_FCN_SUB_CLAMP; - break; - - case GL_FUNC_REVERSE_SUBTRACT: - b |= R200_COMB_FCN_RSUB_CLAMP; - break; - - case GL_MIN: - b |= R200_COMB_FCN_MIN; - break; - - case GL_MAX: - b |= R200_COMB_FCN_MAX; - break; - - default: - break; - } - - R200_STATECHANGE( rmesa, ctx ); - rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; - if ( ctx->Color._LogicOpEnabled ) { - rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE; - } else { - rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE; - } -} - -static void r200BlendFuncSeparate( GLcontext *ctx, - GLenum sfactorRGB, GLenum dfactorRGB, - GLenum sfactorA, GLenum dfactorA ) +/** + * 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 + * is already shifted for source factor, but needs to be reshifted for + * 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 ) { - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & - ~(R200_SRC_BLEND_MASK | R200_DST_BLEND_MASK); + int func; - switch ( ctx->Color.BlendSrcRGB ) { + switch ( factor ) { case GL_ZERO: - b |= R200_SRC_BLEND_GL_ZERO; + func = R200_SRC_BLEND_GL_ZERO; break; case GL_ONE: - b |= R200_SRC_BLEND_GL_ONE; + func = R200_SRC_BLEND_GL_ONE; break; case GL_DST_COLOR: - b |= R200_SRC_BLEND_GL_DST_COLOR; + func = R200_SRC_BLEND_GL_DST_COLOR; break; case GL_ONE_MINUS_DST_COLOR: - b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR; + func = R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR; break; case GL_SRC_COLOR: - b |= R200_SRC_BLEND_GL_SRC_COLOR; + func = R200_SRC_BLEND_GL_SRC_COLOR; break; case GL_ONE_MINUS_SRC_COLOR: - b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR; + func = R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR; break; case GL_SRC_ALPHA: - b |= R200_SRC_BLEND_GL_SRC_ALPHA; + func = R200_SRC_BLEND_GL_SRC_ALPHA; break; case GL_ONE_MINUS_SRC_ALPHA: - b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA; + func = R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA; break; case GL_DST_ALPHA: - b |= R200_SRC_BLEND_GL_DST_ALPHA; + func = R200_SRC_BLEND_GL_DST_ALPHA; break; case GL_ONE_MINUS_DST_ALPHA: - b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA; + func = R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA; break; case GL_SRC_ALPHA_SATURATE: - b |= R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE; + func = (is_src) ? R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE : R200_SRC_BLEND_GL_ZERO; break; case GL_CONSTANT_COLOR: - b |= R200_SRC_BLEND_GL_CONST_COLOR; + func = R200_SRC_BLEND_GL_CONST_COLOR; break; case GL_ONE_MINUS_CONSTANT_COLOR: - b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR; + func = R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR; break; case GL_CONSTANT_ALPHA: - b |= R200_SRC_BLEND_GL_CONST_ALPHA; + func = R200_SRC_BLEND_GL_CONST_ALPHA; break; case GL_ONE_MINUS_CONSTANT_ALPHA: - b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA; + func = R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA; break; default: - break; + func = (is_src) ? R200_SRC_BLEND_GL_ONE : R200_SRC_BLEND_GL_ZERO; } + return func; +} - switch ( ctx->Color.BlendDstRGB ) { - case GL_ZERO: - b |= R200_DST_BLEND_GL_ZERO; - break; - case GL_ONE: - b |= R200_DST_BLEND_GL_ONE; - break; - case GL_SRC_COLOR: - b |= R200_DST_BLEND_GL_SRC_COLOR; - break; - case GL_ONE_MINUS_SRC_COLOR: - b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR; - break; - case GL_SRC_ALPHA: - b |= R200_DST_BLEND_GL_SRC_ALPHA; - break; - case GL_ONE_MINUS_SRC_ALPHA: - b |= R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA; - break; - case GL_DST_COLOR: - b |= R200_DST_BLEND_GL_DST_COLOR; - break; - case GL_ONE_MINUS_DST_COLOR: - b |= R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR; - break; - case GL_DST_ALPHA: - b |= R200_DST_BLEND_GL_DST_ALPHA; - break; - case GL_ONE_MINUS_DST_ALPHA: - b |= R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA; +/** + * Sets both the blend equation and the blend function. + * 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 r200_set_blend_state( GLcontext * ctx ) +{ + r200ContextPtr rmesa = R200_CONTEXT(ctx); + /* GLuint blend = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & + ~(R200_COMB_FCN_MASK | R200_SRC_BLEND_MASK | R200_DST_BLEND_MASK); */ + + int func; + int eqn; + + assert( ctx->Color.BlendEquationRGB == ctx->Color.BlendEquationA ); + + func = blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) + | (blend_factor( ctx->Color.BlendDstRGB, GL_FALSE ) << 8); + + switch(ctx->Color.BlendEquationRGB) { + case GL_FUNC_ADD: + case GL_LOGIC_OP: + eqn = R200_COMB_FCN_ADD_CLAMP; break; - case GL_CONSTANT_COLOR: - b |= R200_DST_BLEND_GL_CONST_COLOR; + + case GL_FUNC_SUBTRACT: + eqn = R200_COMB_FCN_SUB_CLAMP; break; - case GL_ONE_MINUS_CONSTANT_COLOR: - b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR; + + case GL_FUNC_REVERSE_SUBTRACT: + eqn = R200_COMB_FCN_RSUB_CLAMP; break; - case GL_CONSTANT_ALPHA: - b |= R200_DST_BLEND_GL_CONST_ALPHA; + + case GL_MIN: + eqn = R200_COMB_FCN_MIN; + func = R200_SRC_BLEND_GL_ONE | R200_DST_BLEND_GL_ONE; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: - b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA; + + case GL_MAX: + eqn = R200_COMB_FCN_MAX; + func = R200_SRC_BLEND_GL_ONE | R200_DST_BLEND_GL_ONE; break; + default: - break; + fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n", + __func__, __LINE__, ctx->Color.BlendEquationRGB ); + return; } R200_STATECHANGE( rmesa, ctx ); - rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; + if ( ctx->Color._LogicOpEnabled ) { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ROP_ENABLE; + } else { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ROP_ENABLE; + } +} + +static void r200BlendEquationSeparate( GLcontext *ctx, + GLenum modeRGB, GLenum modeA ) +{ + r200_set_blend_state( ctx ); +} + +static void r200BlendFuncSeparate( GLcontext *ctx, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA ) +{ + r200_set_blend_state( ctx ); }