diff -ru old/Mesa-7.0.2/include/GL/gl.h Mesa-7.0.2/include/GL/gl.h
--- old/Mesa-7.0.2/include/GL/gl.h	2007-11-01 17:30:52.000000000 +0200
+++ Mesa-7.0.2/include/GL/gl.h	2008-01-04 11:36:24.000000000 +0200
@@ -1625,6 +1625,10 @@
 #define GL_FUNC_REVERSE_SUBTRACT		0x800B
 #define GL_BLEND_COLOR				0x8005
 
+/* Extensions by Jaakko.Hyvatti@foreca.com */
+#define GL_SRC_ALPHA_RELATIVE_FORECA		0x8161
+#define GL_ONE_MINUS_SRC_ALPHA_RELATIVE_FORECA	0x8162
+
 
 GLAPI void GLAPIENTRY glColorTable( GLenum target, GLenum internalformat,
                                     GLsizei width, GLenum format,
diff -ru old/Mesa-7.0.2/src/mesa/main/blend.c Mesa-7.0.2/src/mesa/main/blend.c
--- old/Mesa-7.0.2/src/mesa/main/blend.c	2007-06-22 01:10:54.000000000 +0300
+++ Mesa-7.0.2/src/mesa/main/blend.c	2008-01-04 11:36:24.000000000 +0200
@@ -101,6 +101,8 @@
       case GL_ONE_MINUS_DST_COLOR:
       case GL_SRC_ALPHA:
       case GL_ONE_MINUS_SRC_ALPHA:
+      case GL_SRC_ALPHA_RELATIVE_FORECA:
+      case GL_ONE_MINUS_SRC_ALPHA_RELATIVE_FORECA:
       case GL_DST_ALPHA:
       case GL_ONE_MINUS_DST_ALPHA:
       case GL_SRC_ALPHA_SATURATE:
@@ -128,6 +130,8 @@
       case GL_ONE_MINUS_SRC_COLOR:
       case GL_SRC_ALPHA:
       case GL_ONE_MINUS_SRC_ALPHA:
+      case GL_SRC_ALPHA_RELATIVE_FORECA:
+      case GL_ONE_MINUS_SRC_ALPHA_RELATIVE_FORECA:
       case GL_DST_ALPHA:
       case GL_ONE_MINUS_DST_ALPHA:
       case GL_CONSTANT_COLOR:
diff -ru old/Mesa-7.0.2/src/mesa/main/extensions.c Mesa-7.0.2/src/mesa/main/extensions.c
--- old/Mesa-7.0.2/src/mesa/main/extensions.c	2007-11-01 17:30:52.000000000 +0200
+++ Mesa-7.0.2/src/mesa/main/extensions.c	2008-01-04 11:41:45.000000000 +0200
@@ -168,6 +168,7 @@
    { OFF, "GL_SGIX_shadow_ambient",            F(SGIX_shadow_ambient) },
    { OFF, "GL_SUN_multi_draw_arrays",          F(EXT_multi_draw_arrays) },
    { OFF, "GL_S3_s3tc",                        F(S3_s3tc) },
+   { OFF, "GL_FORECA_blend_relative",          F(FORECA_blend_relative) },
 };
 
 
@@ -291,6 +292,7 @@
    ctx->Extensions.SGIX_depth_texture = GL_TRUE;
    ctx->Extensions.SGIX_shadow = GL_TRUE;
    ctx->Extensions.SGIX_shadow_ambient = GL_TRUE;
+   ctx->Extensions.FORECA_blend_relative = GL_TRUE;
 #if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
    ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE;
 #endif
diff -ru old/Mesa-7.0.2/src/mesa/main/mtypes.h Mesa-7.0.2/src/mesa/main/mtypes.h
--- old/Mesa-7.0.2/src/mesa/main/mtypes.h	2007-11-01 17:30:52.000000000 +0200
+++ Mesa-7.0.2/src/mesa/main/mtypes.h	2008-01-04 11:36:24.000000000 +0200
@@ -2600,6 +2600,7 @@
    GLboolean SGIX_shadow_ambient; /* or GL_ARB_shadow_ambient */
    GLboolean TDFX_texture_compression_FXT1;
    GLboolean S3_s3tc;
