Added support for EXT_blend_equation_separate / ATI_blend_equation_separate.
The internal driver interface was also changed to use
BlendEquationSeparate instead of BlendEquation.
diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
index 3c638be..8da537d 100644
--- a/src/mesa/drivers/common/driverfuncs.c
+++ b/src/mesa/drivers/common/driverfuncs.c
@@ -115,7 +115,7 @@
    /* simple state commands */
    driver->AlphaFunc = NULL;
    driver->BlendColor = NULL;
-   driver->BlendEquation = NULL;
+   driver->BlendEquationSeparate = NULL;
    driver->BlendFuncSeparate = NULL;
    driver->ClearColor = NULL;
    driver->ClearDepth = NULL;
diff --git a/src/mesa/drivers/dri/ffb/ffb_state.c b/src/mesa/drivers/dri/ffb/ffb_state.c
index ddda946..eef7af4 100644
--- a/src/mesa/drivers/dri/ffb/ffb_state.c
+++ b/src/mesa/drivers/dri/ffb/ffb_state.c
@@ -93,13 +93,16 @@
 	}
 }
 
-static void ffbDDBlendEquation(GLcontext *ctx, GLenum mode)
+static void ffbDDBlendEquationSeparate(GLcontext *ctx, 
+				       GLenum modeRGB, GLenum modeA)
 {
 
 #ifdef STATE_TRACE
-	fprintf(stderr, "ffbDDBlendEquation: mode(%s)\n", _mesa_lookup_enum_by_nr(mode));
+	fprintf(stderr, "ffbDDBlendEquation: mode(%s)\n", 
+		_mesa_lookup_enum_by_nr(modeRGB));
 #endif
-	FALLBACK( ctx, (mode != GL_FUNC_ADD_EXT), FFB_BADATTR_BLENDEQN);
+	assert( modeRGB == modeA );
+	FALLBACK( ctx, (modeRGB != GL_FUNC_ADD), FFB_BADATTR_BLENDEQN);
 }
 
 static void ffbDDBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,
@@ -1052,7 +1055,7 @@
 
 	ctx->Driver.Enable = ffbDDEnable;
 	ctx->Driver.AlphaFunc = ffbDDAlphaFunc;
-	ctx->Driver.BlendEquation = ffbDDBlendEquation;
+	ctx->Driver.BlendEquationSeparate = ffbDDBlendEquationSeparate;
 	ctx->Driver.BlendFuncSeparate = ffbDDBlendFuncSeparate;
 	ctx->Driver.DepthFunc = ffbDDDepthFunc;
 	ctx->Driver.DepthMask = ffbDDDepthMask;
diff --git a/src/mesa/drivers/dri/gamma/gamma_state.c b/src/mesa/drivers/dri/gamma/gamma_state.c
index 519c707..813ced4 100644
--- a/src/mesa/drivers/dri/gamma/gamma_state.c
+++ b/src/mesa/drivers/dri/gamma/gamma_state.c
@@ -177,10 +177,12 @@
    gmesa->new_state |= GAMMA_NEW_ALPHA;
 }
 
-static void gammaDDBlendEquation( GLcontext *ctx, GLenum mode )
+static void gammaDDBlendEquationSeparate( GLcontext *ctx, 
+					  GLenum modeRGB, GLenum modeA )
 {
    gammaContextPtr gmesa = GAMMA_CONTEXT(ctx);
 
+   assert( modeRGB == modeA );
    FLUSH_BATCH( gmesa );
 
    gmesa->new_state |= GAMMA_NEW_ALPHA;
@@ -1689,7 +1691,7 @@
    ctx->Driver.ColorMask		= gammaDDColorMask;
 
    ctx->Driver.AlphaFunc		= gammaDDAlphaFunc;
-   ctx->Driver.BlendEquation		= gammaDDBlendEquation;
+   ctx->Driver.BlendEquationSeparate	= gammaDDBlendEquationSeparate;
    ctx->Driver.BlendFuncSeparate	= gammaDDBlendFuncSeparate;
    ctx->Driver.ClearDepth		= gammaDDClearDepth;
    ctx->Driver.CullFace			= gammaDDCullFace;
diff --git a/src/mesa/drivers/dri/i810/i810state.c b/src/mesa/drivers/dri/i810/i810state.c
index 9249d08..e00af65 100644
--- a/src/mesa/drivers/dri/i810/i810state.c
+++ b/src/mesa/drivers/dri/i810/i810state.c
@@ -75,10 +75,14 @@
    imesa->Setup[I810_CTXREG_ZA] |= a;
 }
 
-static void i810BlendEquation(GLcontext *ctx, GLenum mode)
+static void i810BlendEquationSeparate(GLcontext *ctx,
+				      GLenum modeRGB, GLenum modeA)
 {
+   assert( modeRGB == modeA );
+
    /* Can only do GL_ADD equation in hardware */
-   FALLBACK( I810_CONTEXT(ctx), I810_FALLBACK_BLEND_EQ, mode != GL_FUNC_ADD_EXT);
+   FALLBACK( I810_CONTEXT(ctx), I810_FALLBACK_BLEND_EQ, 
+	     modeRGB != GL_FUNC_ADD);
 
    /* BlendEquation sets ColorLogicOpEnabled in an unexpected
     * manner.
@@ -961,7 +965,7 @@
    /* API callbacks
     */
    ctx->Driver.AlphaFunc = i810AlphaFunc;
-   ctx->Driver.BlendEquation = i810BlendEquation;
+   ctx->Driver.BlendEquationSeparate = i810BlendEquationSeparate;
    ctx->Driver.BlendFuncSeparate = i810BlendFuncSeparate;
    ctx->Driver.ClearColor = i810ClearColor;
    ctx->Driver.ColorMask = i810ColorMask;
diff --git a/src/mesa/drivers/dri/i830/i830_state.c b/src/mesa/drivers/dri/i830/i830_state.c
index 9e8952f..7c80e8b 100644
--- a/src/mesa/drivers/dri/i830/i830_state.c
+++ b/src/mesa/drivers/dri/i830/i830_state.c
@@ -359,19 +359,22 @@
 					  b);
 }
 
-static void i830BlendEquation(GLcontext *ctx, GLenum mode) 
+static void i830BlendEquationSeparate(GLcontext *ctx,
+				      GLenum modeRGB, GLenum modeA)
 {
    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(mode));
+	     _mesa_lookup_enum_by_nr(modeRGB));
+
+   assert( modeRGB == modeA );
 
    /* This will catch a logicop blend equation */
    i830EvalLogicOpBlendState(ctx);
 
