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;