+   GLboolean FORECA_blend_relative;
    /*@}*/
    /* The extension string */
    const GLubyte *String;
diff -ru old/Mesa-7.0.2/src/mesa/swrast/s_blend.c Mesa-7.0.2/src/mesa/swrast/s_blend.c
--- old/Mesa-7.0.2/src/mesa/swrast/s_blend.c	2007-06-22 01:10:54.000000000 +0300
+++ Mesa-7.0.2/src/mesa/swrast/s_blend.c	2008-01-04 14:14:21.000000000 +0200
@@ -238,6 +238,66 @@
 
 
 
+/*
+ * Correct transparency blending mode for ubyte with FORECA extension.
+ * Jaakko.Hyvatti@foreca.com
+ *
+ * glBlendFuncSeparate
+ *   (/ * sfactorRGB * / GL_SRC_ALPHA_RELATIVE_FORECA,
+ *    / * dfactorRGB * / GL_ONE_MINUS_SRC_ALPHA_RELATIVE_FORECA,
+ *    / * sfactorA   * / GL_ONE,
+ *    / * dfactorA   * / GL_ONE_MINUS_SRC_ALPHA);
+ *
+ */
+static void _BLENDAPI
+blend_transparency_relative_ubyte( GLcontext *ctx, GLuint n, const GLubyte mask[],
+				   GLvoid *src, CONST GLvoid *dst, GLenum chanType )
+{
+   GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+   const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+   GLuint i;
+   ASSERT(ctx->Color.BlendEquationRGB==GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA_RELATIVE_FORECA);
+   ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA_RELATIVE_FORECA);
+   ASSERT(ctx->Color.BlendSrcA==GL_ONE
+	  && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
+	  || ctx->Color.BlendSrcA==GL_ONE_MINUS_DST_ALPHA
+	  && ctx->Color.BlendDstA==GL_ONE);
+   ASSERT(chanType == GL_UNSIGNED_BYTE);
+   (void) ctx;
+
+   for (i=0;i<n;i++) {
+      if (mask[i]) {
+         const GLint t = rgba[i][ACOMP];  /* t in [0, 255] */
+         if (t == 0) {
+            /* 0% alpha */
+	    COPY_4UBV(rgba[i], dest[i]);
+         }
+         else if (t != 255) {
+	    GLint divtemp;
+            const GLint a = t + DIV255((255 - t) * dest[i][ACOMP]);
+	    // No worries about a==0, that will not happen.
+	    const GLint ts = t * 255 / a;
+	    const GLint td = 255 - ts;
+            const GLint r = DIV255(rgba[i][RCOMP] * ts + dest[i][RCOMP] * td);
+            const GLint g = DIV255(rgba[i][GCOMP] * ts + dest[i][GCOMP] * td);
+            const GLint b = DIV255(rgba[i][BCOMP] * ts + dest[i][BCOMP] * td);
+            ASSERT(r <= 255);
+            ASSERT(g <= 255);
+            ASSERT(b <= 255);
+            ASSERT(a <= 255);
+            rgba[i][RCOMP] = (GLubyte) r;
+            rgba[i][GCOMP] = (GLubyte) g;
+            rgba[i][BCOMP] = (GLubyte) b;
+            rgba[i][ACOMP] = (GLubyte) a;
+         }
+      }
+   }
+}
+
+
+
 /**
  * Add src and dest: glBlendFunc(GL_ONE, GL_ONE).
  * Any chanType ok.
@@ -499,6 +559,147 @@
           * the sX and dX variables just once before the loop.
           */
 