-   switch(mode) {
+   switch(modeRGB) {
    case GL_FUNC_ADD_EXT: 
       func |= BLENDFUNC_ADD; 
       break;
@@ -1643,7 +1646,7 @@
    /* API callbacks
     */
    ctx->Driver.AlphaFunc = i830AlphaFunc;
-   ctx->Driver.BlendEquation = i830BlendEquation;
+   ctx->Driver.BlendEquationSeparate = i830BlendEquationSeparate;
    ctx->Driver.BlendFuncSeparate = i830BlendFuncSeparate;
    ctx->Driver.BlendColor = i830BlendColor;
    ctx->Driver.ClearColor = i830ClearColor;
diff --git a/src/mesa/drivers/dri/mga/mgastate.c b/src/mesa/drivers/dri/mga/mgastate.c
index 6e03918..47c425d 100644
--- a/src/mesa/drivers/dri/mga/mgastate.c
+++ b/src/mesa/drivers/dri/mga/mgastate.c
@@ -124,8 +124,10 @@
              mmesa->hw.blend_func == (AC_src_src_alpha_sat | AC_dst_zero) );
 }
 
-static void mgaDDBlendEquation(GLcontext *ctx, GLenum mode)
+static void mgaDDBlendEquationSeparate(GLcontext *ctx, 
+				       GLenum modeRGB, GLenum modeA)
 {
+   assert( modeRGB == modeA );
    updateBlendLogicOp( ctx );
 }
 
@@ -1193,7 +1195,7 @@
    ctx->Driver.Enable = mgaDDEnable;
    ctx->Driver.LightModelfv = mgaDDLightModelfv;
    ctx->Driver.AlphaFunc = mgaDDAlphaFunc;
-   ctx->Driver.BlendEquation = mgaDDBlendEquation;
+   ctx->Driver.BlendEquationSeparate = mgaDDBlendEquationSeparate;
    ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate;
    ctx->Driver.DepthFunc = mgaDDDepthFunc;
    ctx->Driver.DepthMask = mgaDDDepthMask;
diff --git a/src/mesa/drivers/dri/r128/r128_state.c b/src/mesa/drivers/dri/r128/r128_state.c
index 0be7b1b..8ed63da 100644
--- a/src/mesa/drivers/dri/r128/r128_state.c
+++ b/src/mesa/drivers/dri/r128/r128_state.c
@@ -191,10 +191,12 @@
    rmesa->new_state |= R128_NEW_ALPHA;
 }
 
-static void r128DDBlendEquation( GLcontext *ctx, GLenum mode )
+static void r128DDBlendEquationSeparate( GLcontext *ctx, 
+					 GLenum modeRGB, GLenum modeA )
 {
    r128ContextPtr rmesa = R128_CONTEXT(ctx);
 
+   assert( modeRGB == modeA );
    FLUSH_BATCH( rmesa );
 
    /* BlendEquation sets ColorLogicOpEnabled in an unexpected
@@ -206,7 +208,7 @@
 
    /* Can only do blend addition, not min, max, subtract, etc. */
    FALLBACK( R128_CONTEXT(ctx), R128_FALLBACK_BLEND_EQ,
-	     mode != GL_FUNC_ADD_EXT);
+	     modeRGB != GL_FUNC_ADD);
 
    rmesa->new_state |= R128_NEW_ALPHA;
 }
@@ -1187,7 +1189,7 @@
    ctx->Driver.IndexMask		= NULL;
    ctx->Driver.ColorMask		= r128DDColorMask;
    ctx->Driver.AlphaFunc		= r128DDAlphaFunc;
-   ctx->Driver.BlendEquation		= r128DDBlendEquation;
+   ctx->Driver.BlendEquationSeparate	= r128DDBlendEquationSeparate;
    ctx->Driver.BlendFuncSeparate	= r128DDBlendFuncSeparate;
    ctx->Driver.ClearDepth		= r128DDClearDepth;
    ctx->Driver.CullFace			= r128DDCullFace;
diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c
index 2326c75..2b61098 100644
--- a/src/mesa/drivers/dri/r200/r200_state.c
+++ b/src/mesa/drivers/dri/r200/r200_state.c
@@ -104,12 +104,15 @@
    rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
 }
 
-static void r200BlendEquation( GLcontext *ctx, GLenum mode )
+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;
 
