more work on GL_ARB_texture_compression
[mesa.git] / src / mesa / main / drawpix.c
index a3f1354644121556e338609aaad5d7455c31f51b..f2bbd8a913f084257380bc0a38c98d302a202d2f 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: drawpix.c,v 1.8 1999/11/22 22:21:38 brianp Exp $ */
+/* $Id: drawpix.c,v 1.22 2000/05/04 13:48:49 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
  * 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"),
 #include "feedback.h"
 #include "image.h"
 #include "macros.h"
+#include "mem.h"
 #include "mmath.h"
 #include "pixel.h"
+#include "pixeltex.h"
 #include "span.h"
+#include "state.h"
 #include "stencil.h"
+#include "texture.h"
 #include "types.h"
 #include "zoom.h"
 #endif
@@ -57,28 +61,30 @@ _mesa_clip_pixelrect(const GLcontext *ctx,
                      GLsizei *width, GLsizei *height,
                      GLint *skipPixels, GLint *skipRows)
 {
+   const GLframebuffer *buffer = ctx->DrawBuffer;
+
    /* left clipping */
-   if (*destX < ctx->Buffer->Xmin) {
-      *skipPixels += (ctx->Buffer->Xmin - *destX);
-      *width -= (ctx->Buffer->Xmin - *destX);
-      *destX = ctx->Buffer->Xmin;
+   if (*destX < buffer->Xmin) {
+      *skipPixels += (buffer->Xmin - *destX);
+      *width -= (buffer->Xmin - *destX);
+      *destX = buffer->Xmin;
    }
    /* right clipping */
-   if (*destX + *width > ctx->Buffer->Xmax)
-      *width -= (*destX + *width - ctx->Buffer->Xmax - 1);
+   if (*destX + *width > buffer->Xmax)
+      *width -= (*destX + *width - buffer->Xmax - 1);
 
    if (*width <= 0)
       return GL_FALSE;
 
    /* bottom clipping */
-   if (*destY < ctx->Buffer->Ymin) {
-      *skipRows += (ctx->Buffer->Ymin - *destY);
-      *height -= (ctx->Buffer->Ymin - *destY);
-      *destY = ctx->Buffer->Ymin;
+   if (*destY < buffer->Ymin) {
+      *skipRows += (buffer->Ymin - *destY);
+      *height -= (buffer->Ymin - *destY);
+      *destY = buffer->Ymin;
    }
    /* top clipping */
-   if (*destY + *height > ctx->Buffer->Ymax)
-      *height -= (*destY + *height - ctx->Buffer->Ymax - 1);
+   if (*destY + *height > buffer->Ymax)
+      *height -= (*destY + *height - buffer->Ymax - 1);
 
    if (*height <= 0)
       return GL_TRUE;
@@ -110,24 +116,17 @@ simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
       return GL_TRUE;
    }
 
-   if (ctx->NewState) {
-      gl_update_state(ctx);
-   }
-
-   /* see if device driver can do the drawpix */
-   if (ctx->Driver.DrawPixels
-       && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
-                                    unpack, pixels)) {
-      return GL_TRUE;
-   }
-
    if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
-       && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0
-       && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0
-       && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0
-       && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0
+       && !ctx->Pixel.ScaleOrBiasRGBA
+       && !ctx->Pixel.ScaleOrBiasRGBApcm
+       && ctx->ColorMatrix.type == MATRIX_IDENTITY
+       && !ctx->Pixel.ColorTableEnabled
+       && !ctx->Pixel.PostColorMatrixColorTableEnabled
+       && !ctx->Pixel.MinMaxEnabled
+       && !ctx->Pixel.HistogramEnabled
        && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0
        && ctx->Pixel.MapColorFlag==0