+	 /* Process Alpha factors first, as these results may be used */
+	 /* in the color channel processing later. */
+
+         /* Source Alpha factor */ 
+         switch (ctx->Color.BlendSrcA) { 
+            case GL_ZERO: 
+               sA = 0.0F; 
+               break; 
+            case GL_ONE: 
+               sA = 1.0F; 
+               break; 
+            case GL_DST_COLOR: 
+               sA = Ad; 
+               break; 
+            case GL_ONE_MINUS_DST_COLOR: 
+               sA = 1.0F - Ad; 
+               break; 
+            case GL_SRC_ALPHA: 
+               sA = As; 
+               break; 
+            case GL_ONE_MINUS_SRC_ALPHA: 
+               sA = 1.0F - As; 
+               break; 
+            case GL_DST_ALPHA: 
+               sA = Ad; 
+               break; 
+            case GL_ONE_MINUS_DST_ALPHA: 
+               sA = 1.0F - Ad; 
+               break; 
+            case GL_SRC_ALPHA_SATURATE: 
+               sA = 1.0; 
+               break; 
+            case GL_CONSTANT_COLOR: 
+               sA = ctx->Color.BlendColor[3]; 
+               break; 
+            case GL_ONE_MINUS_CONSTANT_COLOR: 
+               sA = 1.0F - ctx->Color.BlendColor[3]; 
+               break; 
+            case GL_CONSTANT_ALPHA: 
+               sA = ctx->Color.BlendColor[3]; 
+               break; 
+            case GL_ONE_MINUS_CONSTANT_ALPHA: 
+               sA = 1.0F - ctx->Color.BlendColor[3]; 
+               break; 
+            case GL_SRC_COLOR: 
+               sA = As; 
+               break; 
+            case GL_ONE_MINUS_SRC_COLOR: 
+               sA = 1.0F - As; 
+               break; 
+            default: 
+               /* this should never happen */ 
+               sA = 0.0F; 
+               _mesa_problem(ctx, "Bad blend source A factor in blend_general_float"); 
+               return; 
+         } 
+ 
+         /* Dest Alpha factor */ 
+         switch (ctx->Color.BlendDstA) { 
+            case GL_ZERO: 
+               dA = 0.0F; 
+               break; 
+            case GL_ONE: 
+               dA = 1.0F; 
+               break; 
+            case GL_SRC_COLOR: 
+               dA = As; 
+               break; 
+            case GL_ONE_MINUS_SRC_COLOR: 
+               dA = 1.0F - As; 
+               break; 
+            case GL_SRC_ALPHA: 
+               dA = As; 
+               break; 
+            case GL_ONE_MINUS_SRC_ALPHA: 
+               dA = 1.0F - As; 
+               break; 
+            case GL_DST_ALPHA: 
+               dA = Ad; 
+               break; 
+            case GL_ONE_MINUS_DST_ALPHA: 
+               dA = 1.0F - Ad; 
+               break; 
+            case GL_CONSTANT_COLOR: 
+               dA = ctx->Color.BlendColor[3]; 
+               break; 
+            case GL_ONE_MINUS_CONSTANT_COLOR: 
+               dA = 1.0F - ctx->Color.BlendColor[3]; 
+               break; 
+            case GL_CONSTANT_ALPHA: 
+               dA = ctx->Color.BlendColor[3]; 
+               break; 
+            case GL_ONE_MINUS_CONSTANT_ALPHA: 
+               dA = 1.0F - ctx->Color.BlendColor[3]; 
+               break; 
+            case GL_DST_COLOR: 
+               dA = Ad; 
+               break; 
+            case GL_ONE_MINUS_DST_COLOR: 
+               dA = 1.0F - Ad; 
+               break; 
+            default: 
+               /* this should never happen */ 
+               dA = 0.0F; 
+               _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float"); 
+               return; 
+         } 
+ 
+ 
+         /* compute blended alpha */ 
+	 /* This is done before any RGB handling, because some functions */ 
+	 /* there use this final alpha. */ 
+         switch (ctx->Color.BlendEquationA) { 
+         case GL_FUNC_ADD: 
+            a = As * sA + Ad * dA; 
+            break; 
+         case GL_FUNC_SUBTRACT: 
+            a = As * sA - Ad * dA; 
+            break; 
+         case GL_FUNC_REVERSE_SUBTRACT: 
+            a = Ad * dA - As * sA; 
+            break; 
+         case GL_MIN: 
+	    a = MIN2( Ad, As ); 
+            break; 
+         case GL_MAX: 
+	    a = MAX2( Ad, As ); 
+            break; 
+         default: 
+            /* should never get here */ 
+            a = 0.0F;  /* silence uninitialized var warning */ 
+            _mesa_problem(ctx, "unexpected BlendEquation in blend_general()"); 
+            return; 
+         } 
+ 
+         /* final clamping */ 
+#if 0 
+         a = CLAMP( a, 0.0F, 1.0F ); 
+#endif 
+
+
          /* Source RGB factor */
          switch (ctx->Color.BlendSrcRGB) {
             case GL_ZERO:
@@ -523,6 +724,19 @@
             case GL_ONE_MINUS_SRC_ALPHA:
                sR = sG = sB = 1.0F - As;
                break;
+            case GL_SRC_ALPHA_RELATIVE_FORECA:
+	       // This is the usual function for SRC factor.
+	       if (0.0 == a)
+		  sR = sG = sB = 0.0F; /* This value usually has no effect. */
+	       else
+		  sR = sG = sB = As / a;
+               break;
+            case GL_ONE_MINUS_SRC_ALPHA_RELATIVE_FORECA:
+	       if (0.0 == a)
+		  sR = sG = sB = 1.0F; /* This value usually has no effect. */
+	       else
+		  sR = sG = sB = 1.0F - As / a;
+               break;
             case GL_DST_ALPHA:
                sR = sG = sB = Ad;
                break;
@@ -569,60 +783,6 @@
                return;
          }
 