-   switch ( mode ) {
+   assert( modeRGB == modeA );
+
+   switch ( modeRGB ) {
    case GL_FUNC_ADD:
    case GL_LOGIC_OP:
       b |= R200_COMB_FCN_ADD_CLAMP;
@@ -2186,7 +2189,7 @@
    functions->ReadBuffer		= r200ReadBuffer;
 
    functions->AlphaFunc			= r200AlphaFunc;
-   functions->BlendEquation		= r200BlendEquation;
+   functions->BlendEquationSeparate	= r200BlendEquationSeparate;
    functions->BlendFuncSeparate		= r200BlendFuncSeparate;
    functions->ClearColor		= r200ClearColor;
    functions->ClearDepth		= NULL;
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c
index 74e918f..25aa3fa 100644
--- a/src/mesa/drivers/dri/radeon/radeon_state.c
+++ b/src/mesa/drivers/dri/radeon/radeon_state.c
@@ -102,13 +102,16 @@
    rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
 }
 
-static void radeonBlendEquation( GLcontext *ctx, GLenum mode )
+static void radeonBlendEquationSeparate( GLcontext *ctx,
+					 GLenum modeRGB, GLenum modeA )
 {
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK;
    GLboolean fallback = GL_FALSE;
 
-   switch ( mode ) {
+   assert( modeRGB == modeA );
+
+   switch ( modeRGB ) {
    case GL_FUNC_ADD:
    case GL_LOGIC_OP:
       b |= RADEON_COMB_FCN_ADD_CLAMP;
@@ -1693,7 +1696,9 @@
       /* Catch a possible fallback:
        */
       if (state) {
-	 ctx->Driver.BlendEquation( ctx, ctx->Color.BlendEquation );
+	 ctx->Driver.BlendEquationSeparate( ctx,
+					    ctx->Color.BlendEquationRGB,
+					    ctx->Color.BlendEquationA );
 	 ctx->Driver.BlendFuncSeparate( ctx, ctx->Color.BlendSrcRGB,
 					ctx->Color.BlendDstRGB,
 					ctx->Color.BlendSrcRGB,
@@ -2186,7 +2191,7 @@
    ctx->Driver.ReadBuffer		= radeonReadBuffer;
 
    ctx->Driver.AlphaFunc		= radeonAlphaFunc;
-   ctx->Driver.BlendEquation		= radeonBlendEquation;
+   ctx->Driver.BlendEquationSeparate	= radeonBlendEquationSeparate;
    ctx->Driver.BlendFuncSeparate	= radeonBlendFuncSeparate;
    ctx->Driver.ClearColor		= radeonClearColor;
    ctx->Driver.ClearDepth		= radeonClearDepth;
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_state.c b/src/mesa/drivers/dri/tdfx/tdfx_state.c
index 6130698..7ef088c 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_state.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_state.c
@@ -267,10 +267,12 @@
    fxMesa->new_state |= TDFX_NEW_ALPHA;
 }
 
-static void tdfxDDBlendEquation( GLcontext *ctx, GLenum mode )
+static void tdfxDDBlendEquationSeparate( GLcontext *ctx, 
+					 GLenum modeRGB, GLenum modeA )
 {
    tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
 
+   assert( modeRGB == modeA );
    FLUSH_BATCH( fxMesa );
    fxMesa->new_state |= TDFX_NEW_ALPHA;
 }
@@ -1387,7 +1389,7 @@
    ctx->Driver.ColorMask		= tdfxDDColorMask;
 
    ctx->Driver.AlphaFunc		= tdfxDDAlphaFunc;
-   ctx->Driver.BlendEquation		= tdfxDDBlendEquation;
+   ctx->Driver.BlendEquationSeparate	= tdfxDDBlendEquationSeparate;
    ctx->Driver.BlendFuncSeparate	= tdfxDDBlendFuncSeparate;
    ctx->Driver.ClearDepth		= tdfxDDClearDepth;
    ctx->Driver.CullFace			= tdfxDDCullFace;
diff --git a/src/mesa/drivers/glide/fxdd.c b/src/mesa/drivers/glide/fxdd.c
index bda11f9..ef73f79 100644
--- a/src/mesa/drivers/glide/fxdd.c
+++ b/src/mesa/drivers/glide/fxdd.c
@@ -1531,10 +1531,10 @@
    }
 
    if (ctx->Color.BlendEnabled) {
-      if (ctx->Color.BlendEquation != GL_FUNC_ADD_EXT) {
+      if (ctx->Color.BlendEquationRGB != GL_FUNC_ADD) {
          if (!fxMesa->HavePixExt ||
-             ((ctx->Color.BlendEquation != GL_FUNC_SUBTRACT_EXT) &&
-              (ctx->Color.BlendEquation != GL_FUNC_REVERSE_SUBTRACT_EXT))) {
+             ((ctx->Color.BlendEquationRGB != GL_FUNC_SUBTRACT) &&
+              (ctx->Color.BlendEquationRGB != GL_FUNC_REVERSE_SUBTRACT))) {
             return FX_FALLBACK_BLEND;
          }
       }
@@ -1702,7 +1702,7 @@
    ctx->Driver.UpdateTexturePalette = fxDDTexPalette;
    ctx->Driver.AlphaFunc = fxDDAlphaFunc;
    ctx->Driver.BlendFuncSeparate = fxDDBlendFuncSeparate;
-   ctx->Driver.BlendEquation = fxDDBlendEquation;
+   ctx->Driver.BlendEquationSeparate = fxDDBlendEquationSeparate;
    ctx->Driver.DepthFunc = fxDDDepthFunc;
    ctx->Driver.DepthMask = fxDDDepthMask;
    ctx->Driver.ColorMask = fxDDColorMask;
diff --git a/src/mesa/drivers/glide/fxdrv.h b/src/mesa/drivers/glide/fxdrv.h
index 1b42be8..d48e3dd 100644
--- a/src/mesa/drivers/glide/fxdrv.h
+++ b/src/mesa/drivers/glide/fxdrv.h
@@ -620,7 +620,7 @@
 extern void fxDDEnable(GLcontext *, GLenum, GLboolean);
 extern void fxDDAlphaFunc(GLcontext *, GLenum, GLfloat);
 extern void fxDDBlendFuncSeparate(GLcontext *, GLenum, GLenum, GLenum, GLenum);
-extern void fxDDBlendEquation(GLcontext *, GLenum);
+extern void fxDDBlendEquationSeparate(GLcontext *, GLenum, GLenum);
 extern void fxDDDepthMask(GLcontext *, GLboolean);
 extern void fxDDDepthFunc(GLcontext *, GLenum);
 extern void fxDDStencilFunc (GLcontext *ctx, GLenum func, GLint ref, GLuint mask);
diff --git a/src/mesa/drivers/glide/fxsetup.c b/src/mesa/drivers/glide/fxsetup.c
index 4c08630..cb7c4e2 100644
--- a/src/mesa/drivers/glide/fxsetup.c
+++ b/src/mesa/drivers/glide/fxsetup.c
@@ -1527,20 +1527,21 @@
 }
 
 void
-fxDDBlendEquation(GLcontext * ctx, GLenum mode)
+fxDDBlendEquationSeparate(GLcontext * ctx, GLenum modeRGB, GLenum modeA)
 {
  fxMesaContext fxMesa = FX_CONTEXT(ctx);
  tfxUnitsState *us = &fxMesa->unitsState;
  GrAlphaBlendOp_t q;
 
- switch (mode) {
-        case GL_FUNC_ADD_EXT:
+ assert( modeRGB == modeA );
+ switch (modeRGB) {
+        case GL_FUNC_ADD:
              q = GR_BLEND_OP_ADD;
              break;
-        case GL_FUNC_SUBTRACT_EXT:
+        case GL_FUNC_SUBTRACT:
              q = GR_BLEND_OP_SUB;
              break;
-        case GL_FUNC_REVERSE_SUBTRACT_EXT:
+        case GL_FUNC_REVERSE_SUBTRACT:
              q = GR_BLEND_OP_REVSUB;
              break;
         default:
diff --git a/src/mesa/drivers/glide/fxtris.c b/src/mesa/drivers/glide/fxtris.c
index 3b82b57..846fd95 100644
--- a/src/mesa/drivers/glide/fxtris.c
+++ b/src/mesa/drivers/glide/fxtris.c
@@ -1407,7 +1407,7 @@
              ctx->Texture.Unit[0]._ReallyEnabled = 0;
              ctx->Texture.Unit[1]._ReallyEnabled = 0;
              /* SUM the colors */
-             fxDDBlendEquation(ctx, GL_FUNC_ADD_EXT);
+             fxDDBlendEquationSeparate(ctx, GL_FUNC_ADD, GL_FUNC_ADD);
              fxDDBlendFuncSeparate(ctx, GL_ONE, GL_ONE, GL_ZERO, GL_ONE);
              fxDDEnable(ctx, GL_BLEND, GL_TRUE);
              /* make sure we draw only where we want to */
diff --git a/src/mesa/glapi/APIspec b/src/mesa/glapi/APIspec
index 4c180fd..8a1e7f5 100644
--- a/src/mesa/glapi/APIspec
+++ b/src/mesa/glapi/APIspec
@@ -1,4 +1,4 @@
-# $Id: APIspec,v 1.22 2003/11/24 23:03:29 brianp Exp $
+# $Id: APIspec,v 1.23 2004/01/27 18:52:40 idr Exp $
 
 # This file describes all the OpenGL functions.
 # We use a number of Python scripts to parse this file and
@@ -8567,7 +8567,25 @@
 param		params		GLuint *
 category	1.5
 
+# EXT_blend_equation_separate
 
+name		BlendEquationSeparateEXT
+return		void
+param		modeRGB		GLenum
+param		modeA		GLenum
+offset		710
+category	GL_EXT_blend_equation_separate
+
+# ATI_blend_equation_separate
+
+# This is a guess at the name for this function since there is no formal
+# extension spec.
+name		BlendEquationSeparateATI
+alias		BlendEquationSeparateEXT
+return		void
+param		modeRGB		GLenum
+param		modeA		GLenum
+category	GL_ATI_blend_equation_separate
 
 # end of file sentinal
 
diff --git a/src/mesa/glapi/glapioffsets.h b/src/mesa/glapi/glapioffsets.h
index 995e124..d8f595d 100644
--- a/src/mesa/glapi/glapioffsets.h
+++ b/src/mesa/glapi/glapioffsets.h
@@ -712,5 +712,6 @@
 #define _gloffset_GetQueryObjectuivARB 707
 #define _gloffset_MultiModeDrawArraysIBM 708
 #define _gloffset_MultiModeDrawElementsIBM 709
+#define _gloffset_BlendEquationSeparateEXT 710
 
 #endif
diff --git a/src/mesa/glapi/glapitable.h b/src/mesa/glapi/glapitable.h
index 044c62c..f0630e1 100644
--- a/src/mesa/glapi/glapitable.h
+++ b/src/mesa/glapi/glapitable.h
@@ -718,6 +718,7 @@
    void (GLAPIENTRYP GetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint * params); /* 707 */
    void (GLAPIENTRYP MultiModeDrawArraysIBM)(const GLenum * mode, const GLint * first, const GLsizei * count, GLsizei primcount, GLint modestride); /* 708 */
    void (GLAPIENTRYP MultiModeDrawElementsIBM)(const GLenum * mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei primcount, GLint modestride); /* 709 */
+   void (GLAPIENTRYP BlendEquationSeparateEXT)(GLenum modeRGB, GLenum modeA); /* 710 */
 };
 
 #endif
diff --git a/src/mesa/glapi/glapitemp.h b/src/mesa/glapi/glapitemp.h
index a0f2e8d..21523f2 100644
--- a/src/mesa/glapi/glapitemp.h
+++ b/src/mesa/glapi/glapitemp.h
@@ -4767,6 +4767,16 @@
    DISPATCH(GetQueryObjectuivARB, (id, pname, params), (F, "glGetQueryObjectuiv(%d, 0x%x, %p);\n", id, pname, (const void *) params));
 }
 
+KEYWORD1 void KEYWORD2 NAME(BlendEquationSeparateEXT)(GLenum modeRGB, GLenum modeA)
+{
+   DISPATCH(BlendEquationSeparateEXT, (modeRGB, modeA), (F, "glBlendEquationSeparateEXT(0x%x, 0x%x);\n", modeRGB, modeA));
+}
+
+KEYWORD1 void KEYWORD2 NAME(BlendEquationSeparateATI)(GLenum modeRGB, GLenum modeA)
+{
+   DISPATCH(BlendEquationSeparateEXT, (modeRGB, modeA), (F, "glBlendEquationSeparateATI(0x%x, 0x%x);\n", modeRGB, modeA));
+}
+
 
 
 /*
@@ -5490,6 +5500,7 @@
    TABLE_ENTRY(GetQueryObjectuivARB),
    TABLE_ENTRY(MultiModeDrawArraysIBM),
    TABLE_ENTRY(MultiModeDrawElementsIBM),
+   TABLE_ENTRY(BlendEquationSeparateEXT),
    /* A whole bunch of no-op functions.  These might be called
     * when someone tries to call a dynamically-registered
     * extension function without a current rendering context.
@@ -5808,6 +5819,7 @@
    TABLE_ENTRY(GetQueryiv),
    TABLE_ENTRY(GetQueryObjectiv),
    TABLE_ENTRY(GetQueryObjectuiv),
+   TABLE_ENTRY(BlendEquationSeparateATI),
 };
 #endif /*UNUSED_TABLE_NAME*/
 
diff --git a/src/mesa/glapi/glprocs.h b/src/mesa/glapi/glprocs.h
index 1a48b4f..5441093 100644
--- a/src/mesa/glapi/glprocs.h
+++ b/src/mesa/glapi/glprocs.h
@@ -919,5 +919,7 @@
    { "glGetQueryiv", (GLvoid *) glGetQueryiv, _gloffset_GetQueryivARB },
    { "glGetQueryObjectiv", (GLvoid *) glGetQueryObjectiv, _gloffset_GetQueryObjectivARB },
    { "glGetQueryObjectuiv", (GLvoid *) glGetQueryObjectuiv, _gloffset_GetQueryObjectuivARB },
+   { "glBlendEquationSeparateEXT", (GLvoid *) glBlendEquationSeparateEXT, _gloffset_BlendEquationSeparateEXT },
+   { "glBlendEquationSeparateATI", (GLvoid *) glBlendEquationSeparateATI, _gloffset_BlendEquationSeparateEXT },
    { NULL, NULL }  /* end of list marker */
 };
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index 62d968a..8beb0a5 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -838,7 +838,16 @@
                                           color->BlendDstRGB,
                                           color->BlendSrcA,
                                           color->BlendDstA);
-               _mesa_BlendEquation(color->BlendEquation);
+	       /* This special case is because glBlendEquationSeparateEXT
+		* cannot take GL_LOGIC_OP as a parameter.
+		*/
+	       if ( color->BlendEquationRGB == color->BlendEquationA ) {
+		  _mesa_BlendEquation(color->BlendEquationRGB);
+	       }
+	       else {
+		  _mesa_BlendEquationSeparateEXT(color->BlendEquationRGB,
+						 color->BlendEquationA);
+	       }
                _mesa_BlendColor(color->BlendColor[0],
                                 color->BlendColor[1],
                                 color->BlendColor[2],
diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c
index 26d87d1..6741238 100644
--- a/src/mesa/main/blend.c
+++ b/src/mesa/main/blend.c
@@ -215,6 +215,42 @@
 
 #if _HAVE_FULL_GL
 
+static GLboolean
+_mesa_validate_blend_equation( GLcontext *ctx,
+			       GLenum mode, GLboolean is_separate )
+{
+       switch (mode) {
+      case GL_FUNC_ADD:
+         break;
+      case GL_MIN:
+      case GL_MAX:
+         if (!ctx->Extensions.EXT_blend_minmax &&
+             !ctx->Extensions.ARB_imaging) {
+            return GL_FALSE;
+         }
+         break;
+      /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
+       */
+      case GL_LOGIC_OP:
+         if (!ctx->Extensions.EXT_blend_logic_op || is_separate) {
+            return GL_FALSE;
+         }
+         break;
+      case GL_FUNC_SUBTRACT:
+      case GL_FUNC_REVERSE_SUBTRACT:
+         if (!ctx->Extensions.EXT_blend_subtract &&
+             !ctx->Extensions.ARB_imaging) {
+            return GL_FALSE;
+         }
+         break;
+      default:
+         return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+
 /* This is really an extension function! */
 void GLAPIENTRY
 _mesa_BlendEquation( GLenum mode )
@@ -226,41 +262,18 @@
       _mesa_debug(ctx, "glBlendEquation %s\n",
                   _mesa_lookup_enum_by_nr(mode));
 
-   switch (mode) {
-      case GL_FUNC_ADD_EXT:
-         break;
-      case GL_MIN_EXT:
-      case GL_MAX_EXT:
-         if (!ctx->Extensions.EXT_blend_minmax &&
-             !ctx->Extensions.ARB_imaging) {
-            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
-            return;
-         }
-         break;
-      case GL_LOGIC_OP:
-         if (!ctx->Extensions.EXT_blend_logic_op) {
-            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
-            return;
-         }
-         break;
-      case GL_FUNC_SUBTRACT_EXT:
-      case GL_FUNC_REVERSE_SUBTRACT_EXT:
-         if (!ctx->Extensions.EXT_blend_subtract &&
-             !ctx->Extensions.ARB_imaging) {
-            _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
-            return;
-         }
-         break;
-      default:
-         _mesa_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
-         return;
+   if ( ! _mesa_validate_blend_equation( ctx, mode, GL_FALSE ) ) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
+      return;
    }
 
-   if (ctx->Color.BlendEquation == mode)
+   if ( (ctx->Color.BlendEquationRGB == mode) &&
+	(ctx->Color.BlendEquationA == mode) )
       return;
 
    FLUSH_VERTICES(ctx, _NEW_COLOR);
-   ctx->Color.BlendEquation = mode;
+   ctx->Color.BlendEquationRGB = mode;
+   ctx->Color.BlendEquationA = mode;
 
    /* This is needed to support 1.1's RGB logic ops AND
     * 1.0's blending logicops.
@@ -269,10 +282,55 @@
                                  (ctx->Color.BlendEnabled &&
                                   mode == GL_LOGIC_OP));
 
-   if (ctx->Driver.BlendEquation)
-      (*ctx->Driver.BlendEquation)( ctx, mode );
+   if (ctx->Driver.BlendEquationSeparate)
+      (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
 }
 
+void GLAPIENTRY
+_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+      _mesa_debug(ctx, "glBlendEquationSeparateEXT %s %s\n",
+                  _mesa_lookup_enum_by_nr(modeRGB),
+                  _mesa_lookup_enum_by_nr(modeA));
+
+   if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+		  "glBlendEquationSeparateEXT not supported by driver");
+      return;
+   }
+
+   if ( ! _mesa_validate_blend_equation( ctx, modeRGB, GL_TRUE ) ) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
+      return;
+   }
+
+   if ( ! _mesa_validate_blend_equation( ctx, modeA, GL_TRUE ) ) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
+      return;
+   }
+
+
+   if ( (ctx->Color.BlendEquationRGB == modeRGB) &&
+	(ctx->Color.BlendEquationA == modeA) )
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_COLOR);
+   ctx->Color.BlendEquationRGB = modeRGB;
+   ctx->Color.BlendEquationA = modeA;
+
+   /* This is needed to support 1.1's RGB logic ops AND
+    * 1.0's blending logicops.  This test is simplified over glBlendEquation
+    * because modeRGB cannot be GL_LOGIC_OP.
+    */
+   ctx->Color._LogicOpEnabled = (ctx->Color.ColorLogicOpEnabled);
+
+   if (ctx->Driver.BlendEquationSeparate)
+      (*ctx->Driver.BlendEquationSeparate)( ctx, modeRGB, modeA );
+}
 #endif
 
 
@@ -500,7 +558,8 @@
    ctx->Color.BlendDstRGB = GL_ZERO;
    ctx->Color.BlendSrcA = GL_ONE;
    ctx->Color.BlendDstA = GL_ZERO;
-   ctx->Color.BlendEquation = GL_FUNC_ADD_EXT;
+   ctx->Color.BlendEquationRGB = GL_FUNC_ADD;
+   ctx->Color.BlendEquationA = GL_FUNC_ADD;
    ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
    ctx->Color.IndexLogicOpEnabled = GL_FALSE;
    ctx->Color.ColorLogicOpEnabled = GL_FALSE;
diff --git a/src/mesa/main/blend.h b/src/mesa/main/blend.h
index ae96bd4..d6c03d9 100644
--- a/src/mesa/main/blend.h
+++ b/src/mesa/main/blend.h
@@ -50,6 +50,10 @@
 
 
 extern void GLAPIENTRY
+_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA );
+
+
+extern void GLAPIENTRY
 _mesa_BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
 
 
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index cb23e0b..f9fdd3b 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -591,7 +591,7 @@
    /** Set the blend color */
    void (*BlendColor)(GLcontext *ctx, const GLfloat color[4]);
    /** Set the blend equation */
-   void (*BlendEquation)(GLcontext *ctx, GLenum mode);
+   void (*BlendEquationSeparate)(GLcontext *ctx, GLenum modeRGB, GLenum modeA);
    /** Specify pixel arithmetic */
    void (*BlendFuncSeparate)(GLcontext *ctx,
                              GLenum sfactorRGB, GLenum dfactorRGB,
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index 386744f..539e654 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -170,6 +170,7 @@
 	OPCODE_BITMAP,
 	OPCODE_BLEND_COLOR,
 	OPCODE_BLEND_EQUATION,
+	OPCODE_BLEND_EQUATION_SEPARATE,
 	OPCODE_BLEND_FUNC_SEPARATE,
         OPCODE_CALL_LIST,
         OPCODE_CALL_LIST_OFFSET,
@@ -628,6 +629,7 @@
       InstSize[OPCODE_BITMAP] = 8;
       InstSize[OPCODE_BLEND_COLOR] = 5;
       InstSize[OPCODE_BLEND_EQUATION] = 2;
+      InstSize[OPCODE_BLEND_EQUATION_SEPARATE] = 3;
       InstSize[OPCODE_BLEND_FUNC_SEPARATE] = 5;
       InstSize[OPCODE_CALL_LIST] = 2;
       InstSize[OPCODE_CALL_LIST_OFFSET] = 3;
@@ -956,6 +958,23 @@
 }
 
 
+static void GLAPIENTRY save_BlendEquationSeparateEXT( GLenum modeRGB,
+						      GLenum modeA )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_BLEND_EQUATION_SEPARATE, 2 );
+   if (n) {
+      n[1].e = modeRGB;
+      n[2].e = modeA;
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->BlendEquationSeparateEXT)( modeRGB, modeA );
+   }
+}
+
+
 static void GLAPIENTRY save_BlendFuncSeparateEXT(GLenum sfactorRGB, GLenum dfactorRGB,
                                       GLenum sfactorA, GLenum dfactorA)
 {
@@ -5266,6 +5285,9 @@
 	 case OPCODE_BLEND_EQUATION:
 	    (*ctx->Exec->BlendEquation)( n[1].e );
 	    break;
+	 case OPCODE_BLEND_EQUATION_SEPARATE:
+	    (*ctx->Exec->BlendEquationSeparateEXT)( n[1].e, n[2].e );
+	    break;
 	 case OPCODE_BLEND_FUNC_SEPARATE:
 	    (*ctx->Exec->BlendFuncSeparateEXT)(n[1].e, n[2].e, n[3].e, n[4].e);
 	    break;
@@ -7465,6 +7487,9 @@
    table->MapBufferARB = _mesa_MapBufferARB;
    table->UnmapBufferARB = _mesa_UnmapBufferARB;
 #endif
+
+   /* 299. GL_EXT_blend_equation_separate */
+   table->BlendEquationSeparateEXT = save_BlendEquationSeparateEXT;
 }
 
 
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index 7f07686..64cc4d1 100644
--- a/src/mesa/main/enable.c
+++ b/src/mesa/main/enable.c
@@ -236,7 +236,7 @@
           */
          ctx->Color._LogicOpEnabled =
             (ctx->Color.ColorLogicOpEnabled ||
-             (state && ctx->Color.BlendEquation == GL_LOGIC_OP));
+             (state && ctx->Color.BlendEquationRGB == GL_LOGIC_OP));
          break;
 #if FEATURE_userclip
       case GL_CLIP_PLANE0:
@@ -384,7 +384,7 @@
           */
          ctx->Color._LogicOpEnabled =
             (state || (ctx->Color.BlendEnabled &&
-                       ctx->Color.BlendEquation == GL_LOGIC_OP));
+                       ctx->Color.BlendEquationRGB == GL_LOGIC_OP));
          break;
       case GL_MAP1_COLOR_4:
          if (ctx->Eval.Map1Color4 == state)
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index 0b512c5..ac3f633 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -67,6 +67,7 @@
    { ON,  "GL_EXT_abgr",                       0 },
    { ON,  "GL_EXT_bgra",                       0 },
    { OFF, "GL_EXT_blend_color",                F(EXT_blend_color) },
