added GL_SGIX/SGIS_pixel_texture
[mesa.git] / src / mesa / main / accum.c
index adca8ec2f421f797c9f2e7d4dac436e5a532ad35..6654a6314ba37834495b95dbcd702f1424f2959a 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: accum.c,v 1.8 1999/10/20 22:39:16 brianp Exp $ */
+/* $Id: accum.c,v 1.20 2000/04/05 14:40:04 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.1
+ * Version:  3.3
  * 
- * Copyright (C) 1999  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2000  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"),
  */
 
 
-/* $XFree86: xc/lib/GL/mesa/src/accum.c,v 1.3 1999/04/04 00:20:17 dawes Exp $ */
-
 #ifdef PC_HEADER
 #include "all.h"
 #else
-#ifndef XFree86Server
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#else
-#include "GL/xf86glx.h"
-#endif
-#include <assert.h>
+#include "glheader.h"
 #include "accum.h"
 #include "context.h"
-#include "macros.h"
+#include "mem.h"
 #include "masking.h"
 #include "span.h"
+#include "state.h"
 #include "types.h"
-#ifdef XFree86Server
-#include "GL/xf86glx.h"
-#endif
 #endif
 
 
 
 
 
-void gl_alloc_accum_buffer( GLcontext *ctx )
+void
+_mesa_alloc_accum_buffer( GLcontext *ctx )
 {
    GLint n;
 
-   if (ctx->Buffer->Accum) {
-      FREE( ctx->Buffer->Accum );
-      ctx->Buffer->Accum = NULL;
+   if (ctx->DrawBuffer->Accum) {
+      FREE( ctx->DrawBuffer->Accum );
+      ctx->DrawBuffer->Accum = NULL;
    }
 
    /* allocate accumulation buffer if not already present */
-   n = ctx->Buffer->Width * ctx->Buffer->Height * 4 * sizeof(GLaccum);
-   ctx->Buffer->Accum = (GLaccum *) MALLOC( n );
-   if (!ctx->Buffer->Accum) {
+   n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height * 4 * sizeof(GLaccum);
+   ctx->DrawBuffer->Accum = (GLaccum *) MALLOC( n );
+   if (!ctx->DrawBuffer->Accum) {
       /* unable to setup accumulation buffer */
       gl_error( ctx, GL_OUT_OF_MEMORY, "glAccum" );
    }
@@ -104,9 +94,10 @@ void gl_alloc_accum_buffer( GLcontext *ctx )
 
 
 
-void gl_ClearAccum( GLcontext *ctx,
-                    GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
+void
+_mesa_ClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
 {
+   GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glAccum");
 
    ctx->Accum.ClearColor[0] = CLAMP( red, -1.0, 1.0 );
@@ -124,10 +115,10 @@ void gl_ClearAccum( GLcontext *ctx,
  */
 static void rescale_accum( GLcontext *ctx )
 {
-   const GLuint n = ctx->Buffer->Width * ctx->Buffer->Height * 4;
+   const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height * 4;
    const GLfloat fChanMax = (1 << (sizeof(GLchan) * 8)) - 1;
    const GLfloat s = ctx->IntegerAccumScaler * (32767.0 / fChanMax);
-   GLaccum *accum = ctx->Buffer->Accum;
+   GLaccum *accum = ctx->DrawBuffer->Accum;
    GLuint i;
 
    assert(ctx->IntegerAccumMode);
@@ -142,8 +133,10 @@ static void rescale_accum( GLcontext *ctx )
 
 
 
-void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
+void
+_mesa_Accum( GLenum op, GLfloat value )
 {
+   GET_CURRENT_CONTEXT(ctx);
    GLuint xpos, ypos, width, height, width4;
    GLfloat acc_scale;
    GLubyte rgba[MAX_WIDTH][4];
@@ -152,9 +145,13 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
    
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glAccum");
 
-   if (ctx->Visual->AccumBits==0 || !ctx->Buffer->Accum) {
-      /* No accumulation buffer! */
-      gl_warning(ctx, "Calling glAccum() without an accumulation buffer");
+   if (ctx->Visual->AccumRedBits == 0 || ctx->DrawBuffer != ctx->ReadBuffer) {
+      gl_error(ctx, GL_INVALID_OPERATION, "glAccum");
+      return;
+   }
+
+   if (!ctx->DrawBuffer->Accum) {
+      gl_warning(ctx, "Calling glAccum() without an accumulation buffer (low memory?)");
       return;
    }
 
@@ -183,8 +180,8 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
       /* whole window */
       xpos = 0;
       ypos = 0;
-      width = ctx->Buffer->Width;
-      height = ctx->Buffer->Height;
+      width = ctx->DrawBuffer->Width;
+      height = ctx->DrawBuffer->Height;
    }
 
    width4 = 4 * width;
@@ -198,7 +195,7 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
             if (ctx->IntegerAccumMode)
                rescale_accum(ctx);
            for (j = 0; j < height; j++) {
-              GLaccum * acc = ctx->Buffer->Accum + ypos * width4 + 4 * xpos;
+              GLaccum * acc = ctx->DrawBuffer->Accum + ypos * width4 + 4 * xpos;
                GLuint i;
               for (i = 0; i < width4; i++) {
                   acc[i] += intVal;
@@ -215,7 +212,7 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
             if (ctx->IntegerAccumMode)
                rescale_accum(ctx);
            for (j = 0; j < height; j++) {
-              GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + 4 * xpos;
+              GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + 4 * xpos;
                GLuint i;
               for (i = 0; i < width4; i++) {
                   acc[i] = (GLaccum) ( (GLfloat) acc[i] * value );
@@ -226,7 +223,8 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
         break;
 
       case GL_ACCUM:
-         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
+         (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
+                                       ctx->Pixel.DriverReadBuffer );
 
          /* May have to leave optimized accum buffer mode */
          if (ctx->IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0)
@@ -237,13 +235,13 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
          if (ctx->IntegerAccumMode) {
             /* simply add integer color values into accum buffer */
             GLuint j;
-            GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4;
+            GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4;
             assert(ctx->IntegerAccumScaler > 0.0);
             assert(ctx->IntegerAccumScaler <= 1.0);
             for (j = 0; j < height; j++) {
                
                GLuint i, i4;
-               gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
+               gl_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba);
                for (i = i4 = 0; i < width; i++, i4+=4) {
                   acc[i4+0] += rgba[i][RCOMP];
                   acc[i4+1] += rgba[i][GCOMP];
@@ -262,9 +260,9 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
             const GLfloat ascale = value * acc_scale / fChanMax;
             GLuint j;
             for (j=0;j<height;j++) {
-               GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4;
+               GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4;
                GLuint i;
-               gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
+               gl_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba);
                for (i=0;i<width;i++) {
                   *acc += (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale );  acc++;
                   *acc += (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale );  acc++;
@@ -274,11 +272,14 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
                ypos++;
             }
          }
-         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
+         /* restore read buffer = draw buffer (the default) */
+         (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
+                                       ctx->Color.DriverDrawBuffer );
         break;
 
       case GL_LOAD:
-         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
+         (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
+                                       ctx->Pixel.DriverReadBuffer );
 
          /* This is a change to go into optimized accum buffer mode */
          if (value > 0.0 && value <= 1.0) {
@@ -297,12 +298,12 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
          if (ctx->IntegerAccumMode) {
             /* just copy values into accum buffer */
             GLuint j;
-            GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4;
+            GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4;
             assert(ctx->IntegerAccumScaler > 0.0);
             assert(ctx->IntegerAccumScaler <= 1.0);
             for (j = 0; j < height; j++) {
                GLuint i, i4;
-               gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
+               gl_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba);
                for (i = i4 = 0; i < width; i++, i4 += 4) {
                   acc[i4+0] = rgba[i][RCOMP];
                   acc[i4+1] = rgba[i][GCOMP];
@@ -322,8 +323,8 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
             const GLfloat d = 3.0 / acc_scale;
             GLuint i, j;
             for (j = 0; j < height; j++) {
-               GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4;
-               gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
+               GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos * 4;
+               gl_read_rgba_span(ctx, ctx->DrawBuffer, width, xpos, ypos, rgba);
                for (i=0;i<width;i++) {
                   *acc++ = (GLaccum) ((GLfloat) rgba[i][RCOMP] * rscale + d);
                   *acc++ = (GLaccum) ((GLfloat) rgba[i][GCOMP] * gscale + d);
@@ -333,7 +334,10 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
                ypos++;
             }
          }
-         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
+
+         /* restore read buffer = draw buffer (the default) */
+         (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
+                                       ctx->Color.DriverDrawBuffer );
         break;
 
       case GL_RETURN:
@@ -341,13 +345,13 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
          if (ctx->IntegerAccumMode && value != 1.0)
             rescale_accum(ctx);
 
-         if (ctx->IntegerAccumMode) {
+         if (ctx->IntegerAccumMode && ctx->IntegerAccumScaler > 0) {
             /* build lookup table to avoid many floating point multiplies */
             const GLfloat mult = ctx->IntegerAccumScaler;
             static GLchan multTable[32768];
             static GLfloat prevMult = 0.0;
             GLuint j;
-            const GLint max = 256 / mult;
+            const GLint max = (GLint) (256 / mult);
             if (mult != prevMult) {
                assert(max <= 32768);
                for (j = 0; j < max; j++)
@@ -358,7 +362,7 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
             assert(ctx->IntegerAccumScaler > 0.0);
             assert(ctx->IntegerAccumScaler <= 1.0);
             for (j = 0; j < height; j++) {
-               const GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos*4;
+               const GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos*4;
                GLuint i, i4;
                for (i = i4 = 0; i < width; i++, i4 += 4) {
                   ASSERT(acc[i4+0] < max);
@@ -371,7 +375,7 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
                   rgba[i][ACOMP] = multTable[acc[i4+3]];
                }
                if (ctx->Color.SWmasking) {
-                  gl_mask_rgba_span( ctx, width, xpos, ypos, rgba );
+                  _mesa_mask_rgba_span( ctx, width, xpos, ypos, rgba );
                }
                (*ctx->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, 
                                              (const GLubyte (*)[4])rgba, NULL );
@@ -385,7 +389,7 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
             const GLfloat ascale = value / acc_scale * fChanMax;
             GLuint i, j;
             for (j=0;j<height;j++) {
-               const GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos*4;
+               const GLaccum *acc = ctx->DrawBuffer->Accum + ypos * width4 + xpos*4;
                for (i=0;i<width;i++) {
                   GLint r, g, b, a;
                   r = (GLint) ( (GLfloat) (*acc++) * rscale + 0.5F );
@@ -398,7 +402,7 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
                   rgba[i][ACOMP] = CLAMP( a, 0, iChanMax );
                }
                if (ctx->Color.SWmasking) {
-                  gl_mask_rgba_span( ctx, width, xpos, ypos, rgba );
+                  _mesa_mask_rgba_span( ctx, width, xpos, ypos, rgba );
                }
                (*ctx->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, 
                                              (const GLubyte (*)[4])rgba, NULL );
@@ -417,12 +421,13 @@ void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
 /*
  * Clear the accumulation Buffer.
  */
-void gl_clear_accum_buffer( GLcontext *ctx )
+void
+_mesa_clear_accum_buffer( GLcontext *ctx )
 {
    GLuint buffersize;
    GLfloat acc_scale;
 
-   if (ctx->Visual->AccumBits==0) {
+   if (ctx->Visual->AccumRedBits==0) {
       /* No accumulation buffer! */
       return;
    }
@@ -439,15 +444,15 @@ void gl_clear_accum_buffer( GLcontext *ctx )
    }
 
    /* number of pixels */
-   buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
+   buffersize = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
 
-   if (!ctx->Buffer->Accum) {
+   if (!ctx->DrawBuffer->Accum) {
       /* try to alloc accumulation buffer */
-      ctx->Buffer->Accum = (GLaccum *)
+      ctx->DrawBuffer->Accum = (GLaccum *)
                           MALLOC( buffersize * 4 * sizeof(GLaccum) );
    }
 
-   if (ctx->Buffer->Accum) {
+   if (ctx->DrawBuffer->Accum) {
       if (ctx->Scissor.Enabled) {
         /* Limit clear to scissor box */
         GLaccum r, g, b, a;
@@ -459,12 +464,12 @@ void gl_clear_accum_buffer( GLcontext *ctx )
         b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
         a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
          /* size of region to clear */
-         width = 4 * (ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1);
-         height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
+         width = 4 * (ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin + 1);
+         height = ctx->DrawBuffer->Ymax - ctx->DrawBuffer->Ymin + 1;
          /* ptr to first element to clear */
-         row = ctx->Buffer->Accum
-               + 4 * (ctx->Buffer->Ymin * ctx->Buffer->Width
-                      + ctx->Buffer->Xmin);
+         row = ctx->DrawBuffer->Accum
+               + 4 * (ctx->DrawBuffer->Ymin * ctx->DrawBuffer->Width
+                      + ctx->DrawBuffer->Xmin);
          for (j=0;j<height;j++) {
             for (i=0;i<width;i+=4) {
                row[i+0] = r;
@@ -472,7 +477,7 @@ void gl_clear_accum_buffer( GLcontext *ctx )
                row[i+2] = b;
                row[i+3] = a;
            }
-            row += 4 * ctx->Buffer->Width;
+            row += 4 * ctx->DrawBuffer->Width;
         }
       }
       else {
@@ -482,14 +487,14 @@ void gl_clear_accum_buffer( GLcontext *ctx )
             ctx->Accum.ClearColor[2]==0.0 &&
             ctx->Accum.ClearColor[3]==0.0) {
            /* Black */
-           MEMSET( ctx->Buffer->Accum, 0, buffersize * 4 * sizeof(GLaccum) );
+           BZERO( ctx->DrawBuffer->Accum, buffersize * 4 * sizeof(GLaccum) );
         }
         else {
            /* Not black */
            GLaccum *acc, r, g, b, a;
            GLuint i;
 
-           acc = ctx->Buffer->Accum;
+           acc = ctx->DrawBuffer->Accum;
            r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
            g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
            b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);