+       && ctx->Texture.ReallyEnabled == 0
        && unpack->Alignment==1
        && !unpack->SwapBytes
        && !unpack->LsbFirst) {
@@ -153,24 +152,24 @@ simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
        */
       if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
          /* horizontal clipping */
-         if (destX < ctx->Buffer->Xmin) {
-            skipPixels += (ctx->Buffer->Xmin - destX);
-            drawWidth  -= (ctx->Buffer->Xmin - destX);
-            destX = ctx->Buffer->Xmin;
+         if (destX < ctx->DrawBuffer->Xmin) {
+            skipPixels += (ctx->DrawBuffer->Xmin - destX);
+            drawWidth  -= (ctx->DrawBuffer->Xmin - destX);
+            destX = ctx->DrawBuffer->Xmin;
          }
-         if (destX + drawWidth > ctx->Buffer->Xmax)
-            drawWidth -= (destX + drawWidth - ctx->Buffer->Xmax - 1);
+         if (destX + drawWidth > ctx->DrawBuffer->Xmax)
+            drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax - 1);
          if (drawWidth <= 0)
             return GL_TRUE;
 
          /* vertical clipping */
-         if (destY < ctx->Buffer->Ymin) {
-            skipRows   += (ctx->Buffer->Ymin - destY);
-            drawHeight -= (ctx->Buffer->Ymin - destY);
-            destY = ctx->Buffer->Ymin;
+         if (destY < ctx->DrawBuffer->Ymin) {
+            skipRows   += (ctx->DrawBuffer->Ymin - destY);
+            drawHeight -= (ctx->DrawBuffer->Ymin - destY);
+            destY = ctx->DrawBuffer->Ymin;
          }
-         if (destY + drawHeight > ctx->Buffer->Ymax)
-            drawHeight -= (destY + drawHeight - ctx->Buffer->Ymax - 1);
+         if (destY + drawHeight > ctx->DrawBuffer->Ymax)
+            drawHeight -= (destY + drawHeight - ctx->DrawBuffer->Ymax - 1);
          if (drawHeight <= 0)
             return GL_TRUE;
 
@@ -178,7 +177,7 @@ simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
       }
       else {
          /* setup array of fragment Z value to pass to zoom function */
-         GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
+         GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
          GLint i;
          assert(drawWidth < MAX_WIDTH);
          for (i=0; i<drawWidth; i++)
@@ -345,7 +344,7 @@ simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
                GLint row;
                for (row=0; row<drawHeight; row++) {
                   assert(drawWidth < MAX_WIDTH);
-                  gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
+                  _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
                   (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
                                                (const GLubyte (*)[4])rgba, 
                                               NULL);
@@ -359,7 +358,7 @@ simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
                GLint row;
                for (row=0; row<drawHeight; row++) {
                   assert(drawWidth < MAX_WIDTH);
-                  gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
+                  _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
                   gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
                                             zSpan, (void *) rgba, zoomY0);
                   src += rowLength;
@@ -415,8 +414,8 @@ draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
    drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
 
    /* Fragment depth values */
-   if (ctx->Depth.Test) {
-      GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
+   if (ctx->Depth.Test || ctx->Fog.Enabled) {
+      GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
       GLint i;
       for (i = 0; i < drawWidth; i++) {
         zspan[i] = zval;
@@ -428,7 +427,7 @@ draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
     */
    for (row = 0; row < height; row++, y++) {
       GLuint indexes[MAX_WIDTH];
-      const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack,
+      const GLvoid *source = _mesa_image_address(&ctx->Unpack,
                     pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
       _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes,
                               type, source, &ctx->Unpack, GL_TRUE);
@@ -453,6 +452,7 @@ draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
                      GLenum type, const GLvoid *pixels )
 {
    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
+   const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
    const GLint desty = y;
    GLint row, drawWidth;
 
@@ -474,17 +474,23 @@ draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
       GLstencil values[MAX_WIDTH];
       GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
                       ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
-      const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack,
+      const GLvoid *source = _mesa_image_address(&ctx->Unpack,
                     pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
       _mesa_unpack_index_span(ctx, drawWidth, destType, values,
-                              type, source, &ctx->Unpack, GL_TRUE);
+                              type, source, &ctx->Unpack, GL_FALSE);
+      if (shift_or_offset) {
+         _mesa_shift_and_offset_stencil( ctx, drawWidth, values );
+      }
+      if (ctx->Pixel.MapStencilFlag) {
+         _mesa_map_stencil( ctx, drawWidth, values );
+      }
 
       if (zoom) {
          gl_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y,
                                        values, desty );
       }
       else {
-         gl_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
+         _mesa_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
       }
    }
 }
@@ -543,30 +549,23 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
       /* Special case: directly write 16-bit depth values */
       GLint row;
       for (row = 0; row < height; row++, y++) {
-         const GLdepth *zptr = gl_pixel_addr_in_image(&ctx->Unpack,
+         GLdepth zspan[MAX_WIDTH];
+         const GLushort *zptr = _mesa_image_address(&ctx->Unpack,
                 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
-         gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
+         GLint i;
+         for (i = 0; i < width; i++)
+            zspan[i] = zptr[i];
+         gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
       }
    }
-   else if (type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
+   else if (type==GL_UNSIGNED_INT && ctx->Visual->DepthBits == 32
        && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
       /* Special case: directly write 32-bit depth values */
-      GLint i, row;
-      /* Compute shift value to scale 32-bit uints down to depth values. */
-      GLuint shift = 0;
-      GLuint max = MAX_DEPTH;
-      while ((max & 0x80000000) == 0) {
-         max = max << 1;
-         shift++;
-      }
+      GLint row;
       for (row = 0; row < height; row++, y++) {
-         GLdepth zspan[MAX_WIDTH];
-         const GLdepth *zptr = gl_pixel_addr_in_image(&ctx->Unpack,
+         const GLuint *zptr = _mesa_image_address(&ctx->Unpack,
                 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
-         for (i=0;i<width;i++) {
-            zspan[i] = zptr[i] >> shift;
-         }
-         gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
+         gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
       }
    }
    else {
@@ -574,7 +573,7 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
       GLint row;
       for (row = 0; row < height; row++, y++) {
          GLdepth zspan[MAX_WIDTH];
-         const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack,
+         const GLvoid *src = _mesa_image_address(&ctx->Unpack,
                 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
          _mesa_unpack_depth_span( ctx, drawWidth, zspan, type, src,
                                   &ctx->Unpack, GL_TRUE );
@@ -621,9 +620,9 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
       return;
 
    /* Fragment depth values */
-   if (ctx->Depth.Test) {
+   if (ctx->Depth.Test || ctx->Fog.Enabled) {
       /* fill in array of z values */
-      GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
+      GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
       GLint i;
       for (i=0;i<width;i++) {
         zspan[i] = z;
@@ -633,8 +632,8 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
 
    if (ctx->RasterMask == 0 && !zoom
        && x >= 0 && y >= 0
-       && x + width <= ctx->Buffer->Width
-       && y + height <= ctx->Buffer->Height) {
+       && x + width <= ctx->DrawBuffer->Width
+       && y + height <= ctx->DrawBuffer->Height) {
       quickDraw = GL_TRUE;
    }
    else {
@@ -650,10 +649,23 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
       if (width > MAX_WIDTH)
          width = MAX_WIDTH;
       for (row = 0; row < height; row++, y++) {
-         const GLvoid *source = gl_pixel_addr_in_image(unpack,
+         const GLvoid *source = _mesa_image_address(unpack,
                   pixels, width, height, format, type, 0, row, 0);
          _mesa_unpack_ubyte_color_span(ctx, width, GL_RGBA, (void*) rgba,
                    format, type, source, unpack, GL_TRUE);
+         if (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
+            continue;
+
+         if (ctx->Texture.ReallyEnabled && ctx->Pixel.PixelTextureEnabled) {
+            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH];
+            GLuint unit;
+            /* XXX not sure how multitexture is supposed to work here */
+            for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++) {
+               _mesa_pixeltexgen(ctx, width, (const GLubyte (*)[4]) rgba,
+                                 s, t, r, q);
+               gl_texture_pixels(ctx, unit, width, s, t, r, NULL, rgba);
+            }
+         }
 
          if (quickDraw) {
             (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
@@ -688,9 +700,22 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
         return;
       }
 
+      if (ctx->NewState) {
+         gl_update_state(ctx);
+      }
+
       x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
       y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
 
+      ctx->OcclusionResult = GL_TRUE;
+
+      /* see if device driver can do the drawpix */
+      if (ctx->Driver.DrawPixels
+          && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
+                                       &ctx->Unpack, pixels)) {
+         return;
+      }
+
       switch (format) {
         case GL_STENCIL_INDEX:
            draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
@@ -700,9 +725,9 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
            break;
         case GL_COLOR_INDEX:
             if (ctx->Visual->RGBAflag)
-               draw_index_pixels(ctx, x, y, width, height, type, pixels);
-            else
                draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
+            else
+               draw_index_pixels(ctx, x, y, width, height, type, pixels);
            break;
         case GL_RED:
         case GL_GREEN: