Initial work for supporting different renderbuffer color depths at runtime.
authorBrian Paul <brian.paul@tungstengraphics.com>
Mon, 25 Sep 2006 23:57:39 +0000 (23:57 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Mon, 25 Sep 2006 23:57:39 +0000 (23:57 +0000)
src/mesa/swrast/s_alpha.c
src/mesa/swrast/s_blend.c
src/mesa/swrast/s_context.c
src/mesa/swrast/s_context.h
src/mesa/swrast/s_fog.c
src/mesa/swrast/s_logic.c
src/mesa/swrast/s_masking.c
src/mesa/swrast/s_span.c
src/mesa/swrast/s_span.h
src/mesa/swrast/s_zoom.c

index 55c1e6a58f8621cfa55c4a76634c8798e48ffef2..8776e6128d5c3e155e87ef5212061145a2e4f0af 100644 (file)
@@ -1,9 +1,8 @@
-
 /*
  * Mesa 3-D graphics library
- * Version:  4.1
+ * Version:  6.5.2
  *
- * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 #include "s_context.h"
 
 
+#define ALPHA_TEST(ALPHA, LOOP_CODE)           \
+do {                                           \
+   switch (ctx->Color.AlphaFunc) {             \
+      case GL_LESS:                            \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA < ref);          \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_LEQUAL:                          \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA <= ref);         \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_GEQUAL:                          \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA >= ref);         \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_GREATER:                         \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA > ref);          \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_NOTEQUAL:                                \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA != ref);         \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_EQUAL:                           \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA == ref);         \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      default:                                 \
+         _mesa_problem(ctx, "Invalid alpha test in _swrast_alpha_test" ); \
+         return 0;                             \
+   }                                           \
+} while (0)
+
+
+
 /**
- * \fn GLint _swrast_alpha_test( const GLcontext *ctx, struct sw_span *span )
- * \brief Apply the alpha test to a span of pixels.
- * \return
- *      - "0" = all pixels in the span failed the alpha test.
- *      - "1" = one or more pixels passed the alpha test.
+ * Perform the alpha test for an array of pixels.
+ * For pixels that fail the test, mask[i] will be set to 0.
+ * \return  0 if all pixels in the span failed the alpha test,
+ *          1 if one or more pixels passed the alpha test.
  */
 GLint
-_swrast_alpha_test( const GLcontext *ctx, struct sw_span *span )
+_swrast_alpha_test(const GLcontext *ctx, struct sw_span *span)
 {
-   const GLchan (*rgba)[4] = (const GLchan (*)[4]) span->array->rgba;
-   GLchan ref;
    const GLuint n = span->end;
    GLubyte *mask = span->array->mask;
    GLuint i;
 
-   CLAMPED_FLOAT_TO_CHAN(ref, ctx->Color.AlphaRef);
+   if (ctx->Color.AlphaFunc == GL_ALWAYS) {
+      /* do nothing */
+      return 1;
+   }
+   else if (ctx->Color.AlphaFunc == GL_NEVER) {
+      /* All pixels failed - caller should check for this return value and
+       * act accordingly.
+       */
+      span->writeAll = GL_FALSE;
+      return 0;
+   }
 
    if (span->arrayMask & SPAN_RGBA) {
-      /* Use the array values */
-      switch (ctx->Color.AlphaFunc) {
-         case GL_LESS:
-            for (i = 0; i < n; i++)
-               mask[i] &= (rgba[i][ACOMP] < ref);
-            break;
-         case GL_LEQUAL:
-            for (i = 0; i < n; i++)
-               mask[i] &= (rgba[i][ACOMP] <= ref);
-            break;
-         case GL_GEQUAL:
-            for (i = 0; i < n; i++)
-               mask[i] &= (rgba[i][ACOMP] >= ref);
-            break;
-         case GL_GREATER:
-            for (i = 0; i < n; i++)
-               mask[i] &= (rgba[i][ACOMP] > ref);
-            break;
-         case GL_NOTEQUAL:
-            for (i = 0; i < n; i++)
-               mask[i] &= (rgba[i][ACOMP] != ref);
-            break;
-         case GL_EQUAL:
-            for (i = 0; i < n; i++)
-               mask[i] &= (rgba[i][ACOMP] == ref);
-            break;
-         case GL_ALWAYS:
-            /* do nothing */
-            return 1;
-         case GL_NEVER:
-            /* caller should check for zero! */
-            span->writeAll = GL_FALSE;
-            return 0;
-         default:
-            _mesa_problem( ctx, "Invalid alpha test in _swrast_alpha_test" );
-            return 0;
+      /* Use array's alpha values */
+      if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+         GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
+         GLubyte ref;
+         CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+         ALPHA_TEST(rgba[i][ACOMP], ;);
+      }
+      else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+         GLushort (*rgba)[4] = span->array->color.sz2.rgba;
+         GLushort ref;
+         CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
+         ALPHA_TEST(rgba[i][ACOMP], ;);
+      }
+      else {
+         GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
+         const GLfloat ref = ctx->Color.AlphaRef;
+         ALPHA_TEST(rgba[i][ACOMP], ;);
       }
    }
    else {
-      /* Use the interpolation values */
-#if CHAN_TYPE == GL_FLOAT
-      const GLfloat alphaStep = span->alphaStep;
-      GLfloat alpha = span->alpha;
+      /* Interpolate alpha values */
       ASSERT(span->interpMask & SPAN_RGBA);
-      switch (ctx->Color.AlphaFunc) {
-         case GL_LESS:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (alpha < ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_LEQUAL:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (alpha <= ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_GEQUAL:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (alpha >= ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_GREATER:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (alpha > ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_NOTEQUAL:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (alpha != ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_EQUAL:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (alpha == ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_ALWAYS:
-            /* do nothing */
-            return 1;
-         case GL_NEVER:
-            /* caller should check for zero! */
-            span->writeAll = GL_FALSE;
-            return 0;
-         default:
-            _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
-            return 0;
+      if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+         const GLfixed alphaStep = span->alphaStep;
+         GLfixed alpha = span->alpha;
+         GLubyte ref;
+         CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+         ALPHA_TEST(alpha, alpha += alphaStep);
       }
-#else
-      /* 8 or 16-bit channel interpolation */
-      const GLfixed alphaStep = span->alphaStep;
-      GLfixed alpha = span->alpha;
-      ASSERT(span->interpMask & SPAN_RGBA);
-      switch (ctx->Color.AlphaFunc) {
-         case GL_LESS:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (FixedToChan(alpha) < ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_LEQUAL:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (FixedToChan(alpha) <= ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_GEQUAL:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (FixedToChan(alpha) >= ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_GREATER:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (FixedToChan(alpha) > ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_NOTEQUAL:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (FixedToChan(alpha) != ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_EQUAL:
-            for (i = 0; i < n; i++) {
-               mask[i] &= (FixedToChan(alpha) == ref);
-               alpha += alphaStep;
-            }
-            break;
-         case GL_ALWAYS:
-            /* do nothing */
-            return 1;
-         case GL_NEVER:
-            /* caller should check for zero! */
-            span->writeAll = GL_FALSE;
-            return 0;
-         default:
-            _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
-            return 0;
+      else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+         const GLfixed alphaStep = span->alphaStep;
+         GLfixed alpha = span->alpha;
+         GLushort ref;
+         CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
+         ALPHA_TEST(alpha, alpha += alphaStep);
+      }
+      else {
+         const GLfloat alphaStep = span->alphaStep;
+         GLfloat alpha = span->alpha;
+         const GLfloat ref = ctx->Color.AlphaRef;
+         ALPHA_TEST(alpha, alpha += alphaStep);
       }
-#endif /* CHAN_TYPE */
    }
 
-#if 0
-   /* XXXX This causes conformance failures!!!! */
-   while ((span->start <= span->end)  &&
-          (mask[span->start] == 0))
-     span->start ++;
-
-   while ((span->end >= span->start)  &&
-          (mask[span->end] == 0))
-     span->end --;
-#endif
-
    span->writeAll = GL_FALSE;
 
-   if (span->start >= span->end)
-     return 0;
-   else
-     return 1;
+   /* XXX examine mask[] values? */
+   return 1;
 }
index 91ec513d5bc9c51cc7837230c65fdd08ea1d45da..4e6c3d909f44521d9e9d87abd499a158bcce1a51 100644 (file)
 #endif
 
 
-/*
+/**
  * Special case for glBlendFunc(GL_ZERO, GL_ONE)
  */
 static void _BLENDAPI
-blend_noopGLcontext *ctx, GLuint n, const GLubyte mask[],
-            GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_noop_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+                 GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
 {
    GLuint i;
-   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);
+   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;
 
    for (i = 0; i < n; i++) {
@@ -73,17 +73,17 @@ blend_noop( GLcontext *ctx, GLuint n, const GLubyte mask[],
 }
 
 
-/*
+/**
  * Special case for glBlendFunc(GL_ONE, GL_ZERO)
  */
 static void _BLENDAPI
-blend_replace( GLcontext *ctx, GLuint n, const GLubyte mask[],
-               GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_replace(GLcontext *ctx, GLuint n, const GLubyte mask[],
+              GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
 {
-   ASSERT(ctx->Color.BlendEquationRGB==GL_FUNC_ADD);
-   ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
-   ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
-   ASSERT(ctx->Color.BlendDstRGB==GL_ZERO);
+   ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendSrcRGB == GL_ONE);
+   ASSERT(ctx->Color.BlendDstRGB == GL_ZERO);
    (void) ctx;
    (void) n;
    (void) mask;
@@ -92,18 +92,21 @@ blend_replace( GLcontext *ctx, GLuint n, const GLubyte mask[],
 }
 
 
-/*
+/**
  * Common transparency blending mode.
  */
 static void _BLENDAPI
-blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
-                    GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_transparency_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+                         GLchan rgba[][4], CONST GLchan dest[][4],
+                         GLenum chanType)
 {
    GLuint i;
-   ASSERT(ctx->Color.BlendEquationRGB==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);
+   ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendSrcRGB == GL_SRC_ALPHA);
+   ASSERT(ctx->Color.BlendSrcA == GL_SRC_ALPHA);
+   ASSERT(ctx->Color.BlendDstRGB == GL_ONE_MINUS_SRC_ALPHA);
+   ASSERT(ctx->Color.BlendDstA == GL_ONE_MINUS_SRC_ALPHA);
    (void) ctx;
 
    for (i=0;i<n;i++) {
@@ -180,18 +183,18 @@ blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
 
 
 
-/*
+/**
  * Add src and dest.
  */
 static void _BLENDAPI
-blend_addGLcontext *ctx, GLuint n, const GLubyte mask[],
-           GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_add_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+                GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
 {
    GLuint i;
-   ASSERT(ctx->Color.BlendEquationRGB==GL_FUNC_ADD);
-   ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
-   ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
-   ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
+   ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+   ASSERT(ctx->Color.BlendSrcRGB == GL_ONE);
+   ASSERT(ctx->Color.BlendDstRGB == GL_ONE);
    (void) ctx;
 
    for (i=0;i<n;i++) {
@@ -219,16 +222,16 @@ blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
 
 
 
-/*
+/**
  * Blend min function  (for GL_EXT_blend_minmax)
  */
 static void _BLENDAPI
-blend_minGLcontext *ctx, GLuint n, const GLubyte mask[],
-           GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_min_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+                GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
 {
    GLuint i;
-   ASSERT(ctx->Color.BlendEquationRGB==GL_MIN);
-   ASSERT(ctx->Color.BlendEquationA==GL_MIN);
+   ASSERT(ctx->Color.BlendEquationRGB == GL_MIN);
+   ASSERT(ctx->Color.BlendEquationA == GL_MIN);
    (void) ctx;
 
    for (i=0;i<n;i++) {
@@ -248,16 +251,16 @@ blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
 
 
 
-/*
+/**
  * Blend max function  (for GL_EXT_blend_minmax)
  */
 static void _BLENDAPI
-blend_maxGLcontext *ctx, GLuint n, const GLubyte mask[],
-           GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_max_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+                GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
 {
    GLuint i;
-   ASSERT(ctx->Color.BlendEquationRGB==GL_MAX);
-   ASSERT(ctx->Color.BlendEquationA==GL_MAX);
+   ASSERT(ctx->Color.BlendEquationRGB == GL_MAX);
+   ASSERT(ctx->Color.BlendEquationA == GL_MAX);
    (void) ctx;
 
    for (i=0;i<n;i++) {
@@ -277,12 +280,12 @@ blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
 
 
 
-/*
+/**
  * Modulate:  result = src * dest
  */
 static void _BLENDAPI
-blend_modulateGLcontext *ctx, GLuint n, const GLubyte mask[],
-                GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_modulate_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+                     GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
 {
    GLuint i;
    (void) ctx;
@@ -318,17 +321,435 @@ blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
 }
 
 
-
-/*
- * General case blend pixels.
- * Input:  n - number of pixels
- *         mask - the usual write mask
- * In/Out:  rgba - the incoming and modified pixels
- * Input:  dest - the pixels from the dest color buffer
+#if 0
+/**
+ * Do any blending operation, using floating point.
+ * \param n  number of pixels
+ * \param mask  fragment writemask array
+ * \param src  array of incoming (and modified) pixels
+ * \param dst  array of pixels from the dest color buffer
  */
+static void
+blend_general_float(GLcontext *ctx, GLuint n, const GLubyte mask[],
+                    GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+   GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+   const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+   GLuint i;
+
+   for (i = 0; i < n; i++) {
+      if (mask[i]) {
+         /* Incoming/source Color */
+         const GLfloat Rs = rgba[i][RCOMP];
+         const GLfloat Gs = rgba[i][GCOMP];
+         const GLfloat Bs = rgba[i][BCOMP];
+         const GLfloat As = rgba[i][ACOMP];
+
+         /* Frame buffer/dest color */
+         const GLfloat Rd = dest[i][RCOMP];
+         const GLfloat Gd = dest[i][GCOMP];
+         const GLfloat Bd = dest[i][BCOMP];
+         const GLfloat Ad = dest[i][ACOMP];
+
+         GLfloat sR, sG, sB, sA;  /* Source factor */
+         GLfloat dR, dG, dB, dA;  /* Dest factor */
+         GLfloat r, g, b, a;      /* result color */
+
+         /* XXX for the case of constant blend terms we could init
+          * the sX and dX variables just once before the loop.
+          */
+
+         /* Source RGB factor */
+         switch (ctx->Color.BlendSrcRGB) {
+            case GL_ZERO:
+               sR = sG = sB = 0.0F;
+               break;
+            case GL_ONE:
+               sR = sG = sB = 1.0F;
+               break;
+            case GL_DST_COLOR:
+               sR = Rd;
+               sG = Gd;
+               sB = Bd;
+               break;
+            case GL_ONE_MINUS_DST_COLOR:
+               sR = 1.0F - Rd;
+               sG = 1.0F - Gd;
+               sB = 1.0F - Bd;
+               break;
+            case GL_SRC_ALPHA:
+               sR = sG = sB = As;
+               break;
+            case GL_ONE_MINUS_SRC_ALPHA:
+               sR = sG = sB = 1.0F - As;
+               break;
+            case GL_DST_ALPHA:
+               sR = sG = sB = Ad;
+               break;
+            case GL_ONE_MINUS_DST_ALPHA:
+               sR = sG = sB = 1.0F - Ad;
+               break;
+            case GL_SRC_ALPHA_SATURATE:
+               if (As < 1.0F - Ad) {
+                  sR = sG = sB = As;
+               }
+               else {
+                  sR = sG = sB = 1.0F - Ad;
+               }
+               break;
+            case GL_CONSTANT_COLOR:
+               sR = ctx->Color.BlendColor[0];
+               sG = ctx->Color.BlendColor[1];
+               sB = ctx->Color.BlendColor[2];
+               break;
+            case GL_ONE_MINUS_CONSTANT_COLOR:
+               sR = 1.0F - ctx->Color.BlendColor[0];
+               sG = 1.0F - ctx->Color.BlendColor[1];
+               sB = 1.0F - ctx->Color.BlendColor[2];
+               break;
+            case GL_CONSTANT_ALPHA:
+               sR = sG = sB = ctx->Color.BlendColor[3];
+               break;
+            case GL_ONE_MINUS_CONSTANT_ALPHA:
+               sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
+               break;
+            case GL_SRC_COLOR: /* GL_NV_blend_square */
+               sR = Rs;
+               sG = Gs;
+               sB = Bs;
+               break;
+            case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
+               sR = 1.0F - Rs;
+               sG = 1.0F - Gs;
+               sB = 1.0F - Bs;
+               break;
+            default:
+               /* this should never happen */
+               _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float");
+               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: /* GL_NV_blend_square */
+               sA = As;
+               break;
+            case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
+               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:
+               dR = dG = dB = 0.0F;
+               break;
+            case GL_ONE:
+               dR = dG = dB = 1.0F;
+               break;
+            case GL_SRC_COLOR:
+               dR = Rs;
+               dG = Gs;
+               dB = Bs;
+               break;
+            case GL_ONE_MINUS_SRC_COLOR:
+               dR = 1.0F - Rs;
+               dG = 1.0F - Gs;
+               dB = 1.0F - Bs;
+               break;
+            case GL_SRC_ALPHA:
+               dR = dG = dB = As;
+               break;
+            case GL_ONE_MINUS_SRC_ALPHA:
+               dR = dG = dB = 1.0F - As;
+               break;
+            case GL_DST_ALPHA:
+               dR = dG = dB = Ad;
+               break;
+            case GL_ONE_MINUS_DST_ALPHA:
+               dR = dG = dB = 1.0F - Ad;
+               break;
+            case GL_CONSTANT_COLOR:
+               dR = ctx->Color.BlendColor[0];
+               dG = ctx->Color.BlendColor[1];
+               dB = ctx->Color.BlendColor[2];
+               break;
+            case GL_ONE_MINUS_CONSTANT_COLOR:
+               dR = 1.0F - ctx->Color.BlendColor[0];
+               dG = 1.0F - ctx->Color.BlendColor[1];
+               dB = 1.0F - ctx->Color.BlendColor[2];
+               break;
+            case GL_CONSTANT_ALPHA:
+               dR = dG = dB = ctx->Color.BlendColor[3];
+               break;
+            case GL_ONE_MINUS_CONSTANT_ALPHA:
+               dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
+               break;
+            case GL_DST_COLOR: /* GL_NV_blend_square */
+               dR = Rd;
+               dG = Gd;
+               dB = Bd;
+               break;
+            case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
+               dR = 1.0F - Rd;
+               dG = 1.0F - Gd;
+               dB = 1.0F - Bd;
+               break;
+            default:
+               /* this should never happen */
+               dR = dG = dB = 0.0F;
+               _mesa_problem(ctx, "Bad blend dest RGB 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: /* GL_NV_blend_square */
+               dA = Ad;
+               break;
+            case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
+               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 );
+           g = MIN2( Gd, Gs );
+           b = MIN2( Bd, Bs );
+            break;
+         case GL_MAX:
+           r = MAX2( Rd, Rs );
+           g = MAX2( Gd, Gs );
+           b = MAX2( Bd, Bs );
+            break;
+        default:
+            /* should never get here */
+            r = g = b = 0.0F;  /* silence uninitialized var warning */
+            _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+            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, CHAN_MAXF );
+#else
+         ASSIGN_4V(rgba[i], r, g, b, a);
+#endif
+      }
+   }
+}
+#endif
+
+
+#if 0 /* not ready yet */
+static void
+blend_general2(GLcontext *ctx, GLuint n, const GLubyte mask[],
+               void *src, const void *dst, GLenum chanType)
+{
+   GLfloat rgbaF[MAX_WIDTH][4], destF[MAX_WIDTH][4];
+
+   if (chanType == GL_UNSIGNED_BYTE) {
+      GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+      const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+      GLuint i;
+      /* convert ubytes to floats */
+      for (i = 0; i < n; i++) {
+         if (mask[i]) {
+            rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]);
+            rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]);
+            rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]);
+            rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]);
+            destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]);
+            destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]);
+            destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]);
+            destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]);
+         }
+      }
+      /* do blend */
+      blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
+      /* convert back to ubytes */
+      for (i = 0; i < n; i++) {
+         if (mask[i]) {
+            UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][RCOMP], rgbaF[i][RCOMP]);
+            UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][GCOMP], rgbaF[i][GCOMP]);
+            UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][BCOMP], rgbaF[i][BCOMP]);
+            UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][ACOMP], rgbaF[i][ACOMP]);
+         }
+      }
+   }
+   else if (chanType == GL_UNSIGNED_SHORT) {
+      GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+      const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+      GLuint i;
+      /* convert ushorts to floats */
+      for (i = 0; i < n; i++) {
+         if (mask[i]) {
+            rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]);
+            rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]);
+            rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]);
+            rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]);
+            destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]);
+            destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]);
+            destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]);
+            destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]);
+         }
+      }
+      /* do blend */
+      blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
+      /* convert back to ushorts */
+      for (i = 0; i < n; i++) {
+         if (mask[i]) {
+            UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]);
+            UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]);
+            UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]);
+            UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]);
+         }
+      }
+   }
+   else {
+      blend_general_float(ctx, n, mask, (GLfloat (*)[4]) rgbaF,
+                          (const GLfloat (*)[4]) destF, chanType);
+   }
+}
+#endif
+
+
 static void _BLENDAPI
-blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
-               GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_general(GLcontext *ctx, GLuint n, const GLubyte mask[],
+              GLchan rgba[][4], CONST GLchan dest[][4],
+              GLenum chanType)
 {
    const GLfloat rscale = 1.0F / CHAN_MAXF;
    const GLfloat gscale = 1.0F / CHAN_MAXF;
@@ -441,7 +862,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
                break;
             default:
                /* this should never happen */
-               _mesa_problem(ctx, "Bad blend source RGB factor in do_blend");
+               _mesa_problem(ctx, "Bad blend source RGB factor in blend_general");
                return;
          }
 
@@ -466,7 +887,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
                sA = 1.0F - (GLfloat) As * ascale;
                break;
             case GL_DST_ALPHA:
-               sA =(GLfloat) Ad * ascale;
+               sA = (GLfloat) Ad * ascale;
                break;
             case GL_ONE_MINUS_DST_ALPHA:
                sA = 1.0F - (GLfloat) Ad * ascale;
@@ -495,7 +916,8 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
             default:
                /* this should never happen */
                sA = 0.0F;
-               _mesa_problem(ctx, "Bad blend source A factor in do_blend");
+               _mesa_problem(ctx, "Bad blend source A factor in blend_general");
+               return;
          }
 
          /* Dest RGB factor */
