more work on GL_ARB_texture_compression
[mesa.git] / src / mesa / main / blend.c
index 6bf3581b8fb791085a4e8d09bb2310b54fc524b9..7bbffcb8dfa2bd101ff52d9b60959df4559f65a6 100644 (file)
@@ -1,8 +1,8 @@
-/* $Id: blend.c,v 1.3 1999/09/30 11:18:21 keithw Exp $ */
+/* $Id: blend.c,v 1.14 2000/04/11 21:38:08 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.1
+ * Version:  3.3
  * 
  * Copyright (C) 1999  Brian Paul   All Rights Reserved.
  * 
@@ -29,9 +29,7 @@
 #ifdef PC_HEADER
 #include "all.h"
 #else
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include "glheader.h"
 #include "alphabuf.h"
 #include "blend.h"
 #include "context.h"
 #include "pb.h"
 #include "span.h"
 #include "types.h"
-#ifdef XFree86Server
-#include "GL/xf86glx.h"
-#endif
 #endif
 
 
-void gl_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+void
+_mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
 {
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFunc");
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
@@ -105,11 +102,12 @@ void gl_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
 }
 
 
-/* GL_INGR_blend_func_separate */
+/* GL_EXT_blend_func_separate */
 void
-gl_BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
-                      GLenum sfactorA, GLenum dfactorA )
+_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
+                            GLenum sfactorA, GLenum dfactorA )
 {
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFuncSeparate");
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
@@ -213,8 +211,10 @@ gl_BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
 
 
 /* This is really an extension function! */
-void gl_BlendEquation( GLcontext *ctx, GLenum mode )
+void
+_mesa_BlendEquation( GLenum mode )
 {
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendEquation");
 
    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
@@ -255,22 +255,28 @@ void gl_BlendEquation( GLcontext *ctx, GLenum mode )
 
 
 
-void gl_BlendColor( GLcontext *ctx, GLclampf red, GLclampf green,
-                   GLclampf blue, GLclampf alpha )
+void
+_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
 {
-   ctx->Color.BlendColor[0] = CLAMP( red,   0.0, 1.0 );
-   ctx->Color.BlendColor[1] = CLAMP( green, 0.0, 1.0 );
-   ctx->Color.BlendColor[2] = CLAMP( blue,  0.0, 1.0 );
-   ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0, 1.0 );
+   GET_CURRENT_CONTEXT(ctx);
+   ctx->Color.BlendColor[0] = CLAMP( red,   0.0F, 1.0F );
+   ctx->Color.BlendColor[1] = CLAMP( green, 0.0F, 1.0F );
+   ctx->Color.BlendColor[2] = CLAMP( blue,  0.0F, 1.0F );
+   ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0F, 1.0F );
 }
 
-
+#ifdef USE_MMX_ASM
+#define _BLENDAPI _ASMAPI
+#else
+#define _BLENDAPI
+#endif
 
 /*
  * Common transparency blending mode.
  */
-static void blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
-                                GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
+                    GLubyte rgba[][4], CONST GLubyte dest[][4] )
 {
    GLuint i;
    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
@@ -280,30 +286,31 @@ static void blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
 
    for (i=0;i<n;i++) {
       if (mask[i]) {
-         GLint t = rgba[i][ACOMP];  /* t in [0,255] */
+         const GLint t = rgba[i][ACOMP];  /* t in [0,255] */
          if (t == 0) {
+            /* 0% alpha */
             rgba[i][RCOMP] = dest[i][RCOMP];
             rgba[i][GCOMP] = dest[i][GCOMP];
             rgba[i][BCOMP] = dest[i][BCOMP];
             rgba[i][ACOMP] = dest[i][ACOMP];
          }
-         else if (t == 255) {
-            /* no-op */
+         else if (t == CHAN_MAX) {
+            /* 100% alpha, no-op */
          }
          else {
-            GLint s = 255 - t;
-            GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8;
-            GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8;
-            GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8;
-            GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8;
-            ASSERT(r <= 255);
-            ASSERT(g <= 255);
-            ASSERT(b <= 255);
-            ASSERT(a <= 255);
-            rgba[i][RCOMP] = r;
-            rgba[i][GCOMP] = g;
-            rgba[i][BCOMP] = b;
-            rgba[i][ACOMP] = a;
+            const GLint s = CHAN_MAX - t;
+            const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8;
+            const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8;
+            const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8;
+            const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8;
+            ASSERT(r <= CHAN_MAX);
+            ASSERT(g <= CHAN_MAX);
+            ASSERT(b <= CHAN_MAX);
+            ASSERT(a <= CHAN_MAX);
+            rgba[i][RCOMP] = (GLubyte) r;
+            rgba[i][GCOMP] = (GLubyte) g;
+            rgba[i][BCOMP] = (GLubyte) b;
+            rgba[i][ACOMP] = (GLubyte) a;
          }
       }
    }
@@ -314,8 +321,9 @@ static void blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
 /*
  * Add src and dest.
  */
-static void blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
-                       GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
+           GLubyte rgba[][4], CONST GLubyte dest[][4] )
 {
    GLuint i;
    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
@@ -329,10 +337,10 @@ static void blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
          GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
          GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
          GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
-         rgba[i][RCOMP] = MIN2( r, 255 );
-         rgba[i][GCOMP] = MIN2( g, 255 );
-         rgba[i][BCOMP] = MIN2( b, 255 );
-         rgba[i][ACOMP] = MIN2( a, 255 );
+         rgba[i][RCOMP] = (GLubyte) MIN2( r, CHAN_MAX );
+         rgba[i][GCOMP] = (GLubyte) MIN2( g, CHAN_MAX );
+         rgba[i][BCOMP] = (GLubyte) MIN2( b, CHAN_MAX );
+         rgba[i][ACOMP] = (GLubyte) MIN2( a, CHAN_MAX );
       }
    }
 }
