Added support for GL_EXT_blend_equation_separate and
authorIan Romanick <idr@us.ibm.com>
Wed, 12 May 2004 16:36:30 +0000 (16:36 +0000)
committerIan Romanick <idr@us.ibm.com>
Wed, 12 May 2004 16:36:30 +0000 (16:36 +0000)
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
src/mesa/drivers/dri/i830/i830_context.c
src/mesa/drivers/dri/i830/i830_state.c

index eab1092..fa6f407 100644 (file)
 #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
index b0236a5..d4d7c2c 100644 (file)
@@ -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
index 2f7ff9f..3fe645a 100644 (file)
@@ -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)