Fix GL_MIN and GL_MAX blend equations (set blend factors accordingly). Fix errors when blending is disabled (set blend equation and function to default values).
diff --git a/src/mesa/drivers/dri/r200/r200_reg.h b/src/mesa/drivers/dri/r200/r200_reg.h
index 8e91263..685fc5c 100644
--- a/src/mesa/drivers/dri/r200/r200_reg.h
+++ b/src/mesa/drivers/dri/r200/r200_reg.h
@@ -69,39 +69,26 @@
#define R200_COMB_FCN_MAX (5 << 12)
#define R200_COMB_FCN_RSUB_CLAMP (6 << 12)
#define R200_COMB_FCN_RSUB_NOCLAMP (7 << 12)
-#define R200_SRC_BLEND_GL_ZERO (32 << 16)
-#define R200_SRC_BLEND_GL_ONE (33 << 16)
-#define R200_SRC_BLEND_GL_SRC_COLOR (34 << 16)
-#define R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16)
-#define R200_SRC_BLEND_GL_DST_COLOR (36 << 16)
-#define R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16)
-#define R200_SRC_BLEND_GL_SRC_ALPHA (38 << 16)
-#define R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16)
-#define R200_SRC_BLEND_GL_DST_ALPHA (40 << 16)
-#define R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16)
-#define R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16)
-#define R200_SRC_BLEND_GL_CONST_COLOR (43 << 16)
-#define R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR (44 << 16)
-#define R200_SRC_BLEND_GL_CONST_ALPHA (45 << 16)
-#define R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA (46 << 16)
-#define R200_SRC_BLEND_MASK (63 << 16)
-#define R200_DST_BLEND_GL_ZERO (32 << 24)
-#define R200_DST_BLEND_GL_ONE (33 << 24)
-#define R200_DST_BLEND_GL_SRC_COLOR (34 << 24)
-#define R200_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24)
-#define R200_DST_BLEND_GL_DST_COLOR (36 << 24)
-#define R200_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24)
-#define R200_DST_BLEND_GL_SRC_ALPHA (38 << 24)
-#define R200_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24)
-#define R200_DST_BLEND_GL_DST_ALPHA (40 << 24)
-#define R200_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24)
-#define R200_DST_BLEND_GL_CONST_COLOR (43 << 24)
-#define R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR (44 << 24)
-#define R200_DST_BLEND_GL_CONST_ALPHA (45 << 24)
-#define R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA (46 << 24)
-#define R200_DST_BLEND_MASK (63 << 24)
-#define R200_RB3D_DEPTHOFFSET 0x1c24
-#define R200_RB3D_DEPTHPITCH 0x1c28
+#define R200_BLEND_GL_ZERO (32)
+#define R200_BLEND_GL_ONE (33)
+#define R200_BLEND_GL_SRC_COLOR (34)
+#define R200_BLEND_GL_ONE_MINUS_SRC_COLOR (35)
+#define R200_BLEND_GL_DST_COLOR (36)
+#define R200_BLEND_GL_ONE_MINUS_DST_COLOR (37)
+#define R200_BLEND_GL_SRC_ALPHA (38)
+#define R200_BLEND_GL_ONE_MINUS_SRC_ALPHA (39)
+#define R200_BLEND_GL_DST_ALPHA (40)
+#define R200_BLEND_GL_ONE_MINUS_DST_ALPHA (41)
+#define R200_BLEND_GL_SRC_ALPHA_SATURATE (42) /* src factor only */
+#define R200_BLEND_GL_CONST_COLOR (43)
+#define R200_BLEND_GL_ONE_MINUS_CONST_COLOR (44)
+#define R200_BLEND_GL_CONST_ALPHA (45)
+#define R200_BLEND_GL_ONE_MINUS_CONST_ALPHA (46)
+#define R200_BLEND_MASK (63)
+#define R200_SRC_BLEND_SHIFT (16)
+#define R200_DST_BLEND_SHIFT (24)
+#define R200_RB3D_DEPTHOFFSET 0x1c24
+#define R200_RB3D_DEPTHPITCH 0x1c28
#define R200_DEPTHPITCH_MASK 0x00001ff8
#define R200_DEPTH_ENDIAN_NO_SWAP (0 << 18)
#define R200_DEPTH_ENDIAN_WORD_SWAP (1 << 18)
diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c
index 1dd352a..70ce8b4 100644
--- a/src/mesa/drivers/dri/r200/r200_state.c
+++ b/src/mesa/drivers/dri/r200/r200_state.c
@@ -104,156 +104,160 @@
rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
}
-static void r200BlendEquationSeparate( 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 )
+{
+ int func;
+
+ switch ( factor ) {
+ case GL_ZERO:
+ func = R200_BLEND_GL_ZERO;
+ break;
+ case GL_ONE:
+ func = R200_BLEND_GL_ONE;
+ break;
+ case GL_DST_COLOR:
+ func = R200_BLEND_GL_DST_COLOR;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ func = R200_BLEND_GL_ONE_MINUS_DST_COLOR;
+ break;
+ case GL_SRC_COLOR:
+ func = R200_BLEND_GL_SRC_COLOR;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR;
+ break;
+ case GL_SRC_ALPHA:
+ func = R200_BLEND_GL_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA;
+ break;
+ case GL_DST_ALPHA:
+ func = R200_BLEND_GL_DST_ALPHA;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO;
+ break;
+ case GL_CONSTANT_COLOR:
+ func = R200_BLEND_GL_CONST_COLOR;
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR;
+ break;
+ case GL_CONSTANT_ALPHA:
+ func = R200_BLEND_GL_CONST_ALPHA;
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA;
+ break;
+ default:
+ func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO;
+ }
+ return func;
+}
+
+/**
+ * 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.
+ * Also, make sure that blend function and blend equation are set to their default
+ * value if color blending is not enabled, since at least blend equations GL_MIN
+ * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
+ * unknown reasons.
+ */
+static void r200_set_blend_state( GLcontext * ctx )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~R200_COMB_FCN_MASK;
+ GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &
+ ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE);
- assert( modeRGB == modeA );
+ int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
+ (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
+ int eqn = R200_COMB_FCN_ADD_CLAMP;
- switch ( modeRGB ) {
+ R200_STATECHANGE( rmesa, ctx );
+
+ if (ctx->Color._LogicOpEnabled) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE;
+ rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
+ return;
+ } else if (ctx->Color.BlendEnabled) {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE;
+ }
+ else {
+ rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
+ rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
+ return;
+ }
+
+ func = (blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
+ (blend_factor( ctx->Color.BlendDstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT);
+
+ switch(ctx->Color.BlendEquationRGB) {
case GL_FUNC_ADD:
case GL_LOGIC_OP:
- b |= R200_COMB_FCN_ADD_CLAMP;
+ eqn = R200_COMB_FCN_ADD_CLAMP;
break;
case GL_FUNC_SUBTRACT:
- b |= R200_COMB_FCN_SUB_CLAMP;
+ eqn = R200_COMB_FCN_SUB_CLAMP;
break;
case GL_FUNC_REVERSE_SUBTRACT:
- b |= R200_COMB_FCN_RSUB_CLAMP;
+ eqn = R200_COMB_FCN_RSUB_CLAMP;
break;
case GL_MIN:
- b |= R200_COMB_FCN_MIN;
+ eqn = R200_COMB_FCN_MIN;
+ func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
+ (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
break;
case GL_MAX:
- b |= R200_COMB_FCN_MAX;
+ eqn = R200_COMB_FCN_MAX;
+ func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
+ (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
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;
- 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;
- }
+ rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func;
+}
+
+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 )
{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
- GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
- ~(R200_SRC_BLEND_MASK | R200_DST_BLEND_MASK);
-
- switch ( ctx->Color.BlendSrcRGB ) {
- case GL_ZERO:
- b |= R200_SRC_BLEND_GL_ZERO;
- break;
- case GL_ONE:
- b |= R200_SRC_BLEND_GL_ONE;
- break;
- case GL_DST_COLOR:
- b |= R200_SRC_BLEND_GL_DST_COLOR;
- break;
- case GL_ONE_MINUS_DST_COLOR:
- b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
- break;
- case GL_SRC_COLOR:
- b |= R200_SRC_BLEND_GL_SRC_COLOR;
- break;
- case GL_ONE_MINUS_SRC_COLOR:
- b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
- break;
- case GL_SRC_ALPHA:
- b |= R200_SRC_BLEND_GL_SRC_ALPHA;
- break;
- case GL_ONE_MINUS_SRC_ALPHA:
- b |= R200_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
- break;
- case GL_DST_ALPHA:
- b |= R200_SRC_BLEND_GL_DST_ALPHA;
- break;
- case GL_ONE_MINUS_DST_ALPHA:
- b |= R200_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
- break;
- case GL_SRC_ALPHA_SATURATE:
- b |= R200_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
- break;
- case GL_CONSTANT_COLOR:
- b |= R200_SRC_BLEND_GL_CONST_COLOR;
- break;
- case GL_ONE_MINUS_CONSTANT_COLOR:
- b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_COLOR;
- break;
- case GL_CONSTANT_ALPHA:
- b |= R200_SRC_BLEND_GL_CONST_ALPHA;
- break;
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- b |= R200_SRC_BLEND_GL_ONE_MINUS_CONST_ALPHA;
- break;
- default:
- break;
- }
-
- 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;
- break;
- case GL_CONSTANT_COLOR:
- b |= R200_DST_BLEND_GL_CONST_COLOR;
- break;
- case GL_ONE_MINUS_CONSTANT_COLOR:
- b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_COLOR;
- break;
- case GL_CONSTANT_ALPHA:
- b |= R200_DST_BLEND_GL_CONST_ALPHA;
- break;
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- b |= R200_DST_BLEND_GL_ONE_MINUS_CONST_ALPHA;
- break;
- default:
- break;
- }
-
- R200_STATECHANGE( rmesa, ctx );
- rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
+ r200_set_blend_state( ctx );
}
@@ -1738,17 +1742,8 @@
break;
case GL_BLEND:
- R200_STATECHANGE( rmesa, ctx );
- if (state) {
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_ALPHA_BLEND_ENABLE;
- } else {
- rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_ALPHA_BLEND_ENABLE;
- }
- 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;
- }
+ case GL_COLOR_LOGIC_OP:
+ r200_set_blend_state( ctx );
break;
case GL_CLIP_PLANE0:
@@ -1864,15 +1859,6 @@
}
break;
- case GL_COLOR_LOGIC_OP:
- R200_STATECHANGE( rmesa, ctx );
- 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;
- }
- break;
-
case GL_NORMALIZE:
R200_STATECHANGE( rmesa, tcl );
if ( state ) {
diff --git a/src/mesa/drivers/dri/r200/r200_state_init.c b/src/mesa/drivers/dri/r200/r200_state_init.c
index d9896c9..4e073f2 100644
--- a/src/mesa/drivers/dri/r200/r200_state_init.c
+++ b/src/mesa/drivers/dri/r200/r200_state_init.c
@@ -367,8 +367,8 @@
rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000;
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP |
- R200_SRC_BLEND_GL_ONE |
- R200_DST_BLEND_GL_ZERO );
+ (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
+ (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT));
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] =
rmesa->r200Screen->depthOffset + rmesa->r200Screen->fbLocation;