@@ -557,7 +979,8 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
             default:
                /* this should never happen */
                dR = dG = dB = 0.0F;
-               _mesa_problem(ctx, "Bad blend dest RGB factor in do_blend");
+               _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general");
+               return;
          }
 
          /* Dest Alpha factor */
@@ -607,7 +1030,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
             default:
                /* this should never happen */
                dA = 0.0F;
-               _mesa_problem(ctx, "Bad blend dest A factor in do_blend");
+               _mesa_problem(ctx, "Bad blend dest A factor in blend_general");
                return;
          }
 
@@ -633,59 +1056,63 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
 
          /* compute blended color */
 #if CHAN_TYPE == GL_FLOAT
-         if (ctx->Color.BlendEquationRGB==GL_FUNC_ADD) {
+         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;
-         }
-         else if (ctx->Color.BlendEquationRGB==GL_FUNC_SUBTRACT) {
+            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;
-         }
-         else if (ctx->Color.BlendEquationRGB==GL_FUNC_REVERSE_SUBTRACT) {
+            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;
-         }
-         else if (ctx->Color.BlendEquationRGB==GL_MIN) {
+            break;
+         case GL_MIN:
            r = MIN2( Rd, Rs );
            g = MIN2( Gd, Gs );
            b = MIN2( Bd, Bs );
-        }
-         else if (ctx->Color.BlendEquationRGB==GL_MAX) {
+            break;
+         case GL_MAX:
            r = MAX2( Rd, Rs );
            g = MAX2( Gd, Gs );
            b = MAX2( Bd, Bs );
-        }
-         else {
+            break;
+         default:
             /* should never get here */
             r = g = b = 0.0F;  /* silence uninitialized var warning */
             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+            return;
          }
 
