Remove unused texunit parameter to ctx->Driver.GenerateMipmap()
[mesa.git] / src / mesa / main / drawpix.c
index 0b49428621362ee6dd750bf00fddbe83b1da6e48..fde933843095522911387a0804b379076b836cd7 100644 (file)
@@ -1,21 +1,19 @@
-/* $Id: drawpix.c,v 1.4 1999/10/19 20:33:57 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  3.1
- * 
- * Copyright (C) 1999  Brian Paul   All Rights Reserved.
- * 
+ * Version:  7.1
+ *
+ * Copyright (C) 1999-2008  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"),
  * to deal in the Software without restriction, including without limitation
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-
-
-
-
-#ifdef PC_HEADER
-#include "all.h"
-#else
-#ifndef XFree86Server
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#else
-#include "GL/xf86glx.h"
-#endif
+#include "glheader.h"
+#include "imports.h"
+#include "bufferobj.h"
 #include "context.h"
 #include "drawpix.h"
 #include "feedback.h"
+#include "framebuffer.h"
 #include "image.h"
-#include "macros.h"
-#include "mmath.h"
-#include "pixel.h"
-#include "span.h"
-#include "stencil.h"
-#include "types.h"
-#include "zoom.h"
-#ifdef XFree86Server
-#include "GL/xf86glx.h"
-#endif
-#endif
-
-
-
-/* TODO:  apply texture mapping to fragments */
+#include "state.h"
 
 
-/*
- * Try to do a fast glDrawPixels.  Conditions include:
- *   not using a display list
- *   simple pixel unpacking
- *   no raster ops
- *   etc....
- * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
+/**
+ * Do error checking of the format/type parameters to glReadPixels and
+ * glDrawPixels.
+ * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
+ *                for ReadPixels.
+ * \return GL_TRUE if error detected, GL_FALSE if no errors
  */
-GLboolean gl_direct_DrawPixels( GLcontext *ctx,
-                                const struct gl_pixelstore_attrib *unpack,
-                                GLsizei width, GLsizei height,
-                                GLenum format, GLenum type,
-                                const GLvoid *pixels )
+static GLboolean
+error_check_format_type(GLcontext *ctx, GLenum format, GLenum type,
+                        GLboolean drawing)
 {
-   GLubyte rgb[MAX_WIDTH][3];
-   GLubyte rgba[MAX_WIDTH][4];
-
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels", 
-                                                 GL_FALSE);
-
+   const char *readDraw = drawing ? "Draw" : "Read";
 
-   if (!ctx->Current.RasterPosValid) {
-      /* no-op */
+   if (ctx->Extensions.EXT_packed_depth_stencil
+       && type == GL_UNSIGNED_INT_24_8_EXT
+       && format != GL_DEPTH_STENCIL_EXT) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
       return GL_TRUE;
    }
 
-   if (ctx->NewState) {
-      gl_update_state(ctx);
+   /* basic combinations test */
+   if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "gl%sPixels(format or type)", readDraw);
+      return GL_TRUE;
    }
 
-   /* see if device driver can do the drawpix */
-   if (ctx->Driver.DrawPixels) {
-      GLint x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
-      GLint y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
-      if ((*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
-                                    unpack, pixels))
+   /* additional checks */
+   switch (format) {
+   case GL_RED:
+   case GL_GREEN:
+   case GL_BLUE:
+   case GL_ALPHA:
+   case GL_LUMINANCE:
+   case GL_LUMINANCE_ALPHA:
+   case GL_RGB:
+   case GL_BGR:
+   case GL_RGBA:
+   case GL_BGRA:
+   case GL_ABGR_EXT:
+      if (drawing && !ctx->Visual.rgbMode) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                   "glDrawPixels(drawing RGB pixels into color index buffer)");
          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.IndexShift==0 && ctx->Pixel.IndexOffset==0
-       && ctx->Pixel.MapColorFlag==0
-       && unpack->Alignment==1
-       && !unpack->SwapBytes
-       && !unpack->LsbFirst) {
-
-      GLint destX = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
-      GLint destY = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
-      GLint drawWidth = width;           /* actual width drawn */
-      GLint drawHeight = height;         /* actual height drawn */
-      GLint skipPixels = unpack->SkipPixels;
-      GLint skipRows = unpack->SkipRows;
-      GLint rowLength;
-      GLdepth zSpan[MAX_WIDTH];  /* only used when zooming */
-      GLint zoomY0;
-
-      if (unpack->RowLength > 0)
-         rowLength = unpack->RowLength;
-      else
-         rowLength = width;
-
-      /* If we're not using pixel zoom then do all clipping calculations
-       * now.  Otherwise, we'll let the gl_write_zoomed_*_span() functions
-       * handle the clipping.
-       */
-      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 + drawWidth > ctx->Buffer->Xmax)
-            drawWidth -= (destX + drawWidth - ctx->Buffer->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 + drawHeight > ctx->Buffer->Ymax)
-            drawHeight -= (destY + drawHeight - ctx->Buffer->Ymax - 1);
-         if (drawHeight <= 0)
-            return GL_TRUE;
       }