+   { OFF, "GL_EXT_blend_equation_separate",    F(EXT_blend_equation_separate) },
    { OFF, "GL_EXT_blend_func_separate",        F(EXT_blend_func_separate) },
    { OFF, "GL_EXT_blend_logic_op",             F(EXT_blend_logic_op) },
    { OFF, "GL_EXT_blend_minmax",               F(EXT_blend_minmax) },
@@ -109,6 +110,7 @@
    { OFF, "GL_3DFX_texture_compression_FXT1",  F(TDFX_texture_compression_FXT1) },
    { OFF, "GL_APPLE_client_storage",           F(APPLE_client_storage) },
    { ON,  "GL_APPLE_packed_pixels",            0 },
+   { OFF, "GL_ATI_blend_equation_separate",    F(EXT_blend_equation_separate) },
    { OFF, "GL_ATI_texture_env_combine3",       F(ATI_texture_env_combine3)},
    { OFF, "GL_ATI_texture_mirror_once",        F(ATI_texture_mirror_once)},
    { OFF, "GL_HP_occlusion_test",              F(HP_occlusion_test) },
@@ -182,6 +184,7 @@
    ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE;
    ctx->Extensions.ATI_texture_mirror_once = GL_TRUE;
    ctx->Extensions.EXT_blend_color = GL_TRUE;