-         if (ctx->Color.BlendEquationA==GL_FUNC_ADD) {
+         switch (ctx->Color.BlendEquationA) {
+         case GL_FUNC_ADD:
             a = As * sA + Ad * dA;
-         }
-         else if (ctx->Color.BlendEquationA==GL_FUNC_SUBTRACT) {
+            break;
+         case GL_FUNC_SUBTRACT:
             a = As * sA - Ad * dA;
-         }
-         else if (ctx->Color.BlendEquationA==GL_FUNC_REVERSE_SUBTRACT) {
+            break;
+         case GL_FUNC_REVERSE_SUBTRACT:
             a = Ad * dA - As * sA;
-         }
-         else if (ctx->Color.BlendEquationA==GL_MIN) {
+            break;
+         case GL_MIN:
            a = MIN2( Ad, As );
-        }
-         else if (ctx->Color.BlendEquationA==GL_MAX) {
+            break;
+         case GL_MAX:
            a = MAX2( Ad, As );
-        }
-         else {
+            break;
+         default:
             /* should never get here */
             a = 0.0F;  /* silence uninitialized var warning */
             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+            return;
          }
 
          /* final clamping */
@@ -694,56 +1121,60 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
          rgba[i][BCOMP] = MAX2( b, 0.0F );
          rgba[i][ACOMP] = CLAMP( a, 0.0F, CHAN_MAXF );
 #else
-         if (ctx->Color.BlendEquationRGB==GL_FUNC_ADD) {
+         switch (ctx->Color.BlendEquationRGB) {
+         case GL_FUNC_ADD:
             r = Rs * sR + Rd * dR + 0.5F;
             g = Gs * sG + Gd * dG + 0.5F;
             b = Bs * sB + Bd * dB + 0.5F;
-         }
-         else if (ctx->Color.BlendEquationRGB==GL_FUNC_SUBTRACT) {
+            break;
+         case GL_FUNC_SUBTRACT:
             r = Rs * sR - Rd * dR + 0.5F;
             g = Gs * sG - Gd * dG + 0.5F;
             b = Bs * sB - Bd * dB + 0.5F;
-         }
-         else if (ctx->Color.BlendEquationRGB==GL_FUNC_REVERSE_SUBTRACT) {
+            break;
+         case 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;
-         }
-         else if (ctx->Color.BlendEquationRGB==GL_MIN) {
+            break;
+         case GL_MIN:
            r = MIN2( Rd, Rs );
            g = MIN2( Gd, Gs );
            b = MIN2( Bd, Bs );
-        }
-         else if (ctx->Color.BlendEquationRGB==GL_MAX) {
+            break;
+         case GL_MAX:
            r = MAX2( Rd, Rs );
            g = MAX2( Gd, Gs );
            b = MAX2( Bd, Bs );
-        }
-         else {
+            break;
+         default:
             /* should never get here */
             r = g = b = 0.0F;  /* silence uninitialized var warning */
             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+            return;
          }
 
-         if (ctx->Color.BlendEquationA==GL_FUNC_ADD) {
+         switch (ctx->Color.BlendEquationA) {
+         case GL_FUNC_ADD:
             a = As * sA + Ad * dA + 0.5F;
-         }
-         else if (ctx->Color.BlendEquationA==GL_FUNC_SUBTRACT) {
+            break;
+         case GL_FUNC_SUBTRACT:
             a = As * sA - Ad * dA + 0.5F;
-         }
-         else if (ctx->Color.BlendEquationA==GL_FUNC_REVERSE_SUBTRACT) {
+            break;
+         case GL_FUNC_REVERSE_SUBTRACT:
             a = Ad * dA - As * sA + 0.5F;
-         }
-         else if (ctx->Color.BlendEquationA==GL_MIN) {
+            break;
+         case GL_MIN:
            a = MIN2( Ad, As );
-        }
-         else if (ctx->Color.BlendEquationA==GL_MAX) {
+            break;
+         case GL_MAX:
            a = MAX2( Ad, As );
-        }
-         else {
+            break;
+         default:
             /* should never get here */
             a = 0.0F;  /* silence uninitialized var warning */
             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+            return;
          }
 
          /* final clamping */
@@ -757,12 +1188,13 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
 }
 
 
-/*
+/**
  * Analyze current blending parameters to pick fastest blending function.
  * Result: the ctx->Color.BlendFunc pointer is updated.
  */
 void _swrast_choose_blend_func( GLcontext *ctx )
 {
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const GLenum eq = ctx->Color.BlendEquationRGB;
    const GLenum srcRGB = ctx->Color.BlendSrcRGB;
    const GLenum dstRGB = ctx->Color.BlendDstRGB;
@@ -770,77 +1202,77 @@ void _swrast_choose_blend_func( GLcontext *ctx )
    const GLenum dstA = ctx->Color.BlendDstA;
 
    if (ctx->Color.BlendEquationRGB != ctx->Color.BlendEquationA) {
-      SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
+      swrast->BlendFunc = blend_general;
    }
-   else if (eq==GL_MIN) {
+   else if (eq == GL_MIN) {
       /* Note: GL_MIN ignores the blending weight factors */
 #if defined(USE_MMX_ASM)
       if ( cpu_has_mmx ) {
-         SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_min;
+         swrast->BlendFunc = _mesa_mmx_blend_min;
       }
       else
 #endif
-         SWRAST_CONTEXT(ctx)->BlendFunc = blend_min;
+         swrast->BlendFunc = blend_min_ubyte;
    }
-   else if (eq==GL_MAX) {
+   else if (eq == GL_MAX) {
       /* Note: GL_MAX ignores the blending weight factors */
 #if defined(USE_MMX_ASM)
       if ( cpu_has_mmx ) {
-         SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_max;
+         swrast->BlendFunc = _mesa_mmx_blend_max;
       }
       else
 #endif
-         SWRAST_CONTEXT(ctx)->BlendFunc = blend_max;
+         swrast->BlendFunc = blend_max_ubyte;
    }
    else if (srcRGB != srcA || dstRGB != dstA) {
-      SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
+      swrast->BlendFunc = blend_general;
    }
-   else if (eq==GL_FUNC_ADD && srcRGB==GL_SRC_ALPHA
-            && dstRGB==GL_ONE_MINUS_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 ) {
-         SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_transparency;
+         swrast->BlendFunc = _mesa_mmx_blend_transparency;
       }
       else
 #endif
-        SWRAST_CONTEXT(ctx)->BlendFunc = blend_transparency;
+        swrast->BlendFunc = blend_transparency_ubyte;
    }
-   else if (eq==GL_FUNC_ADD && 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;
+         swrast->BlendFunc = _mesa_mmx_blend_add;
       }
       else
 #endif
-         SWRAST_CONTEXT(ctx)->BlendFunc = blend_add;
+         swrast->BlendFunc = blend_add_ubyte;
    }
-   else if (((eq==GL_FUNC_ADD || eq==GL_FUNC_REVERSE_SUBTRACT)
-            && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
+   else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT)
+            && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR))
            ||
-           ((eq==GL_FUNC_ADD || eq==GL_FUNC_SUBTRACT)
-            && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
+           ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT)
+            && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) {
 #if defined(USE_MMX_ASM)
       if ( cpu_has_mmx ) {
-         SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_modulate;
+         swrast->BlendFunc = _mesa_mmx_blend_modulate;
       }
       else
 #endif
-         SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate;
+         swrast->BlendFunc = blend_modulate_ubyte;
    }
-   else if (eq==GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
-      SWRAST_CONTEXT(ctx)->BlendFunc = blend_noop;
+   else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
+      swrast->BlendFunc = blend_noop_ubyte;
    }
-   else if (eq==GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
-      SWRAST_CONTEXT(ctx)->BlendFunc = blend_replace;
+   else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
+      swrast->BlendFunc = blend_replace;
    }
    else {
-      SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
+      swrast->BlendFunc = blend_general;
    }
 }
 
 
 
-/*
+/**
  * Apply the blending operator to a span of pixels.
  * We can handle horizontal runs of pixels (spans) or arrays of x/y
  * pixel coordinates.
@@ -849,25 +1281,17 @@ void
 _swrast_blend_span(GLcontext *ctx, struct gl_renderbuffer *rb,
                    struct sw_span *span)
 {
-   GLchan framebuffer[MAX_WIDTH][4];
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+   void *rbPixels;
 
    ASSERT(span->end <= MAX_WIDTH);
    ASSERT(span->arrayMask & SPAN_RGBA);
+   ASSERT(rb->DataType == span->array->ChanType);
    ASSERT(!ctx->Color._LogicOpEnabled);
 
-   /* Read span of current frame buffer pixels */
-   if (span->arrayMask & SPAN_XY) {
-      /* array of x/y pixel coords */
-      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
-                         framebuffer, 4 * sizeof(GLchan));
-   }
-   else {
-      /* horizontal run of pixels */
-      _swrast_read_rgba_span(ctx, rb, span->end, span->x, span->y,
-                             framebuffer);
-   }
+   rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
 