-      else {
-         /* setup array of fragment Z value to pass to zoom function */
-         GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
-         GLint i;
-         assert(drawWidth < MAX_WIDTH);
-         for (i=0; i<drawWidth; i++)
-            zSpan[i] = z;
-
-         /* save Y value of first row */
-         zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
+      if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glReadPixels(no color buffer)");
+         return GL_TRUE;
       }
-
-
-      /*
-       * Ready to draw!
-       * The window region at (destX, destY) of size (drawWidth, drawHeight)
-       * will be written to.
-       * We'll take pixel data from buffer pointed to by "pixels" but we'll
-       * skip "skipRows" rows and skip "skipPixels" pixels/row.
-       */
-
-      if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
-         if (ctx->Visual->RGBAflag) {
-            GLubyte *src = (GLubyte *) pixels
-               + (skipRows * rowLength + skipPixels) * 4;
-            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
-               /* no zooming */
-               GLint row;
-               for (row=0; row<drawHeight; row++) {
-                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
-                                               (void *) src, NULL);
-                  src += rowLength * 4;
-                  destY++;
-               }
-            }
-            else {
-               /* with zooming */
-               GLint row;
-               for (row=0; row<drawHeight; row++) {
-                  gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
-                                            zSpan, (void *) src, zoomY0);
-                  src += rowLength * 4;
-                  destY++;
-               }
-            }
-         }
+      break;
+   case GL_COLOR_INDEX:
+      if (!drawing && ctx->Visual.rgbMode) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                    "glReadPixels(reading color index format from RGB buffer)");
          return GL_TRUE;
       }
-      else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) {
-         if (ctx->Visual->RGBAflag) {
-            GLubyte *src = (GLubyte *) pixels
-               + (skipRows * rowLength + skipPixels) * 3;
-            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
-               GLint row;
-               for (row=0; row<drawHeight; row++) {
-                  (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
-                                              (void *) src, NULL);
-                  src += rowLength * 3;
-                  destY++;
-               }
-            }
-            else {
-               /* with zooming */
-               GLint row;
-               for (row=0; row<drawHeight; row++) {
-                  gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
-                                           zSpan, (void *) src, zoomY0);
-                  src += rowLength * 3;
-                  destY++;
-               }
-            }
-         }
+      if (!drawing && !_mesa_dest_buffer_exists(ctx, GL_COLOR)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glReadPixels(no color buffer)");
          return GL_TRUE;
       }
-      else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) {
-         if (ctx->Visual->RGBAflag) {
-            GLubyte *src = (GLubyte *) pixels
-               + (skipRows * rowLength + skipPixels);
-            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
-               /* no zooming */
-               GLint row;
-               assert(drawWidth < MAX_WIDTH);
-               for (row=0; row<drawHeight; row++) {
-                  GLint i;
-                 for (i=0;i<drawWidth;i++) {
-                     rgb[i][0] = src[i];
-                     rgb[i][1] = src[i];
-                     rgb[i][2] = src[i];
-                 }
-                  (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
-                                              (void *) rgb, NULL);
-                  src += rowLength;
-                  destY++;
-               }
-            }
-            else {
-               /* with zooming */
-               GLint row;
-               assert(drawWidth < MAX_WIDTH);
-               for (row=0; row<drawHeight; row++) {
-                  GLint i;
-                 for (i=0;i<drawWidth;i++) {
-                     rgb[i][0] = src[i];
-                     rgb[i][1] = src[i];
-                     rgb[i][2] = src[i];
-                 }
-                  gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
-                                           zSpan, (void *) rgb, zoomY0);
-                  src += rowLength;
-                  destY++;
-               }
-            }
-         }
+      break;
+   case GL_STENCIL_INDEX:
+      if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
+          (!drawing && !_mesa_source_buffer_exists(ctx, format))) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "gl%sPixels(no stencil buffer)", readDraw);
          return GL_TRUE;
       }