+   ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
    ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
    ctx->Extensions.EXT_blend_logic_op = GL_TRUE;
    ctx->Extensions.EXT_blend_minmax = GL_TRUE;
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 287eae7..723c48c 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -235,8 +235,11 @@
       case GL_BLEND_DST_ALPHA_EXT:
          *params = ENUM_TO_BOOL(ctx->Color.BlendDstA);
          break;
-      case GL_BLEND_EQUATION_EXT:
-	 *params = ENUM_TO_BOOL( ctx->Color.BlendEquation );
+      case GL_BLEND_EQUATION:
+	 *params = ENUM_TO_BOOL( ctx->Color.BlendEquationRGB );
+	 break;
+      case GL_BLEND_EQUATION_ALPHA_EXT:
+	 *params = ENUM_TO_BOOL( ctx->Color.BlendEquationA );
 	 break;
       case GL_BLEND_COLOR_EXT:
 	 params[0] = FLOAT_TO_BOOL( ctx->Color.BlendColor[0] );
@@ -1777,8 +1780,11 @@
       case GL_BLEND_DST_ALPHA_EXT:
          *params = ENUM_TO_DOUBLE(ctx->Color.BlendDstA);
          break;
-      case GL_BLEND_EQUATION_EXT:
-	 *params = ENUM_TO_DOUBLE(ctx->Color.BlendEquation);
+      case GL_BLEND_EQUATION:
+	 *params = ENUM_TO_DOUBLE(ctx->Color.BlendEquationRGB);
+	 break;
+      case GL_BLEND_EQUATION_ALPHA_EXT:
+	 *params = ENUM_TO_DOUBLE(ctx->Color.BlendEquationA);
 	 break;
       case GL_BLEND_COLOR_EXT:
 	 params[0] = (GLdouble) ctx->Color.BlendColor[0];