-   SWRAST_CONTEXT(ctx)->BlendFunc( ctx, span->end, span->array->mask,
-                                   span->array->rgba,
-                                  (const GLchan (*)[4]) framebuffer );
+   swrast->BlendFunc(ctx, span->end, span->array->mask,
+                     span->array->rgba, (const GLchan (*)[4]) rbPixels,
+                     span->array->ChanType);
 }
index 030313aea60c2ae0d10c3ecbc759df99f4a088d7..bb096be75a1a188cabe2572298339d1696a47444 100644 (file)
@@ -199,11 +199,6 @@ _swrast_update_fog_state( GLcontext *ctx )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
-   /* convert fog color to GLchan values */
-   CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[RCOMP], ctx->Fog.Color[RCOMP]);
-   CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[GCOMP], ctx->Fog.Color[GCOMP]);
-   CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[BCOMP], ctx->Fog.Color[BCOMP]);
-
    /* determine if fog is needed, and if so, which fog mode */
    swrast->_FogEnabled = GL_FALSE;
    if (ctx->FragmentProgram._Enabled) {
@@ -359,17 +354,16 @@ _swrast_validate_point( GLcontext *ctx, const SWvertex *v0 )
  * function, then call it.
  */
 static void _ASMAPI
-_swrast_validate_blend_func( GLcontext *ctx, GLuint n,
-                            const GLubyte mask[],
-                            GLchan src[][4],
-                            CONST GLchan dst[][4] )
+_swrast_validate_blend_func(GLcontext *ctx, GLuint n, const GLubyte mask[],
+                            GLchan src[][4], CONST GLchan dst[][4],
+                            GLenum chanType )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
    _swrast_validate_derived( ctx );
    _swrast_choose_blend_func( ctx );
 
-   swrast->BlendFunc( ctx, n, mask, src, dst );
+   swrast->BlendFunc( ctx, n, mask, src, dst, chanType );
 }
 
 
@@ -680,6 +674,17 @@ _swrast_CreateContext( GLcontext *ctx )
       FREE(swrast);
       return GL_FALSE;
    }
+   swrast->SpanArrays->ChanType = CHAN_TYPE;
+#if CHAN_TYPE == GL_UNSIGNED_BYTE
+   swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz1.rgba;
+   swrast->SpanArrays->spec = swrast->SpanArrays->color.sz1.spec;
+#elif CHAN_TYPE == GL_UNSIGNED_SHORT
+   swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz2.rgba;
+   swrast->SpanArrays->spec = swrast->SpanArrays->color.sz2.spec;
+#else
+   swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz4.rgba;
+   swrast->SpanArrays->spec = swrast->SpanArrays->color.sz4.spec;
+#endif
 
    /* init point span buffer */
    swrast->PointSpan.primitive = GL_POINT;
index 76f08b007ea9749ab587ae9c4eed26c1f2f74e8d..0f3df3b48a45b681e288a6e106bf7fbb1cb98d1c 100644 (file)
 #define SPAN_VARYING     0x2000
 /*@}*/
 
+#if 0
+/* alternate arrangement for code below */
+struct arrays2 {
+   union {
+      GLubyte  sz1[MAX_WIDTH][4]; /* primary color */
+      GLushort sz2[MAX_WIDTH][4];
+      GLfloat  sz4[MAX_WIDTH][4];
+   } rgba;
+   union {
+      GLubyte  sz1[MAX_WIDTH][4]; /* specular color and temp storage */
+      GLushort sz2[MAX_WIDTH][4];
+      GLfloat  sz4[MAX_WIDTH][4];
+   } spec;
+};
+#endif
+
 
 /**
  * \struct span_arrays 
  * These arrays are separated out of sw_span to conserve memory.
  */
 struct span_arrays {
-   GLchan  rgba[MAX_WIDTH][4];
-   GLchan  spec[MAX_WIDTH][4]; /* specular color */
+   GLenum ChanType; /**< Color channel type, GL_UNSIGNED_BYTE, GL_FLOAT */
+   union {
+      struct {
+         GLubyte rgba[MAX_WIDTH][4]; /**< primary color */
+         GLubyte spec[MAX_WIDTH][4]; /**< specular color and temp storage */
+      } sz1;
+      struct {
+         GLushort rgba[MAX_WIDTH][4];
+         GLushort spec[MAX_WIDTH][4];
+      } sz2;
+      struct {
+         GLfloat rgba[MAX_WIDTH][4];
+         GLfloat spec[MAX_WIDTH][4];
+      } sz4;
+   } color;
+   /** XXX these are temporary fields, pointing into above color arrays */
+   GLchan (*rgba)[4];
+   GLchan (*spec)[4];
+
    GLuint  index[MAX_WIDTH];
    GLint   x[MAX_WIDTH];  /**< X/Y used for point/line rendering only */
    GLint   y[MAX_WIDTH];  /**< X/Y used for point/line rendering only */
@@ -218,7 +251,8 @@ typedef void (*texture_sample_func)(GLcontext *ctx,
 
 typedef void (_ASMAPIP blend_func)( GLcontext *ctx, GLuint n,
                                     const GLubyte mask[],
-                                    GLchan src[][4], CONST GLchan dst[][4] );
+                                    GLchan src[][4], CONST GLchan dst[][4],
+                                    GLenum chanType);
 
 typedef void (*swrast_point_func)( GLcontext *ctx, const SWvertex *);
 
@@ -291,7 +325,6 @@ typedef struct
    GLfloat _BackfaceSign;
    GLboolean _PreferPixelFog;    /* Compute fog blend factor per fragment? */
    GLboolean _AnyTextureCombine;
-   GLchan _FogColor[3];
    GLboolean _FogEnabled;
    GLenum _FogMode;  /* either GL_FOG_MODE or fragment program's fog mode */
 
index e3d6274b3fe4db550b67bb864f93bc74935ddf00..daa74ca0ca41d956c0e10689bbcec04dc200c28f 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5.2
  *
- * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 
 #include "s_context.h"
 #include "s_fog.h"
-#include "s_span.h"
+
+
+/** XXX temporary */
+#define UBYTE_RGBA  GLubyte (*rgba)[4] = span->array->color.sz1.rgba
+#define USHORT_RGBA  GLushort (*rgba)[4] = span->array->color.sz2.rgba
+#define FLOAT_RGBA  GLfloat (*rgba)[4] = span->array->color.sz4.rgba
+
 
 
 /**
@@ -66,6 +72,33 @@ _swrast_z_to_fogfactor(GLcontext *ctx, GLfloat z)
 }
 
 
+/**
+ * Template code for computing fog blend factor and applying it to colors.
+ * \param TYPE  either GLubyte, GLushort or GLfloat.
+ * \param COMPUTE_F  code to compute the fog blend factor, f.
+ */
+#define FOG_LOOP(TYPE, COMPUTE_F)                                      \
+do {                                                                   \
+   const GLfloat fogStep = span->fogStep;                              \
+   GLfloat fogCoord = span->fog;                                       \
+   const GLfloat wStep = haveW ? span->dwdx : 0.0F;                    \
+   GLfloat w = haveW ? span->w : 1.0F;                                 \
+   GLuint i;                                                           \
+   for (i = 0; i < span->end; i++) {                                   \
+      GLfloat f, oneMinusF;                                            \
+      COMPUTE_F;                                                       \
+      f = CLAMP(f, 0.0F, 1.0F);                                                \
+      oneMinusF = 1.0F - f;                                            \
+      rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \
+      rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \
+      rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \
+      fogCoord += fogStep;                                             \
+      w += wStep;                                                      \
+   }                                                                   \
+} while (0)
+
+
+
 /**
  * Apply fog to a span of RGBA pixels.
  * The fog value are either in the span->array->fog array or interpolated from
@@ -77,11 +110,10 @@ void
 _swrast_fog_rgba_span( const GLcontext *ctx, struct sw_span *span )
 {
    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   const GLchan rFog = swrast->_FogColor[RCOMP];
-   const GLchan gFog = swrast->_FogColor[GCOMP];
-   const GLchan bFog = swrast->_FogColor[BCOMP];
+   const GLfloat rFog = ctx->Fog.Color[RCOMP] * CHAN_MAX;
+   const GLfloat gFog = ctx->Fog.Color[GCOMP] * CHAN_MAX;
+   const GLfloat bFog = ctx->Fog.Color[BCOMP] * CHAN_MAX;
    const GLuint haveW = (span->interpMask & SPAN_W);
-   GLchan (*rgba)[4] = (GLchan (*)[4]) span->array->rgba;
 
    ASSERT(swrast->_FogEnabled);
    ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
@@ -96,79 +128,71 @@ _swrast_fog_rgba_span( const GLcontext *ctx, struct sw_span *span )
       /* The span's fog values are fog coordinates, now compute blend factors
        * and blend the fragment colors with the fog color.
        */
+      const GLfloat fogEnd = ctx->Fog.End;
+      const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End)
+         ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+      const GLfloat density = -ctx->Fog.Density;
+      const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
+
       switch (swrast->_FogMode) {
       case GL_LINEAR:
-         {
-            const GLfloat fogEnd = ctx->Fog.End;
-            const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End)
-               ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start);
-            const GLfloat fogStep = span->fogStep;
-            GLfloat fogCoord = span->fog;
-            const GLfloat wStep = haveW ? span->dwdx : 0.0F;
-            GLfloat w = haveW ? span->w : 1.0F;
-            GLuint i;
-            for (i = 0; i < span->end; i++) {
-               GLfloat f, oneMinusF;
-               f = (fogEnd - FABSF(fogCoord) / w) * fogScale;
-               f = CLAMP(f, 0.0F, 1.0F);
-               oneMinusF = 1.0F - f;
-               rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog);
-               rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog);
-               rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog);
-               fogCoord += fogStep;
-               w += wStep;
-            }
+#define COMPUTE_F  f = (fogEnd - FABSF(fogCoord) / w) * fogScale;
+         if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+            UBYTE_RGBA;
+            FOG_LOOP(GLubyte, COMPUTE_F);
+         }
+         else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+            USHORT_RGBA;
+            FOG_LOOP(GLushort, COMPUTE_F);
          }