-      else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) {
-         if (ctx->Visual->RGBAflag) {
-            GLubyte *src = (GLubyte *) pixels
-               + (skipRows * rowLength + skipPixels)*2;
-            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
-               /* no zooming */
-               GLint row;
-               assert(drawWidth < MAX_WIDTH);
-               for (row=0; row<drawHeight; row++) {
-                  GLint i;
-                  GLubyte *ptr = src;
-                 for (i=0;i<drawWidth;i++) {
-                     rgba[i][0] = *ptr;
-                     rgba[i][1] = *ptr;
-                     rgba[i][2] = *ptr++;
-                     rgba[i][3] = *ptr++;
-                 }
-                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
-                                               (void *) rgba, NULL);
-                  src += rowLength*2;
-                  destY++;
-               }
-            }
-            else {
-               /* with zooming */
-               GLint row;
-               assert(drawWidth < MAX_WIDTH);
-               for (row=0; row<drawHeight; row++) {
-                  GLubyte *ptr = src;
-                  GLint i;
-                 for (i=0;i<drawWidth;i++) {
-                     rgba[i][0] = *ptr;
-                     rgba[i][1] = *ptr;
-                     rgba[i][2] = *ptr++;
-                     rgba[i][3] = *ptr++;
-                 }
-                  gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
-                                            zSpan, (void *) rgba, zoomY0);
-                  src += rowLength*2;
-                  destY++;
-               }
-            }
-         }
+      break;
+   case GL_DEPTH_COMPONENT:
+      if (!drawing && !_mesa_source_buffer_exists(ctx, format)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "gl%sPixels(no depth buffer)", readDraw);
          return GL_TRUE;
       }
-      else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
-         GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
-         if (ctx->Visual->RGBAflag) {
-            /* convert CI data to RGBA */
-            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
-               /* no zooming */
-               GLint row;
-               for (row=0; row<drawHeight; row++) {
-                  assert(drawWidth < MAX_WIDTH);
-                  gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
-                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
-                                               (const GLubyte (*)[4])rgba, 
-                                              NULL);
-                  src += rowLength;
-                  destY++;
-               }
-               return GL_TRUE;
-            }
-            else {
-               /* with zooming */
-               GLint row;
-               for (row=0; row<drawHeight; row++) {
-                  assert(drawWidth < MAX_WIDTH);
-                  gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
-                  gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
-                                            zSpan, (void *) rgba, zoomY0);
-                  src += rowLength;
-                  destY++;
-               }
-               return GL_TRUE;
-            }
-         }
-         else {
-            /* write CI data to CI frame buffer */
-            GLint row;
-            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
-               /* no zooming */
-               for (row=0; row<drawHeight; row++) {
-                  (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
-                                              src, NULL);
-                  src += rowLength;
-                  destY++;
-               }
-               return GL_TRUE;
-            }
-            else {
-               /* with zooming */
-               return GL_FALSE;
-            }
-         }
+      break;
+   case GL_DEPTH_STENCIL_EXT:
+      if (!ctx->Extensions.EXT_packed_depth_stencil ||
+          type != GL_UNSIGNED_INT_24_8_EXT) {
+         _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
+         return GL_TRUE;
       }
-      else {
-         /* can't handle this pixel format and/or data type here */
-         return GL_FALSE;
+      if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
+          (!drawing && !_mesa_source_buffer_exists(ctx, format))) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "gl%sPixels(no depth or stencil buffer)", readDraw);
+         return GL_TRUE;
       }
+      break;
+   default:
+      /* this should have been caught in _mesa_is_legal_format_type() */
+      _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw);
+      return GL_TRUE;
    }
-   else {
-      /* can't do direct render, have to use slow path */
-      return GL_FALSE;
-   }
+
+   /* no errors */
+   return GL_FALSE;
 }
+      
 
 
+#if _HAVE_FULL_GL
 
 /*
- * Do glDrawPixels of index pixels.
+ * Execute glDrawPixels
  */
-static void draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
-                               const struct gl_image *image )
+void GLAPIENTRY
+_mesa_DrawPixels( GLsizei width, GLsizei height,
+                  GLenum format, GLenum type, const GLvoid *pixels )
 {
-   GLint width, height, widthInBytes;
-   const GLint desty = y;
-   GLint i, j;
-   GLdepth zspan[MAX_WIDTH];
-   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
-
-   assert(image);
-   assert(image->Format == GL_COLOR_INDEX);
-
-   width = image->Width;
-   height = image->Height;
-   if (image->Type == GL_BITMAP)
-      widthInBytes = (width + 7) / 8;
-   else
-      widthInBytes = width;
-
-   /* Fragment depth values */
-   if (ctx->Depth.Test) {
-      GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
-      for (i=0;i<width;i++) {
-        zspan[i] = zval;
-      }
-   }
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-   /* process the image row by row */
-   for (i=0;i<height;i++,y++) {
-      GLuint ispan[MAX_WIDTH];
-
-      /* convert to uints */
-      switch (image->Type) {
-        case GL_UNSIGNED_BYTE:
-           {
-              GLubyte *src = (GLubyte *) image->Data + i * width;
-              for (j=0;j<width;j++) {
-                 ispan[j] = (GLuint) *src++;
-              }
-           }
-           break;
-        case GL_FLOAT:
-           {
-              GLfloat *src = (GLfloat *) image->Data + i * width;
-              for (j=0;j<width;j++) {
-                 ispan[j] = (GLuint) (GLint) *src++;
-              }
-           }
-           break;
-         case GL_BITMAP:
-            {
-              GLubyte *src = (GLubyte *) image->Data + i * widthInBytes;
-              for (j=0;j<width;j++) {
-                 ispan[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
-              }
-            }
-            break;
-        default:
-           gl_problem( ctx, "draw_index_pixels type" );
-            return;
-      }
-
-      /* apply shift and offset */
-      if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
-         gl_shift_and_offset_ci( ctx, width, ispan );
-      }
+   if (width < 0 || height < 0) {
+      _mesa_error( ctx, GL_INVALID_VALUE, "glDrawPixels(width or height < 0" );
+      return;
+   }
 
-      if (ctx->Visual->RGBAflag) {
-        /* Convert index to RGBA and write to frame buffer */
-        GLubyte rgba[MAX_WIDTH][4];
-         gl_map_ci_to_rgba( ctx, width, ispan, rgba );
-         if (zoom) {
-            gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 
-                                      (const GLubyte (*)[4])rgba, desty );
-         }
-         else {
-            gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
-         }
-      }
-      else {
-        /* optionally apply index map then write to frame buffer */
-        if (ctx->Pixel.MapColorFlag) {
-            gl_map_ci(ctx, width, ispan);
-        }
-         if (zoom) {
-            gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty );
-         }
-         else {
-            gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
-         }
-      }
+   if (ctx->NewState) {
+      _mesa_update_state(ctx);
    }
 