@@ -342,8 +350,9 @@ static void blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
 /*
  * Blend min function  (for GL_EXT_blend_minmax)
  */
-static void blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
-                       GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
+           GLubyte rgba[][4], CONST GLubyte dest[][4] )
 {
    GLuint i;
    ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
@@ -351,10 +360,10 @@ static void blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
 
    for (i=0;i<n;i++) {
       if (mask[i]) {
-         rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
-         rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
-         rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
-         rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
+         rgba[i][RCOMP] = (GLubyte) MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
+         rgba[i][GCOMP] = (GLubyte) MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
+         rgba[i][BCOMP] = (GLubyte) MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
+         rgba[i][ACOMP] = (GLubyte) MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
       }
    }
 }
@@ -364,8 +373,9 @@ static void blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
 /*
  * Blend max function  (for GL_EXT_blend_minmax)
  */
-static void blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
-                       GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
+           GLubyte rgba[][4], CONST GLubyte dest[][4] )
 {
    GLuint i;
    ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
@@ -373,10 +383,10 @@ static void blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
 
    for (i=0;i<n;i++) {
       if (mask[i]) {
-         rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
-         rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
-         rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
-         rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
+         rgba[i][RCOMP] = (GLubyte) MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
+         rgba[i][GCOMP] = (GLubyte) MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
+         rgba[i][BCOMP] = (GLubyte) MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
+         rgba[i][ACOMP] = (GLubyte) MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
       }
    }
 }
@@ -386,8 +396,9 @@ static void blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
 /*
  * Modulate:  result = src * dest
  */
-static void blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
-                            GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
+                GLubyte rgba[][4], CONST GLubyte dest[][4] )
 {
    GLuint i;
    (void) ctx;
@@ -398,10 +409,10 @@ static void blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
          GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8;
          GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8;
          GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8;
-         rgba[i][RCOMP] = r;
-         rgba[i][GCOMP] = g;
-         rgba[i][BCOMP] = b;
-         rgba[i][ACOMP] = a;
+         rgba[i][RCOMP] = (GLubyte) r;
+         rgba[i][GCOMP] = (GLubyte) g;
+         rgba[i][BCOMP] = (GLubyte) b;
+         rgba[i][ACOMP] = (GLubyte) a;
       }
    }
 }
@@ -415,13 +426,14 @@ static void blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
  * In/Out:  rgba - the incoming and modified pixels
  * Input:  dest - the pixels from the dest color buffer
  */