+         else {
+            FLOAT_RGBA;
+            ASSERT(span->array->ChanType == GL_FLOAT);
+            FOG_LOOP(GLfloat, COMPUTE_F);
+         }
+#undef COMPUTE_F
          break;
+
       case GL_EXP:
-         {
-            const GLfloat density = -ctx->Fog.Density;
-            const GLfloat fogStep = span->fogStep;
-            GLfloat fogCoord = span->fog;
-            const GLfloat wStep = haveW ? span->dwdx : 0.0F;
-            GLfloat w = haveW ? span->w : 1.0F;
-            GLuint i;
-            for (i = 0; i < span->end; i++) {
-               GLfloat f, oneMinusF;
-               f = EXPF(density * FABSF(fogCoord) / w);
-               f = CLAMP(f, 0.0F, 1.0F);
-               oneMinusF = 1.0F - f;
-               rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog);
-               rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog);
-               rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog);
-               fogCoord += fogStep;
-               w += wStep;
-            }
+#define COMPUTE_F  f = EXPF(density * FABSF(fogCoord) / w);
+         if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+            UBYTE_RGBA;
+            FOG_LOOP(GLubyte, COMPUTE_F);
+         }
+         else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+            USHORT_RGBA;
+            FOG_LOOP(GLushort, COMPUTE_F);
+         }
+         else {
+            FLOAT_RGBA;
+            ASSERT(span->array->ChanType == GL_FLOAT);
+            FOG_LOOP(GLfloat, COMPUTE_F);
          }
+#undef COMPUTE_F
          break;
+
       case GL_EXP2:
-         {
-            const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
-            const GLfloat fogStep = span->fogStep;
-            GLfloat fogCoord = span->fog;
-            const GLfloat wStep = haveW ? span->dwdx : 0.0F;
-            GLfloat w = haveW ? span->w : 1.0F;
-            GLuint i;
-            for (i = 0; i < span->end; i++) {
-               const GLfloat coord = fogCoord / w;
-               GLfloat tmp = negDensitySquared * coord * coord;
-               GLfloat f, oneMinusF;
-#if defined(__alpha__) || defined(__alpha)
-               /* XXX this underflow check may be needed for other systems*/
-               if (tmp < FLT_MIN_10_EXP)
-                  tmp = FLT_MIN_10_EXP;
-#endif
-               f = EXPF(tmp);
-               f = CLAMP(f, 0.0F, 1.0F);
-               oneMinusF = 1.0F - f;
-               rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog);
-               rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog);
-               rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog);
-               fogCoord += fogStep;
-               w += wStep;
-            }
+#define COMPUTE_F  const GLfloat coord = fogCoord / w; \
+                   GLfloat tmp = negDensitySquared * coord * coord; \
+                   if (tmp < FLT_MIN_10_EXP) \
+                      tmp = FLT_MIN_10_EXP; \
+                   f = EXPF(tmp);
+         if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+            UBYTE_RGBA;
+            FOG_LOOP(GLubyte, COMPUTE_F);
+         }
+         else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+            USHORT_RGBA;
+            FOG_LOOP(GLushort, COMPUTE_F);
+         }
+         else {
+            FLOAT_RGBA;
+            ASSERT(span->array->ChanType == GL_FLOAT);
+            FOG_LOOP(GLfloat, COMPUTE_F);
          }
+#undef COMPUTE_F
          break;
+
       default:
          _mesa_problem(ctx, "Bad fog mode in _swrast_fog_rgba_span");
          return;
@@ -179,33 +203,58 @@ _swrast_fog_rgba_span( const GLcontext *ctx, struct sw_span *span )
        * They were previously computed per-vertex.
        */
       GLuint i;
-      for (i = 0; i < span->end; i++) {
-         const GLfloat f = span->array->fog[i];
-         const GLfloat oneMinusF = 1.0F - f;
-         rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog);
-         rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog);
-         rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog);
+      if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+         UBYTE_RGBA;
+         for (i = 0; i < span->end; i++) {
+            const GLfloat f = span->array->fog[i];
+            const GLfloat oneMinusF = 1.0F - f;
+            rgba[i][RCOMP] = (GLubyte) (f * rgba[i][RCOMP] + oneMinusF * rFog);
+            rgba[i][GCOMP] = (GLubyte) (f * rgba[i][GCOMP] + oneMinusF * gFog);
+            rgba[i][BCOMP] = (GLubyte) (f * rgba[i][BCOMP] + oneMinusF * bFog);
+         }
+      }
+      else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+         USHORT_RGBA;
+         for (i = 0; i < span->end; i++) {
+            const GLfloat f = span->array->fog[i];
+            const GLfloat oneMinusF = 1.0F - f;
+            rgba[i][RCOMP] = (GLushort) (f * rgba[i][RCOMP] + oneMinusF * rFog);
+            rgba[i][GCOMP] = (GLushort) (f * rgba[i][GCOMP] + oneMinusF * gFog);
+            rgba[i][BCOMP] = (GLushort) (f * rgba[i][BCOMP] + oneMinusF * bFog);
+         }
+      }
+      else {
+         FLOAT_RGBA;
+         ASSERT(span->array->ChanType == GL_FLOAT);
+         for (i = 0; i < span->end; i++) {
+            const GLfloat f = span->array->fog[i];
+            const GLfloat oneMinusF = 1.0F - f;
+            rgba[i][RCOMP] = f * rgba[i][RCOMP] + oneMinusF * rFog;
+            rgba[i][GCOMP] = f * rgba[i][GCOMP] + oneMinusF * gFog;
+            rgba[i][BCOMP] = f * rgba[i][BCOMP] + oneMinusF * bFog;
+         }
       }