-}
+   if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glDrawPixels (invalid fragment program)");
+      return;
+   }
 
+   if (error_check_format_type(ctx, format, type, GL_TRUE)) {
+      /* found an error */
+      return;
+   }
 
+   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                  "glDrawPixels(incomplete framebuffer)" );
+      return;
+   }
 
-/*
- * Do glDrawPixels of stencil image.  The image datatype may either
- * be GLubyte or GLbitmap.
- */
-static void draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
-                                 const struct gl_image *image )
-{
-   GLint widthInBytes, width, height;
-   const GLint desty = y;
-   GLint i;
-   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
-
-   if (image->Type != GL_BYTE &&
-       image->Type != GL_UNSIGNED_BYTE &&
-       image->Type != GL_SHORT &&
-       image->Type != GL_UNSIGNED_SHORT &&
-       image->Type != GL_INT &&
-       image->Type != GL_UNSIGNED_INT &&
-       image->Type != GL_FLOAT &&
-       image->Type != GL_BITMAP) {
-      gl_error( ctx, GL_INVALID_OPERATION, "glDrawPixels(stencil type)");
+   if (!ctx->Current.RasterPosValid) {
       return;
    }
 
-   assert(image);
-   assert(image->Format == GL_STENCIL_INDEX);
-   assert(image->Type == GL_UNSIGNED_BYTE || image->Type == GL_BITMAP);
-
-   if (image->Type == GL_UNSIGNED_BYTE)
-      widthInBytes = image->Width;
-   else
-      widthInBytes = (image->Width + 7) / 8;
-   width = image->Width;
-   height = image->Height;
-
-   /* process the image row by row */
-   for (i=0;i<height;i++,y++) {
-      GLstencil *src = (GLstencil*)image->Data + i * widthInBytes;
-      GLstencil *stencilValues;
-      GLstencil stencilCopy[MAX_WIDTH];
-
-      if (image->Type == GL_BITMAP) {
-         /* convert bitmap data to GLubyte (0 or 1) data */
-         GLint j;
-         for (j = 0; j < width; j++) {
-            stencilCopy[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
+   if (ctx->RenderMode == GL_RENDER) {
+      /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
+      GLint x = IROUND(ctx->Current.RasterPos[0]);
+      GLint y = IROUND(ctx->Current.RasterPos[1]);
+
+      if (ctx->Unpack.BufferObj->Name) {
+         /* unpack from PBO */
+         if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+                                        format, type, pixels)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glDrawPixels(invalid PBO access)");
+            return;
+         }
+         if (ctx->Unpack.BufferObj->Pointer) {
+            /* buffer is mapped - that's an error */
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glDrawPixels(PBO is mapped)");
+            return;
          }
-         src = stencilCopy;
       }
 
-      if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift
-          || ctx->Pixel.MapStencilFlag) {
+      ctx->Driver.DrawPixels(ctx, x, y, width, height, format, type,
+                            &ctx->Unpack, pixels);
+   }
+   else if (ctx->RenderMode == GL_FEEDBACK) {
+      /* Feedback the current raster pos info */
+      FLUSH_CURRENT( ctx, 0 );
+      FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
+      _mesa_feedback_vertex( ctx,
+                             ctx->Current.RasterPos,
+                             ctx->Current.RasterColor,
+                             ctx->Current.RasterIndex,
+                             ctx->Current.RasterTexCoords[0] );
+   }
+   else {
+      ASSERT(ctx->RenderMode == GL_SELECT);
+      /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
+   }
+}
 
-         /* make copy of stencil values */
-         if (src != stencilCopy)
-            MEMCPY( stencilCopy, src, width * sizeof(GLstencil));
 
-         /* apply shift and offset */
-         if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
-            gl_shift_and_offset_stencil( ctx, width, stencilCopy );
-         }
+void GLAPIENTRY
+_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
+                  GLenum type )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
-         /* mapping */
-         if (ctx->Pixel.MapStencilFlag) {
-            gl_map_stencil( ctx, width, stencilCopy );
-         }
+   if (ctx->NewState) {
+      _mesa_update_state(ctx);
+   }
 
-         stencilValues = stencilCopy;
-      }
-      else {
-         /* use stencil values in-place */
-         stencilValues = src;
-      }
+   if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glCopyPixels (invalid fragment program)");
+      return;
+   }
 