-         /* Source Alpha factor */
-         switch (ctx->Color.BlendSrcA) {
-            case GL_ZERO:
-               sA = 0.0F;
-               break;
-            case GL_ONE:
-               sA = 1.0F;
-               break;
-            case GL_DST_COLOR:
-               sA = Ad;
-               break;
-            case GL_ONE_MINUS_DST_COLOR:
-               sA = 1.0F - Ad;
-               break;
-            case GL_SRC_ALPHA:
-               sA = As;
-               break;
-            case GL_ONE_MINUS_SRC_ALPHA:
-               sA = 1.0F - As;
-               break;
-            case GL_DST_ALPHA:
-               sA = Ad;
-               break;
-            case GL_ONE_MINUS_DST_ALPHA:
-               sA = 1.0F - Ad;
-               break;
-            case GL_SRC_ALPHA_SATURATE:
-               sA = 1.0;
-               break;
-            case GL_CONSTANT_COLOR:
-               sA = ctx->Color.BlendColor[3];
-               break;
-            case GL_ONE_MINUS_CONSTANT_COLOR:
-               sA = 1.0F - ctx->Color.BlendColor[3];
-               break;
-            case GL_CONSTANT_ALPHA:
-               sA = ctx->Color.BlendColor[3];
-               break;
-            case GL_ONE_MINUS_CONSTANT_ALPHA:
-               sA = 1.0F - ctx->Color.BlendColor[3];
-               break;
-            case GL_SRC_COLOR:
-               sA = As;
-               break;
-            case GL_ONE_MINUS_SRC_COLOR:
-               sA = 1.0F - As;
-               break;
-            default:
-               /* this should never happen */
-               sA = 0.0F;
-               _mesa_problem(ctx, "Bad blend source A factor in blend_general_float");
-               return;
-         }
-
          /* Dest RGB factor */
          switch (ctx->Color.BlendDstRGB) {
             case GL_ZERO:
@@ -647,6 +807,19 @@
             case GL_ONE_MINUS_SRC_ALPHA:
                dR = dG = dB = 1.0F - As;
                break;
+            case GL_SRC_ALPHA_RELATIVE_FORECA:
+	       if (0.0 == a)
+		  dR = dG = dB = 0.0F; /* This value usually has no effect. */
+	       else
+		  dR = dG = dB = As / a;
+               break;
+            case GL_ONE_MINUS_SRC_ALPHA_RELATIVE_FORECA:
+	       // This is the usual function for DST factor.
+	       if (0.0 == a)
+		  dR = dG = dB = 1.0F; /* This value usually has no effect. */
+	       else
+		  dR = dG = dB = 1.0F - As / a;
+               break;
             case GL_DST_ALPHA:
                dR = dG = dB = Ad;
                break;
@@ -686,76 +859,22 @@
                return;
          }
 