+
    }
    else {
       /* The span's fog start/step values are blend factors.
        * They were previously computed per-vertex.
        */
-      const GLfloat fogStep = span->fogStep;
-      GLfloat fog = span->fog;
-      const GLfloat wStep = haveW ? span->dwdx : 0.0F;
-      GLfloat w = haveW ? span->w : 1.0F;
-      GLuint i;
-      ASSERT(span->interpMask & SPAN_FOG);
-      for (i = 0; i < span->end; i++) {
-         const GLfloat fact = fog / w;
-         const GLfloat oneMinusF = 1.0F - fact;
-         rgba[i][RCOMP] = (GLchan) (fact * rgba[i][RCOMP] + oneMinusF * rFog);
-         rgba[i][GCOMP] = (GLchan) (fact * rgba[i][GCOMP] + oneMinusF * gFog);
-         rgba[i][BCOMP] = (GLchan) (fact * rgba[i][BCOMP] + oneMinusF * bFog);
-         fog += fogStep;
-         w += wStep;
+#define COMPUTE_F f = fogCoord / w;
+      if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+         UBYTE_RGBA;
+         FOG_LOOP(GLubyte, COMPUTE_F);
+      }
+      else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+         USHORT_RGBA;
+         FOG_LOOP(GLushort, COMPUTE_F);
+      }
+      else {
+         FLOAT_RGBA;
+         ASSERT(span->array->ChanType == GL_FLOAT);
+         FOG_LOOP(GLfloat, COMPUTE_F);
       }
+#undef COMPUTE_F
    }
 }
 
index b791117af82ac2c6eab41caaa5b9fe4a55557c30..214e4e7735f0ec35a83524cbebcb0494b90759f7 100644 (file)
 #include "s_span.h"
 
 
-#define LOGIC_OP_LOOP(MODE)                    \
+/**
+ * We do all logic ops on 4-byte GLuints.
+ * Depending on bytes per pixel, the mask array elements correspond to
+ * 1, 2 or 4 GLuints.
+ */
+#define LOGIC_OP_LOOP(MODE, MASKSTRIDE)                \
 do {                                           \
    GLuint i;                                   \
    switch (MODE) {                             \
       case GL_CLEAR:                           \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = 0;                      \
            }                                   \
         }                                      \
         break;                                 \
       case GL_SET:                             \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = ~0;                     \
            }                                   \
         }                                      \
@@ -56,91 +61,91 @@ do {                                                \
         break;                                 \
       case GL_COPY_INVERTED:                   \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = ~src[i];                \
            }                                   \
         }                                      \
         break;                                 \
       case GL_NOOP:                            \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = dest[i];                \
            }                                   \
         }                                      \
         break;                                 \
       case GL_INVERT:                          \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = ~dest[i];               \
            }                                   \
         }                                      \
         break;                                 \
       case GL_AND:                             \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] &= dest[i];               \
            }                                   \
         }                                      \
         break;                                 \
       case GL_NAND:                            \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = ~(src[i] & dest[i]);    \
            }                                   \
         }                                      \
         break;                                 \
       case GL_OR:                              \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] |= dest[i];               \
            }                                   \
         }                                      \
         break;                                 \
       case GL_NOR:                             \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = ~(src[i] | dest[i]);    \
            }                                   \
         }                                      \
         break;                                 \
       case GL_XOR:                             \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] ^= dest[i];               \
            }                                   \
         }                                      \
         break;                                 \
       case GL_EQUIV:                           \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = ~(src[i] ^ dest[i]);    \
            }                                   \
         }                                      \
         break;                                 \
       case GL_AND_REVERSE:                     \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = src[i] & ~dest[i];      \
            }                                   \
         }                                      \
         break;                                 \
       case GL_AND_INVERTED:                    \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = ~src[i] & dest[i];      \
            }                                   \
         }                                      \
         break;                                 \
       case GL_OR_REVERSE:                      \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = src[i] | ~dest[i];      \
            }                                   \
         }                                      \
         break;                                 \
       case GL_OR_INVERTED:                     \
          for (i = 0; i < n; i++) {             \
-           if (mask[i]) {                      \
+           if (mask[i / MASKSTRIDE]) {         \
               src[i] = ~src[i] | dest[i];      \
            }                                   \
         }                                      \
@@ -152,27 +157,27 @@ do {                                              \
 
 
 
-static void
-logicop_ubyte(GLcontext *ctx, GLuint n, GLubyte src[], const GLubyte dest[],
+static INLINE void
+logicop_uint1(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
               const GLubyte mask[])
 {
-   LOGIC_OP_LOOP(ctx->Color.LogicOp);
+   LOGIC_OP_LOOP(ctx->Color.LogicOp, 1);
 }
 
 
-static void
-logicop_ushort(GLcontext *ctx, GLuint n, GLushort src[], const GLushort dest[],
-               const GLubyte mask[])
+static INLINE void
+logicop_uint2(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
+              const GLubyte mask[])
 {
-   LOGIC_OP_LOOP(ctx->Color.LogicOp);
+   LOGIC_OP_LOOP(ctx->Color.LogicOp, 2);
 }
 
 
-static void
-logicop_uint(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
-             const GLubyte mask[])
+static INLINE void
+logicop_uint4(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
+              const GLubyte mask[])
 {
-   LOGIC_OP_LOOP(ctx->Color.LogicOp);
+   LOGIC_OP_LOOP(ctx->Color.LogicOp, 4);
 }
 
 
@@ -200,7 +205,7 @@ _swrast_logicop_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb,
       rb->GetRow(ctx, rb, span->end, span->x, span->y, dest);
    }
 
-   logicop_uint(ctx, span->end, index, dest, span->array->mask);
+   logicop_uint1(ctx, span->end, index, dest, span->array->mask);
 }
 
 
@@ -213,33 +218,29 @@ void
 _swrast_logicop_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
                           struct sw_span *span)
 {
-   GLchan dest[MAX_WIDTH][4];
+   void *rbPixels;
 
    ASSERT(span->end < MAX_WIDTH);
    ASSERT(span->arrayMask & SPAN_RGBA);
-   ASSERT(rb->DataType == CHAN_TYPE);
+   ASSERT(rb->DataType == span->array->ChanType);
 
-   if (span->arrayMask & SPAN_XY) {
-      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
-                         dest, 4 * sizeof(GLchan));
+   rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
+
+   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+      /* treat 4*GLubyte as GLuint */
+      logicop_uint1(ctx, span->end,
+                    (GLuint *) span->array->color.sz1.rgba,
+                    (const GLuint *) rbPixels, span->array->mask);
+   }
+   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+      /* treat 2*GLushort as GLuint */
+      logicop_uint2(ctx, 2 * span->end,
+                    (GLuint *) span->array->color.sz2.rgba,
+                    (const GLuint *) rbPixels, span->array->mask);
    }
    else {
-      _swrast_read_rgba_span(ctx, rb, span->end, span->x, span->y, dest);
+      logicop_uint4(ctx, 4 * span->end,
+                    (GLuint *) span->array->color.sz4.rgba,
+                    (const GLuint *) rbPixels, span->array->mask);
    }
-
-   /* XXX make this a runtime test */
-#if CHAN_TYPE == GL_UNSIGNED_BYTE
-   /* treat 4*GLubyte as GLuint */
-   logicop_uint(ctx, span->end, (GLuint *) span->array->rgba,
-                (const GLuint *) dest, span->array->mask);
-#elif CHAN_TYPE == GL_UNSIGNED_SHORT
-   logicop_ushort(ctx, 4 * span->end, (GLushort *) span->array->rgba,
-                  (const GLushort *) dest, span->array->mask);
-#elif CHAN_TYPE == GL_FLOAT
-   logicop_uint(ctx, 4 * span->end, (GLuint *) span->array->rgba,
-                (const GLuint *) dest, span->array->mask);
-#endif
-   (void) logicop_ubyte;
-   (void) logicop_ushort;
-   (void) logicop_uint;
 }