-      /* write stencil values to stencil buffer */
-      if (zoom) {
-         gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y,
-                                       stencilValues, desty );
-      }
-      else {
-         gl_write_stencil_span( ctx, (GLuint) width, x, y, stencilValues );
-      }
+   if (width < 0 || height < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glCopyPixels(width or height < 0)");
+      return;
    }
-}
 
+   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
+       ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                  "glCopyPixels(incomplete framebuffer)" );
+      return;
+   }
 
+   if (!_mesa_source_buffer_exists(ctx, type) ||
+       !_mesa_dest_buffer_exists(ctx, type)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glCopyPixels(missing source or dest buffer)");
+      return;
+   }
 
-/*
- * Do a glDrawPixels of depth values.
- */
-static void draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
-                               const struct gl_image *image )
-{
-   GLint width, height;
-   const GLint desty = y;
-   GLubyte rgba[MAX_WIDTH][4];
-   GLuint ispan[MAX_WIDTH];
-   const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
-   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
-
-   assert(image);
-   assert(image->Format == GL_DEPTH_COMPONENT);
-
-   width = image->Width;
-   height = image->Height;
-
-   /* Color or index */
-   if (ctx->Visual->RGBAflag) {
-      GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
-      GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
-      GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
-      GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
-      GLint i;
-      for (i=0; i<width; i++) {
-         rgba[i][RCOMP] = r;
-         rgba[i][GCOMP] = g;
-         rgba[i][BCOMP] = b;
-         rgba[i][ACOMP] = a;
-      }
+   if (!ctx->Current.RasterPosValid) {
+      return;
+   }
+
+   if (ctx->RenderMode == GL_RENDER) {
+      /* Round to satisfy conformance tests (matches SGI's OpenGL) */
+      GLint destx = IROUND(ctx->Current.RasterPos[0]);
+      GLint desty = IROUND(ctx->Current.RasterPos[1]);
+      ctx->Driver.CopyPixels( ctx, srcx, srcy, width, height, destx, desty,
+                             type );
+   }
+   else if (ctx->RenderMode == GL_FEEDBACK) {
+      FLUSH_CURRENT( ctx, 0 );
+      FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
+      _mesa_feedback_vertex( ctx, 
+                             ctx->Current.RasterPos,
+                             ctx->Current.RasterColor,
+                             ctx->Current.RasterIndex,
+                             ctx->Current.RasterTexCoords[0] );
    }
    else {
-      GLint i;
-      for (i=0;i<width;i++) {
-        ispan[i] = ctx->Current.RasterIndex;
-      }
+      ASSERT(ctx->RenderMode == GL_SELECT);
+      /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
    }
+}
 
-   if (image->Type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
-       && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
-      /* Special case: directly write 16-bit depth values */
-      GLint j;
-      for (j=0;j<height;j++,y++) {
-         GLdepth *zptr = (GLdepth *) image->Data + j * width;
-         gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
-      }
+#endif /* _HAVE_FULL_GL */
+
+
+
+void GLAPIENTRY
+_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
+                 GLenum format, GLenum type, GLvoid *pixels )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+   if (width < 0 || height < 0) {
+      _mesa_error( ctx, GL_INVALID_VALUE,
+                   "glReadPixels(width=%d height=%d)", width, height );
+      return;
    }
-   else if (image->Type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
-       && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
-      /* Special case: directly write 32-bit depth values */
-      GLint i, j;
-      /* 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++;
-      }
-      for (j=0;j<height;j++,y++) {
-         GLdepth zspan[MAX_WIDTH];
-         GLuint *zptr = (GLuint *) image->Data + j * width;
-         for (i=0;i<width;i++) {
-            zspan[i] = zptr[i] >> shift;
-         }
-         gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
-      }
+
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
+   if (error_check_format_type(ctx, format, type, GL_FALSE)) {
+      /* found an error */
+      return;
    }
-   else {
-      /* General case (slower) */
-      GLint i, j;
-
-      /* process image row by row */
-      for (i=0;i<height;i++,y++) {
-         GLfloat depth[MAX_WIDTH];
-         GLdepth zspan[MAX_WIDTH];
-
-         switch (image->Type) {
-            case GL_UNSIGNED_SHORT:
-               {
-                  GLushort *src = (GLushort *) image->Data + i * width;
-                  for (j=0;j<width;j++) {
-                     depth[j] = USHORT_TO_FLOAT( *src++ );
-                  }
-               }
-               break;
-            case GL_UNSIGNED_INT:
-               {
-                  GLuint *src = (GLuint *) image->Data + i * width;
-                  for (j=0;j<width;j++) {
-                     depth[j] = UINT_TO_FLOAT( *src++ );
-                  }
-               }
-               break;
-            case GL_FLOAT:
-               {
-                  GLfloat *src = (GLfloat *) image->Data + i * width;
-                  for (j=0;j<width;j++) {
-                     depth[j] = *src++;
-                  }
-               }
-               break;
-            default:
-               gl_problem(ctx, "Bad type in draw_depth_pixels");
-               return;
-         }
 
-         /* apply depth scale and bias */
-         if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) {
-            for (j=0;j<width;j++) {
-               depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
-            }
-         }
+   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                  "glReadPixels(incomplete framebuffer)" );
+      return;
+   }
 