-         /* Dest Alpha factor */
-         switch (ctx->Color.BlendDstA) {
-            case GL_ZERO:
-               dA = 0.0F;
-               break;
-            case GL_ONE:
-               dA = 1.0F;
-               break;
-            case GL_SRC_COLOR:
-               dA = As;
-               break;
-            case GL_ONE_MINUS_SRC_COLOR:
-               dA = 1.0F - As;
-               break;
-            case GL_SRC_ALPHA:
-               dA = As;
-               break;
-            case GL_ONE_MINUS_SRC_ALPHA:
-               dA = 1.0F - As;
-               break;
-            case GL_DST_ALPHA:
-               dA = Ad;
-               break;
-            case GL_ONE_MINUS_DST_ALPHA:
-               dA = 1.0F - Ad;
-               break;
-            case GL_CONSTANT_COLOR:
-               dA = ctx->Color.BlendColor[3];
-               break;
-            case GL_ONE_MINUS_CONSTANT_COLOR:
-               dA = 1.0F - ctx->Color.BlendColor[3];
-               break;
-            case GL_CONSTANT_ALPHA:
-               dA = ctx->Color.BlendColor[3];
-               break;
-            case GL_ONE_MINUS_CONSTANT_ALPHA:
-               dA = 1.0F - ctx->Color.BlendColor[3];
-               break;
-            case GL_DST_COLOR:
-               dA = Ad;
-               break;
-            case GL_ONE_MINUS_DST_COLOR:
-               dA = 1.0F - Ad;
-               break;
-            default:
-               /* this should never happen */
-               dA = 0.0F;
-               _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float");
-               return;
-         }
-
          /* compute the blended RGB */
          switch (ctx->Color.BlendEquationRGB) {
          case GL_FUNC_ADD:
             r = Rs * sR + Rd * dR;
             g = Gs * sG + Gd * dG;
             b = Bs * sB + Bd * dB;
-            a = As * sA + Ad * dA;
             break;
          case GL_FUNC_SUBTRACT:
             r = Rs * sR - Rd * dR;
             g = Gs * sG - Gd * dG;
             b = Bs * sB - Bd * dB;
-            a = As * sA - Ad * dA;
             break;
          case GL_FUNC_REVERSE_SUBTRACT:
             r = Rd * dR - Rs * sR;
             g = Gd * dG - Gs * sG;
             b = Bd * dB - Bs * sB;
-            a = Ad * dA - As * sA;
             break;
          case GL_MIN:
 	    r = MIN2( Rd, Rs );
@@ -774,36 +893,12 @@
             return;
          }
 
-         /* compute the blended alpha */
-         switch (ctx->Color.BlendEquationA) {
-         case GL_FUNC_ADD:
-            a = As * sA + Ad * dA;
-            break;
-         case GL_FUNC_SUBTRACT:
-            a = As * sA - Ad * dA;
-            break;
-         case GL_FUNC_REVERSE_SUBTRACT:
-            a = Ad * dA - As * sA;
-            break;
-         case GL_MIN:
-	    a = MIN2( Ad, As );
-            break;
-         case GL_MAX:
-	    a = MAX2( Ad, As );
-            break;
-         default:
-            /* should never get here */
-            a = 0.0F;  /* silence uninitialized var warning */
-            _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
-            return;
-         }
-
          /* final clamping */
 #if 0
          rgba[i][RCOMP] = MAX2( r, 0.0F );
          rgba[i][GCOMP] = MAX2( g, 0.0F );
          rgba[i][BCOMP] = MAX2( b, 0.0F );
-         rgba[i][ACOMP] = CLAMP( a, 0.0F, 1.0F );
+         rgba[i][ACOMP] = a; /* clamping done earlier */
 #else
          ASSIGN_4V(rgba[i], r, g, b, a);
 #endif
@@ -924,7 +1019,18 @@
          swrast->BlendFunc = blend_max;
    }
    else if (srcRGB != srcA || dstRGB != dstA) {
-      swrast->BlendFunc = blend_general;
+      if ( eq == GL_FUNC_ADD
+	   && chanType == GL_UNSIGNED_BYTE
+	   && srcRGB == GL_SRC_ALPHA_RELATIVE_FORECA
+	   && dstRGB == GL_ONE_MINUS_SRC_ALPHA_RELATIVE_FORECA
+	   && ( (srcA == GL_ONE && dstA == GL_ONE_MINUS_SRC_ALPHA)
+		|| (srcA == GL_ONE_MINUS_SRC_ALPHA && dstA == GL_ONE))) {
+	 swrast->BlendFunc = blend_transparency_relative_ubyte;
+      }
+      else
+      {
+	 swrast->BlendFunc = blend_general;
+      }
    }
    else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA
             && dstRGB == GL_ONE_MINUS_SRC_ALPHA) {