index f83e305b06ca56fba5e6e8a1b3372a8f1fd4da08..4a82bbe8e6b42758541d729bf482dd4609e1c277 100644 (file)
@@ -43,44 +43,63 @@ void
 _swrast_mask_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
                        struct sw_span *span)
 {
-   GLchan dest[MAX_WIDTH][4];
-#if CHAN_BITS == 8
-   GLuint srcMask = *((GLuint*)ctx->Color.ColorMask);
-   GLuint dstMask = ~srcMask;
-   GLuint *rgba32 = (GLuint *) span->array->rgba;
-   GLuint *dest32 = (GLuint *) dest;
-#else
-   const GLboolean rMask = ctx->Color.ColorMask[RCOMP];
-   const GLboolean gMask = ctx->Color.ColorMask[GCOMP];
-   const GLboolean bMask = ctx->Color.ColorMask[BCOMP];
-   const GLboolean aMask = ctx->Color.ColorMask[ACOMP];
-#endif
    const GLuint n = span->end;
-   GLuint i;
+   void *rbPixels;
 
    ASSERT(n < MAX_WIDTH);
    ASSERT(span->arrayMask & SPAN_RGBA);
+   ASSERT(rb->DataType == span->array->ChanType);
 
-   if (span->arrayMask & SPAN_XY) {
-      _swrast_get_values(ctx, rb, n, span->array->x, span->array->y,
-                         dest, 4 * sizeof(GLchan));
-   }
-   else {
-      _swrast_read_rgba_span(ctx, rb, n, span->x, span->y, dest);
-   }
+   rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
 
-#if CHAN_BITS == 8
-   for (i = 0; i < n; i++) {
-      rgba32[i] = (rgba32[i] & srcMask) | (dest32[i] & dstMask);
+   /*
+    * Do component masking.
+    * Note that we're not using span->array->mask[] here.  We could...
+    */
+   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+      /* treat 4xGLubyte as 1xGLuint */
+      const GLuint srcMask = *((GLuint *) ctx->Color.ColorMask);
+      const GLuint dstMask = ~srcMask;
+      const GLuint *dst = (const GLuint *) rbPixels;
+      GLuint *src = (GLuint *) span->array->color.sz1.rgba;
+      GLuint i;
+      for (i = 0; i < n; i++) {
+         src[i] = (src[i] & srcMask) | (dst[i] & dstMask);
+      }
+   }
+   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+      /* 2-byte components */
+      /* XXX try to use 64-bit arithmetic someday */
+      const GLushort rMask = ctx->Color.ColorMask[RCOMP] ? 0xffff : 0x0;
+      const GLushort gMask = ctx->Color.ColorMask[GCOMP] ? 0xffff : 0x0;
+      const GLushort bMask = ctx->Color.ColorMask[BCOMP] ? 0xffff : 0x0;
+      const GLushort aMask = ctx->Color.ColorMask[ACOMP] ? 0xffff : 0x0;
+      const GLushort (*dst)[4] = (const GLushort (*)[4]) rbPixels;
+      GLushort (*src)[4] = span->array->color.sz2.rgba;
+      GLuint i;
+      for (i = 0; i < n; i++) {
+         src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
+         src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
+         src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
+         src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
+      }
    }
-#else
-   for (i = 0; i < n; i++) {
-      if (!rMask)  span->array->rgba[i][RCOMP] = dest[i][RCOMP];
-      if (!gMask)  span->array->rgba[i][GCOMP] = dest[i][GCOMP];
-      if (!bMask)  span->array->rgba[i][BCOMP] = dest[i][BCOMP];
-      if (!aMask)  span->array->rgba[i][ACOMP] = dest[i][ACOMP];
+   else {
+      /* 4-byte components */
+      const GLuint rMask = ctx->Color.ColorMask[RCOMP] ? ~0x0 : 0x0;
+      const GLuint gMask = ctx->Color.ColorMask[GCOMP] ? ~0x0 : 0x0;
+      const GLuint bMask = ctx->Color.ColorMask[BCOMP] ? ~0x0 : 0x0;
+      const GLuint aMask = ctx->Color.ColorMask[ACOMP] ? ~0x0 : 0x0;
+      const GLuint (*dst)[4] = (const GLuint (*)[4]) rbPixels;
+      GLuint (*src)[4] = (GLuint (*)[4]) span->array->color.sz4.rgba;
+      GLuint i;
+      for (i = 0; i < n; i++) {
+         src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
+         src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
+         src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
+         src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
+      }
    }
-#endif
 }
 
 
index 009945edb1279d1100653ff613c0f8241fd222d8..72b14ebf3afe151131a3bef14531d702f7008225 100644 (file)
@@ -933,7 +933,7 @@ _swrast_write_index_span( GLcontext *ctx, struct sw_span *span)
     */
    {
       struct gl_framebuffer *fb = ctx->DrawBuffer;
-      const GLuint output = 0; /* only frag progs can write to others */
+      const GLuint output = 0; /* only frag progs can write to other outputs */
       const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
       GLuint indexSave[MAX_WIDTH];
       GLuint buf;
@@ -1311,7 +1311,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
     */
    {
       struct gl_framebuffer *fb = ctx->DrawBuffer;
-      const GLuint output = 0; /* only frag progs can write to others */
+      const GLuint output = 0; /* only frag progs can write to other outputs */
       const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
       GLchan rgbaSave[MAX_WIDTH][4];
       GLuint buf;
@@ -1322,6 +1322,8 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
                       4 * span->end * sizeof(GLchan));
       }
 
+      /* XXX check that span's ChanType == rb's DataType, convert if needed */
+
       for (buf = 0; buf < numDrawBuffers; buf++) {
          struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
          ASSERT(rb->_BaseFormat == GL_RGBA);
@@ -1529,6 +1531,7 @@ _swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
 
 /**
  * Wrapper for gl_renderbuffer::PutRow() which does clipping.
+ * \param valueSize  size of each value (pixel) in bytes
  */
 void
 _swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
@@ -1563,6 +1566,7 @@ _swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
 
 /**
  * Wrapper for gl_renderbuffer::GetRow() which does clipping.
+ * \param valueSize  size of each value (pixel) in bytes
  */
 void
 _swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
@@ -1592,3 +1596,48 @@ _swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
 
    rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
 }
+
+
+/**
+ * Get RGBA pixels from the given renderbuffer.  Put the pixel colors into
+ * the span's specular color arrays.  The specular color arrays should no
+ * longer be needed by time this function is called.
+ * Used by blending, logicop and masking functions.
+ * \return pointer to the colors we read.
+ */
+void *
+_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
+                      struct sw_span *span)
+{
+   GLuint pixelSize;
+   void *rbPixels;
+
+   /*
+    * Determine pixel size (in bytes).
+    * Point rbPixels to a temporary space (use specular color arrays).
+    */
+   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+      pixelSize = 4 * sizeof(GLubyte);
+      rbPixels = span->array->color.sz1.spec;
+   }
+   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+      pixelSize = 4 * sizeof(GLushort);
+      rbPixels = span->array->color.sz2.spec;
+   }
+   else {
+      pixelSize = 4 * sizeof(GLfloat);
+      rbPixels = span->array->color.sz4.spec;
+   }
+
+   /* Get destination values from renderbuffer */
+   if (span->arrayMask & SPAN_XY) {
+      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
+                         rbPixels, pixelSize);
+   }
+   else {
+      _swrast_get_row(ctx, rb, span->end, span->x, span->y,
+                      rbPixels, pixelSize);
+   }
+
+   return rbPixels;
+}
index 40a57e1ae53014e2267fd47366e4c7125e4db5f7..4e8ba8e132920de6e1546b4d1bc89631f4f7c1fd 100644 (file)
@@ -82,4 +82,9 @@ _swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
                 GLuint count, GLint x, GLint y,
                 GLvoid *values, GLuint valueSize);
 
+
+extern void *
+_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
+                      struct sw_span *span);
+
 #endif
index 3fd914083f9e7466f875f731833add820eb8f433..77cf8ca899f1d37e94b1ebdb6b56ea8323b34073 100644 (file)
@@ -144,6 +144,18 @@ zoom_span( GLcontext *ctx, GLint imgX, GLint imgY, const struct sw_span *span,
    zoomed.x = x0;
    zoomed.end = zoomedWidth;
    zoomed.array = &zoomed_arrays;
+   zoomed_arrays.ChanType = CHAN_TYPE;
+#if CHAN_TYPE == GL_UNSIGNED_BYTE
+   zoomed_arrays.rgba = zoomed_arrays.color.sz1.rgba;
+   zoomed_arrays.spec = zoomed_arrays.color.sz1.spec;
+#elif CHAN_TYPE == GL_UNSIGNED_SHORT
+   zoomed_arrays.rgba = zoomed_arrays.color.sz2.rgba;
+   zoomed_arrays.spec = zoomed_arrays.color.sz2.spec;
+#else
+   zoomed_arrays.rgba = zoomed_arrays.color.sz4.rgba;
+   zoomed_arrays.spec = zoomed_arrays.color.sz4.spec;
+#endif
+
 
    /* copy fog interp info */
    zoomed.fog = span->fog;