-         /* clamp depth values to [0,1] and convert from floats to integers */
-         for (j=0;j<width;j++) {
-            zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE);
-         }
+   if (!_mesa_source_buffer_exists(ctx, format)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
+      return;
+   }
 
-         if (ctx->Visual->RGBAflag) {
-            if (zoom) {
-               gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
-                                          (const GLubyte (*)[4])rgba, desty );
-            }
-            else {
-               gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
-            }
-         }
-         else {
-            if (zoom) {
-               gl_write_zoomed_index_span( ctx, width, x, y, zspan,
-                                           ispan, GL_BITMAP );
-            }
-            else {
-               gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
-            }
-         }
+   if (ctx->Pack.BufferObj->Name) {
+      if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
+                                     format, type, pixels)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "glReadPixels(invalid PBO access)");
+         return;
+      }
 
+      if (ctx->Pack.BufferObj->Pointer) {
+         /* buffer is mapped - that's an error */
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
+         return;
       }
    }
-}
-
 
+   ctx->Driver.ReadPixels(ctx, x, y, width, height,
+                         format, type, &ctx->Pack, pixels);
+}
 
-/* Simple unpacking parameters: */
-static struct gl_pixelstore_attrib NoUnpack = {
-   1,            /* Alignment */
-   0,            /* RowLength */
-   0,            /* SkipPixels */
-   0,            /* SkipRows */
-   0,            /* ImageHeight */
-   0,            /* SkipImages */
-   GL_FALSE,     /* SwapBytes */
-   GL_FALSE      /* LsbFirst */
-};
 
 
-/*
- * Do glDrawPixels of RGBA pixels.
- */
-static void draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
-                              const struct gl_image *image )
+void GLAPIENTRY
+_mesa_Bitmap( GLsizei width, GLsizei height,
+              GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+              const GLubyte *bitmap )
 {
-   GLint width, height;
-   GLint i, j;
-   const GLint desty = y;
-   GLdepth zspan[MAX_WIDTH];
-   GLboolean quickDraw;
-   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
-
-   assert(image);
-
-   /* Try an optimized glDrawPixels first */
-   if (gl_direct_DrawPixels(ctx, &NoUnpack, image->Width, image->Height,
-                            image->Format, image->Type, image->Data ))
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+   if (width < 0 || height < 0) {
+      _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
       return;
+   }
 
-   width = image->Width;
-   height = image->Height;
+   if (!ctx->Current.RasterPosValid) {
+      return;    /* do nothing */
+   }
 
-   /* Fragment depth values */
-   if (ctx->Depth.Test) {
-      /* fill in array of z values */
-      GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
-      for (i=0;i<width;i++) {
-        zspan[i] = z;
-      }
+   if (ctx->NewState) {
+      _mesa_update_state(ctx);
    }
 
-   if (ctx->RasterMask==0 && !zoom && x>=0 && y>=0
-       && x+width<=ctx->Buffer->Width && y+height<=ctx->Buffer->Height) {
-      quickDraw = GL_TRUE;
+   if (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "glBitmap (invalid fragment program)");
+      return;
    }
-   else {
-      quickDraw = GL_FALSE;
-   }
-
-   {
-      /* General solution */
-      GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
-      GLuint components;
-      GLubyte rgba[MAX_WIDTH][4];
-      GLfloat  rf[MAX_WIDTH];
-      GLfloat  gf[MAX_WIDTH];
-      GLfloat  bf[MAX_WIDTH];
-      DEFARRAY(GLfloat,af,MAX_WIDTH);
-      CHECKARRAY(af,return);
-
-      r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
-      switch (image->Format) {
-        case GL_RED:
-           r_flag = GL_TRUE;
-           components = 1;
-           break;
-        case GL_GREEN:
-           g_flag = GL_TRUE;
-           components = 1;
-           break;
-        case GL_BLUE:
-           b_flag = GL_TRUE;
-           components = 1;
-           break;
-        case GL_ALPHA:
-           a_flag = GL_TRUE;
-           components = 1;
-           break;
-        case GL_RGB:
-           r_flag = g_flag = b_flag = GL_TRUE;
-           components = 3;
-           break;
-        case GL_LUMINANCE:
-           l_flag = GL_TRUE;
-           components = 1;
-           break;
-        case GL_LUMINANCE_ALPHA:
-           l_flag = a_flag = GL_TRUE;
-           components = 2;
-           break;
-        case GL_RGBA:
-           r_flag = g_flag = b_flag = a_flag = GL_TRUE;
-           components = 4;
-           break;
-         default:
-            gl_problem(ctx, "Bad type in draw_rgba_pixels");
-            goto cleanup;
-      }
 
-      /* process the image row by row */
-      for (i=0;i<height;i++,y++) {
-        /* convert to floats */
-        switch (image->Type) {
-           case GL_UNSIGNED_BYTE:
-              {
-                 GLubyte *src = (GLubyte *) image->Data + i * width * components;
-                 for (j=0;j<width;j++) {
-                    if (l_flag) {
-                       rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++);
-                    }
-                    else {
-                       rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
-                       gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
-                       bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
-                    }
-                    af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0;
-                 }
-              }
-              break;
-           case GL_FLOAT:
-              {
-                 GLfloat *src = (GLfloat *) image->Data + i * width * components;
-                 for (j=0;j<width;j++) {
-                    if (l_flag) {
-                       rf[j] = gf[j] = bf[j] = *src++;
-                    }
-                    else {
-                       rf[j] = r_flag ? *src++ : 0.0;
-                       gf[j] = g_flag ? *src++ : 0.0;
-                       bf[j] = b_flag ? *src++ : 0.0;
-                    }
-                    af[j] = a_flag ? *src++ : 1.0;
-                 }
-              }
-              break;
-           default:
-              gl_problem( ctx, "draw_rgba_pixels type" );
-               goto cleanup;
-        }
-
-        /* apply scale and bias */
-        if (ctx->Pixel.ScaleOrBiasRGBA) {
-            gl_scale_and_bias_color(ctx, width, rf, gf, bf, af);
-        }
-
-        /* apply pixel mappings */
-        if (ctx->Pixel.MapColorFlag) {
-            gl_map_color(ctx, width, rf, gf, bf, af);
-        }
-
-        /* convert to integers */
-        for (j=0;j<width;j++) {
-           rgba[j][RCOMP] = (GLint) (rf[j] * 255.0F);
-           rgba[j][GCOMP] = (GLint) (gf[j] * 255.0F);
-           rgba[j][BCOMP] = (GLint) (bf[j] * 255.0F);
-           rgba[j][ACOMP] = (GLint) (af[j] * 255.0F);
-        }
-
-        /* write to frame buffer */
-         if (quickDraw) {
-            (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y, 
-                                         (const GLubyte (*)[4])rgba, NULL);
-         }
-         else if (zoom) {
-            gl_write_zoomed_rgba_span( ctx, width, x, y, zspan, 
-                                      (const GLubyte (*)[4])rgba, desty );
+   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                  "glBitmap(incomplete framebuffer)");
+      return;
+   }
+
+   if (ctx->RenderMode == GL_RENDER) {
+      /* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
+      const GLfloat epsilon = 0.0001;
+      GLint x = IFLOOR(ctx->Current.RasterPos[0] + epsilon - xorig);
+      GLint y = IFLOOR(ctx->Current.RasterPos[1] + epsilon - yorig);
+
+      if (ctx->Unpack.BufferObj->Name) {
+         /* unpack from PBO */
+         if (!_mesa_validate_pbo_access(2, &ctx->Unpack, width, height, 1,
+                                        GL_COLOR_INDEX, GL_BITMAP,
+                                        (GLvoid *) bitmap)) {
+            _mesa_error(ctx, GL_INVALID_OPERATION,
+                        "glBitmap(invalid PBO access)");
+            return;
          }
-         else {
-            gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
+         if (ctx->Unpack.BufferObj->Pointer) {
+            /* buffer is mapped - that's an error */
+            _mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)");
+            return;
          }
       }
-cleanup:
-      UNDEFARRAY(af);
+
+      ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
+   }
+#if _HAVE_FULL_GL
+   else if (ctx->RenderMode == GL_FEEDBACK) {
+      FLUSH_CURRENT(ctx, 0);
+      FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_BITMAP_TOKEN );
+      _mesa_feedback_vertex( ctx,
+                             ctx->Current.RasterPos,
+                             ctx->Current.RasterColor,
+                             ctx->Current.RasterIndex, 
+                             ctx->Current.RasterTexCoords[0] );
    }