-static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
-                           GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
+               GLubyte rgba[][4], CONST GLubyte dest[][4] )
 {
-   GLfloat rscale = 1.0F / 255.0F;
-   GLfloat gscale = 1.0F / 255.0F;
-   GLfloat bscale = 1.0F / 255.0F;
-   GLfloat ascale = 1.0F / 255.0F;
+   GLfloat rscale = 1.0F / CHAN_MAXF;
+   GLfloat gscale = 1.0F / CHAN_MAXF;
+   GLfloat bscale = 1.0F / CHAN_MAXF;
+   GLfloat ascale = 1.0F / CHAN_MAXF;
    GLuint i;
 
    for (i=0;i<n;i++) {
@@ -475,7 +487,7 @@ static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
                sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
                break;
             case GL_SRC_ALPHA_SATURATE:
-               if (As < 1.0F - (GLfloat) Ad * ascale) {
+               if (As < CHAN_MAX - Ad) {
                   sR = sG = sB = (GLfloat) As * ascale;
                }
                else {
@@ -547,6 +559,7 @@ static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
                break;
             default:
                /* this should never happen */
+               sA = 0.0F;
                gl_problem(ctx, "Bad blend source A factor in do_blend");
          }
 
@@ -598,6 +611,7 @@ static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
                break;
             default:
                /* this should never happen */
+               dR = dG = dB = 0.0F;
                gl_problem(ctx, "Bad blend dest RGB factor in do_blend");
          }
 
@@ -641,6 +655,7 @@ static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
                break;
             default:
                /* this should never happen */
+               dA = 0.0F;
                gl_problem(ctx, "Bad blend dest A factor in do_blend");
               return;
          }
@@ -684,12 +699,17 @@ static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
             b = Bd * dB - Bs * sB;
             a = Ad * dA - As * sA;
          }
+         else {
+            /* should never get here */
+            r = g = b = a = 0.0F;  /* silence uninitialized var warning */
+            gl_problem(ctx, "unexpected BlendEquation in blend_general()");
+         }
 
          /* final clamping */
-         rgba[i][RCOMP] = (GLint) CLAMP( r, 0.0F, 255.0F );
-         rgba[i][GCOMP] = (GLint) CLAMP( g, 0.0F, 255.0F );
-         rgba[i][BCOMP] = (GLint) CLAMP( b, 0.0F, 255.0F );
-         rgba[i][ACOMP] = (GLint) CLAMP( a, 0.0F, 255.0F );
+         rgba[i][RCOMP] = (GLubyte) (GLint) CLAMP( r, 0.0F, CHAN_MAXF );
+         rgba[i][GCOMP] = (GLubyte) (GLint) CLAMP( g, 0.0F, CHAN_MAXF );
+         rgba[i][BCOMP] = (GLubyte) (GLint) CLAMP( b, 0.0F, CHAN_MAXF );
+         rgba[i][ACOMP] = (GLubyte) (GLint) CLAMP( a, 0.0F, CHAN_MAXF );
       }
    }
 }
@@ -720,7 +740,8 @@ static void set_blend_function( GLcontext *ctx )
     */
    if (gl_x86_cpu_features & GL_CPU_MMX) {
       gl_mmx_set_blend_function (ctx);
-   } else
+   }
+   else
 #endif
    if (srcRGB != srcA || dstRGB != dstA) {
       ctx->Color.BlendFunc = blend_general;
@@ -759,8 +780,9 @@ static void set_blend_function( GLcontext *ctx )
  *         mask - boolean mask indicating which pixels to blend.
  * In/Out:  rgba - pixel values
  */
-void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
-                   GLubyte rgba[][4], const GLubyte mask[] )
+void
+_mesa_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
+                  GLubyte rgba[][4], const GLubyte mask[] )
 {
    GLubyte dest[MAX_WIDTH][4];
 
@@ -770,7 +792,7 @@ void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
    }
 
    /* Read span of current frame buffer pixels */
-   gl_read_rgba_span( ctx, n, x, y, dest );
+   gl_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest );
 
    if (!ctx->Color.BlendFunc)
       set_blend_function(ctx);
@@ -789,9 +811,10 @@ void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
  *         mask - boolean mask indicating which pixels to blend.
  * In/Out:  rgba - pixel values
  */
-void gl_blend_pixels( GLcontext *ctx,
-                      GLuint n, const GLint x[], const GLint y[],
-                     GLubyte rgba[][4], const GLubyte mask[] )
+void
+_mesa_blend_pixels( GLcontext *ctx,
+                    GLuint n, const GLint x[], const GLint y[],
+                    GLubyte rgba[][4], const GLubyte mask[] )
 {
    GLubyte dest[PB_SIZE][4];
 
@@ -803,7 +826,7 @@ void gl_blend_pixels( GLcontext *ctx,
    /* Read pixels from current color buffer */
    (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
    if (ctx->RasterMask & ALPHABUF_BIT) {
-      gl_read_alpha_pixels( ctx, n, x, y, dest, mask );
+      _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask );
    }
 
    if (!ctx->Color.BlendFunc)