@@ -3314,8 +3320,11 @@
       case GL_BLEND_DST_ALPHA_EXT:
          *params = ENUM_TO_FLOAT(ctx->Color.BlendDstA);
          break;
-      case GL_BLEND_EQUATION_EXT:
-	 *params = ENUM_TO_FLOAT(ctx->Color.BlendEquation);
+      case GL_BLEND_EQUATION:
+	 *params = ENUM_TO_FLOAT(ctx->Color.BlendEquationRGB);
+	 break;
+      case GL_BLEND_EQUATION_ALPHA_EXT:
+	 *params = ENUM_TO_FLOAT(ctx->Color.BlendEquationA);
 	 break;
       case GL_BLEND_COLOR_EXT:
 	 params[0] = ctx->Color.BlendColor[0];
@@ -4828,8 +4837,11 @@
       case GL_BLEND_DST_ALPHA_EXT:
          *params = (GLint) ctx->Color.BlendDstA;
          break;
-      case GL_BLEND_EQUATION_EXT:
-	 *params = (GLint) ctx->Color.BlendEquation;
+      case GL_BLEND_EQUATION:
+	 *params = (GLint) ctx->Color.BlendEquationRGB;
+	 break;
+      case GL_BLEND_EQUATION_ALPHA_EXT:
+	 *params = (GLint) ctx->Color.BlendEquationA;
 	 break;
       case GL_BLEND_COLOR_EXT:
 	 params[0] = FLOAT_TO_INT( ctx->Color.BlendColor[0] );
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 5e6777e..5fb9b25 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -419,7 +419,8 @@
    GLenum BlendDstRGB;			/**< Blending destination operator */
    GLenum BlendSrcA;			/**< GL_INGR_blend_func_separate */
    GLenum BlendDstA;			/**< GL_INGR_blend_func_separate */
-   GLenum BlendEquation;		/**< Blending equation */
+   GLenum BlendEquationRGB;		/**< Blending equation */
+   GLenum BlendEquationA;		/**< GL_EXT_blend_equation_separate */
    GLfloat BlendColor[4];		/**< Blending color */
    /*@}*/
 
@@ -1771,6 +1772,7 @@
    GLboolean ATI_texture_mirror_once;
    GLboolean ATI_texture_env_combine3;
    GLboolean EXT_blend_color;
+   GLboolean EXT_blend_equation_separate;
    GLboolean EXT_blend_func_separate;
    GLboolean EXT_blend_logic_op;
    GLboolean EXT_blend_minmax;
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index 3e7554f..b8a67d0 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -368,6 +368,7 @@
 #if _HAVE_FULL_GL
    exec->BlendColor = _mesa_BlendColor;
    exec->BlendEquation = _mesa_BlendEquation;
+   exec->BlendEquationSeparateEXT = _mesa_BlendEquationSeparateEXT;
    exec->ColorSubTable = _mesa_ColorSubTable;
    exec->ColorTable = _mesa_ColorTable;
    exec->ColorTableParameterfv = _mesa_ColorTableParameterfv;