+   else {
+      ASSERT(ctx->RenderMode == GL_SELECT);
+      /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
+   }
+#endif
+
+   /* update raster position */
+   ctx->Current.RasterPos[0] += xmove;
+   ctx->Current.RasterPos[1] += ymove;
 }
 
 
 
+#if 0  /* experimental */
 /*
- * Execute glDrawPixels
+ * Execute glDrawDepthPixelsMESA().  This function accepts both a color
+ * image and depth (Z) image.  Rasterization produces fragments with
+ * color and Z taken from these images.  This function is intended for
+ * Z-compositing.  Normally, this operation requires two glDrawPixels
+ * calls with stencil testing.
  */
-void gl_DrawPixels( GLcontext* ctx, struct gl_image *image )
+void GLAPIENTRY
+_mesa_DrawDepthPixelsMESA( GLsizei width, GLsizei height,
+                           GLenum colorFormat, GLenum colorType,
+                           const GLvoid *colors,
+                           GLenum depthType, const GLvoid *depths )
 {
-   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels");
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
+   if (width < 0 || height < 0) {
+      _mesa_error( ctx, GL_INVALID_VALUE,
+                   "glDrawDepthPixelsMESA(width or height < 0" );
+      return;
+   }
 
-   if (gl_image_error_test( ctx, image, "glDrawPixels" ))
+   if (!ctx->Current.RasterPosValid) {
       return;
+   }
 
-   if (ctx->RenderMode==GL_RENDER) {
-      GLint x, y;
-      if (!ctx->Current.RasterPosValid) {
-        return;
-      }
+   if (ctx->NewState) {
+      _mesa_update_state(ctx);
+   }
 
-      x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
-      y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
-
-      switch (image->Format) {
-        case GL_COLOR_INDEX:
-            draw_index_pixels( ctx, x, y, image );
-           break;
-        case GL_STENCIL_INDEX:
-           draw_stencil_pixels( ctx, x, y, image );
-           break;
-        case GL_DEPTH_COMPONENT:
-           draw_depth_pixels( ctx, x, y, image );
-           break;
-        case GL_RED:
-        case GL_GREEN:
-        case GL_BLUE:
-        case GL_ALPHA:
-        case GL_RGB:
-        case GL_LUMINANCE:
-        case GL_LUMINANCE_ALPHA:
-        case GL_RGBA:
-            draw_rgba_pixels( ctx, x, y, image );
-           break;
-        default:
-           gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" );
-            return;
-      }
+   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                  "glDrawDepthPixelsMESA(incomplete framebuffer)");
+      return;
+   }
+
+   if (ctx->RenderMode == GL_RENDER) {
+      /* Round, to satisfy conformance tests (matches SGI's OpenGL) */
+      GLint x = IROUND(ctx->Current.RasterPos[0]);
+      GLint y = IROUND(ctx->Current.RasterPos[1]);
+      ctx->Driver.DrawDepthPixelsMESA(ctx, x, y, width, height,
+                                      colorFormat, colorType, colors,
+                                      depthType, depths, &ctx->Unpack);
    }
-   else if (ctx->RenderMode==GL_FEEDBACK) {
-      if (ctx->Current.RasterPosValid) {
-         GLfloat color[4];
-        GLfloat texcoord[4], invq;
-        UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor);
-         invq = 1.0F / ctx->Current.Texcoord[0][3];
-         texcoord[0] = ctx->Current.Texcoord[0][0] * invq;
-         texcoord[1] = ctx->Current.Texcoord[0][1] * invq;
-         texcoord[2] = ctx->Current.Texcoord[0][2] * invq;
-         texcoord[3] = ctx->Current.Texcoord[0][3];
-         FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
-         gl_feedback_vertex( ctx,
+   else if (ctx->RenderMode == GL_FEEDBACK) {
+      /* Feedback the current raster pos info */
+      FLUSH_CURRENT( ctx, 0 );
+      FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
+      _mesa_feedback_vertex( ctx,
                              ctx->Current.RasterPos,
-                             color, ctx->Current.Index, texcoord );
-      }
+                             ctx->Current.RasterColor,
+                             ctx->Current.RasterIndex,
+                             ctx->Current.RasterTexCoords[0] );
    }
-   else if (ctx->RenderMode==GL_SELECT) {
-      if (ctx->Current.RasterPosValid) {
-         gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
-      }
+   else {
+      ASSERT(ctx->RenderMode == GL_SELECT);
+      /* Do nothing.  See OpenGL Spec, Appendix B, Corollary 6. */
    }
 }
 
+#endif