diff --git a/src/mesa/sparc/glapi_sparc.S b/src/mesa/sparc/glapi_sparc.S
index f3a2c69..7556744 100644
--- a/src/mesa/sparc/glapi_sparc.S
+++ b/src/mesa/sparc/glapi_sparc.S
@@ -19235,6 +19235,48 @@
 #endif
 	jmpl	%g3, %g0
 	nop
+
+.globl glBlendEquationSeparateEXT
+.type glBlendEquationSeparateEXT,#function
+glBlendEquationSeparateEXT:
+#if defined(__sparc_v9__) && !defined(__linux__)
+	sethi	%hi(0x00000000), %g2
+	sethi	%hi(0x00000000), %g1
+	or	%g2, %lo(0x00000000), %g2
+	or	%g1, %lo(0x00000000), %g1
+	sllx	%g2, 32, %g2
+	ldx	[%g1 + %g2], %g1
+	sethi	%hi(8 * _gloffset_BlendEquationSeparateEXT), %g2
+	or	%g2, %lo(8 * _gloffset_BlendEquationSeparateEXT), %g2
+	ldx	[%g1 + %g2], %g3
+#else
+	sethi	%hi(0x00000000), %g1
+	ld	[%g1 + %lo(0x00000000)], %g1
+	ld	[%g1 + (4 * _gloffset_BlendEquationSeparateEXT)], %g3
+#endif
+	jmpl	%g3, %g0
+	nop
+
+.globl glBlendEquationSeparateATI
+.type glBlendEquationSeparateATI,#function
+glBlendEquationSeparateATI:
+#if defined(__sparc_v9__) && !defined(__linux__)
+	sethi	%hi(0x00000000), %g2
+	sethi	%hi(0x00000000), %g1
+	or	%g2, %lo(0x00000000), %g2
+	or	%g1, %lo(0x00000000), %g1
+	sllx	%g2, 32, %g2
+	ldx	[%g1 + %g2], %g1
+	sethi	%hi(8 * _gloffset_BlendEquationSeparateEXT), %g2
+	or	%g2, %lo(8 * _gloffset_BlendEquationSeparateEXT), %g2
+	ldx	[%g1 + %g2], %g3
+#else
+	sethi	%hi(0x00000000), %g1
+	ld	[%g1 + %lo(0x00000000)], %g1
+	ld	[%g1 + (4 * _gloffset_BlendEquationSeparateEXT)], %g3
+#endif
+	jmpl	%g3, %g0
+	nop
 	 nop
 
 .globl _mesa_sparc_glapi_end
diff --git a/src/mesa/swrast/s_blend.c b/src/mesa/swrast/s_blend.c
index 9f55022..3500dfb 100644
--- a/src/mesa/swrast/s_blend.c
+++ b/src/mesa/swrast/s_blend.c
@@ -60,7 +60,8 @@
             GLchan rgba[][4], CONST GLchan dest[][4] )
 {
    GLuint i;
-   ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
+   ASSERT(ctx->Color.BlendEquationRGB==GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
    ASSERT(ctx->Color.BlendSrcRGB==GL_ZERO);
    ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
    (void) ctx;
@@ -80,7 +81,8 @@
 blend_replace( GLcontext *ctx, GLuint n, const GLubyte mask[],
                GLchan rgba[][4], CONST GLchan dest[][4] )
 {
-   ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
+   ASSERT(ctx->Color.BlendEquatioRGB==GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
    ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
    ASSERT(ctx->Color.BlendDstRGB==GL_ZERO);
    (void) ctx;
@@ -99,7 +101,8 @@
                     GLchan rgba[][4], CONST GLchan dest[][4] )
 {
    GLuint i;
-   ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
+   ASSERT(ctx->Color.BlendEquatioRGB==GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
    ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA);
    ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA);
    (void) ctx;
@@ -186,7 +189,8 @@
            GLchan rgba[][4], CONST GLchan dest[][4] )
 {
    GLuint i;
-   ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
+   ASSERT(ctx->Color.BlendEquatioRGB==GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
    ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
    ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
    (void) ctx;
@@ -224,7 +228,8 @@
            GLchan rgba[][4], CONST GLchan dest[][4] )
 {
    GLuint i;
-   ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
+   ASSERT(ctx->Color.BlendEquatioRGB==GL_MIN);
+   ASSERT(ctx->Color.BlendEquationA==GL_MIN);
    (void) ctx;
 
    for (i=0;i<n;i++) {
@@ -252,7 +257,8 @@
            GLchan rgba[][4], CONST GLchan dest[][4] )
 {
    GLuint i;
-   ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
+   ASSERT(ctx->Color.BlendEquatioRGB==GL_MAX);
+   ASSERT(ctx->Color.BlendEquationA==GL_MAX);
    (void) ctx;
 
    for (i=0;i<n;i++) {
@@ -628,27 +634,58 @@
 
          /* compute blended color */
 #if CHAN_TYPE == GL_FLOAT
-         if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
+         if (ctx->Color.BlendEquationRGB==GL_FUNC_ADD) {
             r = Rs * sR + Rd * dR;
             g = Gs * sG + Gd * dG;
             b = Bs * sB + Bd * dB;
             a = As * sA + Ad * dA;
          }
-         else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
+         else if (ctx->Color.BlendEquationRGB==GL_FUNC_SUBTRACT) {
             r = Rs * sR - Rd * dR;
             g = Gs * sG - Gd * dG;
             b = Bs * sB - Bd * dB;
             a = As * sA - Ad * dA;
          }
-         else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
+         else if (ctx->Color.BlendEquationRGB==GL_FUNC_REVERSE_SUBTRACT) {
             r = Rd * dR - Rs * sR;
             g = Gd * dG - Gs * sG;
             b = Bd * dB - Bs * sB;
             a = Ad * dA - As * sA;
          }
+         else if (ctx->Color.BlendEquationRGB==GL_MIN) {
+	    r = MIN2( Rd, Rs );
+	    g = MIN2( Gd, Gs );
+	    b = MIN2( Bd, Bs );
+	 }
+         else if (ctx->Color.BlendEquationRGB==GL_MAX) {
+	    r = MAX2( Rd, Rs );
+	    g = MAX2( Gd, Gs );
+	    b = MAX2( Bd, Bs );
+	 }
          else {
             /* should never get here */
-            r = g = b = a = 0.0F;  /* silence uninitialized var warning */
+            r = g = b = 0.0F;  /* silence uninitialized var warning */
+            _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+         }
+
+         if (ctx->Color.BlendEquationA==GL_FUNC_ADD) {
+            a = As * sA + Ad * dA;
+         }
+         else if (ctx->Color.BlendEquationA==GL_FUNC_SUBTRACT) {
+            a = As * sA - Ad * dA;
+         }
+         else if (ctx->Color.BlendEquationA==GL_FUNC_REVERSE_SUBTRACT) {
+            a = Ad * dA - As * sA;
+         }
+         else if (ctx->Color.BlendEquationA==GL_MIN) {
+	    a = MIN2( Ad, As );
+	 }
+         else if (ctx->Color.BlendEquationA==GL_MAX) {
+	    a = MAX2( Ad, As );
+	 }
+         else {
+            /* should never get here */
+            a = 0.0F;  /* silence uninitialized var warning */
             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
          }
 
@@ -658,27 +695,55 @@
          rgba[i][BCOMP] = MAX2( b, 0.0F );
          rgba[i][ACOMP] = CLAMP( a, 0.0F, CHAN_MAXF );
 #else
-         if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
+         if (ctx->Color.BlendEquationRGB==GL_FUNC_ADD) {
             r = Rs * sR + Rd * dR + 0.5F;
             g = Gs * sG + Gd * dG + 0.5F;
             b = Bs * sB + Bd * dB + 0.5F;
-            a = As * sA + Ad * dA + 0.5F;
          }
-         else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
+         else if (ctx->Color.BlendEquationRGB==GL_FUNC_SUBTRACT) {
             r = Rs * sR - Rd * dR + 0.5F;
             g = Gs * sG - Gd * dG + 0.5F;
             b = Bs * sB - Bd * dB + 0.5F;
-            a = As * sA - Ad * dA + 0.5F;
          }
-         else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
+         else if (ctx->Color.BlendEquationRGB==GL_FUNC_REVERSE_SUBTRACT) {
             r = Rd * dR - Rs * sR + 0.5F;
             g = Gd * dG - Gs * sG + 0.5F;
             b = Bd * dB - Bs * sB + 0.5F;
-            a = Ad * dA - As * sA + 0.5F;
          }
+         else if (ctx->Color.BlendEquationRGB==GL_MIN) {
+	    r = MIN2( Rd, Rs );
+	    g = MIN2( Gd, Gs );
+	    b = MIN2( Bd, Bs );
+	 }
+         else if (ctx->Color.BlendEquationRGB==GL_MAX) {
+	    r = MAX2( Rd, Rs );
+	    g = MAX2( Gd, Gs );
+	    b = MAX2( Bd, Bs );
+	 }
          else {
             /* should never get here */
-            r = g = b = a = 0.0F;  /* silence uninitialized var warning */
+            r = g = b = 0.0F;  /* silence uninitialized var warning */
+            _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+         }
+
+         if (ctx->Color.BlendEquationA==GL_FUNC_ADD) {
+            a = As * sA + Ad * dA + 0.5F;
+         }
+         else if (ctx->Color.BlendEquationA==GL_FUNC_SUBTRACT) {
+            a = As * sA - Ad * dA + 0.5F;
+         }
+         else if (ctx->Color.BlendEquationA==GL_FUNC_REVERSE_SUBTRACT) {
+            a = Ad * dA - As * sA + 0.5F;
+         }
+         else if (ctx->Color.BlendEquationA==GL_MIN) {
+	    a = MIN2( Ad, As );
+	 }
+         else if (ctx->Color.BlendEquationA==GL_MAX) {
+	    a = MAX2( Ad, As );
+	 }
+         else {
+            /* should never get here */
+            a = 0.0F;  /* silence uninitialized var warning */
             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
          }
 
@@ -699,13 +764,16 @@
  */
 void _swrast_choose_blend_func( GLcontext *ctx )
 {
-   const GLenum eq = ctx->Color.BlendEquation;
+   const GLenum eq = ctx->Color.BlendEquationRGB;
    const GLenum srcRGB = ctx->Color.BlendSrcRGB;
    const GLenum dstRGB = ctx->Color.BlendDstRGB;
    const GLenum srcA = ctx->Color.BlendSrcA;
    const GLenum dstA = ctx->Color.BlendDstA;
 
-   if (eq==GL_MIN_EXT) {
+   if (ctx->Color.BlendEquationRGB != ctx->Color.BlendEquationA) {
+      SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
+   }
+   else if (eq==GL_MIN) {
       /* Note: GL_MIN ignores the blending weight factors */
 #if defined(USE_MMX_ASM)
       if ( cpu_has_mmx ) {
@@ -715,7 +783,7 @@
 #endif
          SWRAST_CONTEXT(ctx)->BlendFunc = blend_min;
    }
-   else if (eq==GL_MAX_EXT) {
+   else if (eq==GL_MAX) {
       /* Note: GL_MAX ignores the blending weight factors */
 #if defined(USE_MMX_ASM)
       if ( cpu_has_mmx ) {
@@ -728,7 +796,7 @@
    else if (srcRGB != srcA || dstRGB != dstA) {
       SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
    }
-   else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
+   else if (eq==GL_FUNC_ADD && srcRGB==GL_SRC_ALPHA
             && dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
 #if defined(USE_MMX_ASM)
       if ( cpu_has_mmx ) {
@@ -738,7 +806,7 @@
 #endif
 	 SWRAST_CONTEXT(ctx)->BlendFunc = blend_transparency;
    }
-   else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
+   else if (eq==GL_FUNC_ADD && srcRGB==GL_ONE && dstRGB==GL_ONE) {
 #if defined(USE_MMX_ASM)
       if ( cpu_has_mmx ) {
          SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_add;
@@ -747,10 +815,10 @@
 #endif
          SWRAST_CONTEXT(ctx)->BlendFunc = blend_add;
    }
-   else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
+   else if (((eq==GL_FUNC_ADD || eq==GL_FUNC_REVERSE_SUBTRACT)
 	     && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
 	    ||
-	    ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
+	    ((eq==GL_FUNC_ADD || eq==GL_FUNC_SUBTRACT)
 	     && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
 #if defined(USE_MMX_ASM)
       if ( cpu_has_mmx ) {
@@ -760,10 +828,10 @@
 #endif
          SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate;
    }
-   else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
+   else if (eq==GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
       SWRAST_CONTEXT(ctx)->BlendFunc = blend_noop;
    }
-   else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
+   else if (eq==GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
       SWRAST_CONTEXT(ctx)->BlendFunc = blend_replace;
    }
    else {
diff --git a/src/mesa/x86/glapi_x86.S b/src/mesa/x86/glapi_x86.S
index 01e81b9..af44a89 100644
--- a/src/mesa/x86/glapi_x86.S
+++ b/src/mesa/x86/glapi_x86.S
@@ -5514,5 +5514,17 @@
 	MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX)
 	JMP(GL_OFFSET(_gloffset_GetQueryObjectuivARB))
 
+ALIGNTEXT16
+GLOBL_FN(GL_PREFIX(BlendEquationSeparateEXT,BlendEquationSeparateEXT@8))
+GL_PREFIX(BlendEquationSeparateEXT,BlendEquationSeparateEXT@8):
+	MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX)
+	JMP(GL_OFFSET(_gloffset_BlendEquationSeparateEXT))
+
+ALIGNTEXT16
+GLOBL_FN(GL_PREFIX(BlendEquationSeparateATI,BlendEquationSeparateATI@8))
+GL_PREFIX(BlendEquationSeparateATI,BlendEquationSeparateATI@8):
+	MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX)
+	JMP(GL_OFFSET(_gloffset_BlendEquationSeparateEXT))
+
 
 #endif  /* __WIN32__ */