mesa: add _mesa_program_state_value_size() helper
[mesa.git] / src / mesa / swrast / s_drawpix.c
index 248d6cc1c0456c183b931d4d697d9651eb446a54..31c6a6a971a7d52ad769349ef984e7205653ac09 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Mesa 3-D graphics library
- * Version:  7.1
  *
  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * 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
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 
 #include "main/glheader.h"
 #include "main/bufferobj.h"
+#include "main/colormac.h"
 #include "main/condrender.h"
 #include "main/context.h"
-#include "main/convolve.h"
+#include "main/format_pack.h"
+#include "main/format_utils.h"
+#include "main/glformats.h"
 #include "main/image.h"
+
 #include "main/macros.h"
-#include "main/imports.h"
+#include "main/pack.h"
+#include "main/pbo.h"
+#include "main/pixeltransfer.h"
 #include "main/state.h"
 
 #include "s_context.h"
 #include "s_zoom.h"
 
 
+/**
+ * Handle a common case of drawing GL_RGB/GL_UNSIGNED_BYTE into a
+ * MESA_FORMAT_XRGB888 or MESA_FORMAT_ARGB888 renderbuffer.
+ */
+static void
+fast_draw_rgb_ubyte_pixels(struct gl_context *ctx,
+                           struct gl_renderbuffer *rb,
+                           GLint x, GLint y,
+                           GLsizei width, GLsizei height,
+                           const struct gl_pixelstore_attrib *unpack,
+                           const GLvoid *pixels,
+                           bool flip_y)
+{
+   const GLubyte *src = (const GLubyte *)
+      _mesa_image_address2d(unpack, pixels, width,
+                            height, GL_RGB, GL_UNSIGNED_BYTE, 0, 0);
+   const GLint srcRowStride = _mesa_image_row_stride(unpack, width,
+                                                     GL_RGB, GL_UNSIGNED_BYTE);
+   GLint i, j;
+   GLubyte *dst;
+   GLint dstRowStride;
+
+   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
+                               GL_MAP_WRITE_BIT, &dst, &dstRowStride,
+                               flip_y);
+
+   if (!dst) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+      return;
+   }
+
+   if (ctx->Pixel.ZoomY == -1.0f) {
+      dst = dst + (height - 1) * dstRowStride;
+      dstRowStride = -dstRowStride;
+   }
+
+   for (i = 0; i < height; i++) {
+      GLuint *dst4 = (GLuint *) dst;
+      for (j = 0; j < width; j++) {
+         dst4[j] = PACK_COLOR_8888(0xff, src[j*3+0], src[j*3+1], src[j*3+2]);
+      }
+      dst += dstRowStride;
+      src += srcRowStride;
+   }
+
+   ctx->Driver.UnmapRenderbuffer(ctx, rb);
+}
+
+
+/**
+ * Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a
+ * MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer.
+ */
+static void
+fast_draw_rgba_ubyte_pixels(struct gl_context *ctx,
+                           struct gl_renderbuffer *rb,
+                           GLint x, GLint y,
+                           GLsizei width, GLsizei height,
+                           const struct gl_pixelstore_attrib *unpack,
+                           const GLvoid *pixels,
+                           bool flip_y)
+{
+   const GLubyte *src = (const GLubyte *)
+      _mesa_image_address2d(unpack, pixels, width,
+                            height, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
+   const GLint srcRowStride =
+      _mesa_image_row_stride(unpack, width, GL_RGBA, GL_UNSIGNED_BYTE);
+   GLint i, j;
+   GLubyte *dst;
+   GLint dstRowStride;
+
+   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
+                               GL_MAP_WRITE_BIT, &dst, &dstRowStride,
+                               flip_y);
+
+   if (!dst) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+      return;
+   }
+
+   if (ctx->Pixel.ZoomY == -1.0f) {
+      dst = dst + (height - 1) * dstRowStride;
+      dstRowStride = -dstRowStride;
+   }
+
+   for (i = 0; i < height; i++) {
+      GLuint *dst4 = (GLuint *) dst;
+      for (j = 0; j < width; j++) {
+         dst4[j] = PACK_COLOR_8888(src[j*4+3], src[j*4+0],
+                                   src[j*4+1], src[j*4+2]);
+      }
+      dst += dstRowStride;
+      src += srcRowStride;
+   }
+
+   ctx->Driver.UnmapRenderbuffer(ctx, rb);
+}
+
+
+/**
+ * Handle a common case of drawing a format/type combination that
+ * exactly matches the renderbuffer format.
+ */
+static void
+fast_draw_generic_pixels(struct gl_context *ctx,
+                         struct gl_renderbuffer *rb,
+                         GLint x, GLint y,
+                         GLsizei width, GLsizei height,
+                         GLenum format, GLenum type,
+                         const struct gl_pixelstore_attrib *unpack,
+                         const GLvoid *pixels,
+                         bool flip_y)
+{
+   const GLubyte *src = (const GLubyte *)
+      _mesa_image_address2d(unpack, pixels, width,
+                            height, format, type, 0, 0);
+   const GLint srcRowStride =
+      _mesa_image_row_stride(unpack, width, format, type);
+   const GLint rowLength = width * _mesa_get_format_bytes(rb->Format);
+   GLint i;
+   GLubyte *dst;
+   GLint dstRowStride;
+
+   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
+                               GL_MAP_WRITE_BIT, &dst, &dstRowStride,
+                               flip_y);
+
+   if (!dst) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+      return;
+   }
+
+   if (ctx->Pixel.ZoomY == -1.0f) {
+      dst = dst + (height - 1) * dstRowStride;
+      dstRowStride = -dstRowStride;
+   }
+
+   for (i = 0; i < height; i++) {
+      memcpy(dst, src, rowLength);
+      dst += dstRowStride;
+      src += srcRowStride;
+   }
+
+   ctx->Driver.UnmapRenderbuffer(ctx, rb);
+}
+
 
 /**
  * Try to do a fast and simple RGB(a) glDrawPixels.
  * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
  */
 static GLboolean
-fast_draw_rgba_pixels(GLcontext *ctx, GLint x, GLint y,
+fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
                       GLsizei width, GLsizei height,
                       GLenum format, GLenum type,
                       const struct gl_pixelstore_attrib *userUnpack,
                       const GLvoid *pixels)
 {
-   const GLint imgX = x, imgY = y;
+   struct gl_framebuffer *fb = ctx->DrawBuffer;
    struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-   GLenum rbType;
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   SWspan span;
-   GLboolean simpleZoom;
-   GLint yStep;  /* +1 or -1 */
    struct gl_pixelstore_attrib unpack;
-   GLint destX, destY, drawWidth, drawHeight; /* post clipping */
 
    if (!rb)
       return GL_TRUE; /* no-op */
 
-   rbType = rb->DataType;
-
-   if ((swrast->_RasterMask & ~CLIP_BIT) ||
+   if (ctx->DrawBuffer->_NumColorDrawBuffers > 1 ||
+       (swrast->_RasterMask & ~CLIP_BIT) ||
        ctx->Texture._EnabledCoordUnits ||
        userUnpack->SwapBytes ||
+       ctx->Pixel.ZoomX != 1.0f ||
+       fabsf(ctx->Pixel.ZoomY) != 1.0f ||
        ctx->_ImageTransferState) {
       /* can't handle any of those conditions */
       return GL_FALSE;
    }
 
-   INIT_SPAN(span, GL_BITMAP);
-   span.arrayMask = SPAN_RGBA;
-   span.arrayAttribs = FRAG_BIT_COL0;
-   _swrast_span_default_attribs(ctx, &span);
-
-   /* copy input params since clipping may change them */
    unpack = *userUnpack;
-   destX = x;
-   destY = y;
-   drawWidth = width;
-   drawHeight = height;
-
-   /* check for simple zooming and clipping */
-   if (ctx->Pixel.ZoomX == 1.0F &&
-       (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F)) {
-      if (!_mesa_clip_drawpixels(ctx, &destX, &destY,
-                                 &drawWidth, &drawHeight, &unpack)) {
-         /* image was completely clipped: no-op, all done */
-         return GL_TRUE;
-      }
-      simpleZoom = GL_TRUE;
-      yStep = (GLint) ctx->Pixel.ZoomY;
-      ASSERT(yStep == 1 || yStep == -1);
-   }
-   else {
-      /* non-simple zooming */
-      simpleZoom = GL_FALSE;
-      yStep = 1;
-      if (unpack.RowLength == 0)
-         unpack.RowLength = width;
-   }
-
-   /*
-    * Ready to draw!
-    */
 
-   if (format == GL_RGBA && type == rbType) {
-      const GLubyte *src
-         = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
-                                                   height, format, type, 0, 0);
-      const GLint srcStride = _mesa_image_row_stride(&unpack, width,
-                                                     format, type);
-      if (simpleZoom) {
-         GLint row;
-         for (row = 0; row < drawHeight; row++) {
-            rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL);
-            src += srcStride;
-            destY += yStep;
-         }
-      }
-      else {
-         /* with zooming */
-         GLint row;
-         for (row = 0; row < drawHeight; row++) {
-            span.x = destX;
-            span.y = destY + row;
-            span.end = drawWidth;
-            span.array->ChanType = rbType;
-            _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src);
-            src += srcStride;
-         }
-         span.array->ChanType = CHAN_TYPE;
-      }
+   /* clipping */
+   if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &unpack)) {
+      /* image was completely clipped: no-op, all done */
       return GL_TRUE;
    }
 
-   if (format == GL_RGB && type == rbType) {
-      const GLubyte *src
-         = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
-                                                   height, format, type, 0, 0);
-      const GLint srcStride = _mesa_image_row_stride(&unpack, width,
-                                                     format, type);
-      if (simpleZoom) {
-         GLint row;
-         for (row = 0; row < drawHeight; row++) {
-            rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL);
-            src += srcStride;
-            destY += yStep;
-         }
-      }
-      else {
-         /* with zooming */
-         GLint row;
-         for (row = 0; row < drawHeight; row++) {
-            span.x = destX;
-            span.y = destY;
-            span.end = drawWidth;
-            span.array->ChanType = rbType;
-            _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src);
-            src += srcStride;
-            destY++;
-         }
-         span.array->ChanType = CHAN_TYPE;
-      }
+   if (format == GL_RGB &&
+       type == GL_UNSIGNED_BYTE &&
+       (rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
+        rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
+      fast_draw_rgb_ubyte_pixels(ctx, rb, x, y, width, height,
+                                 &unpack, pixels, fb->FlipY);
       return GL_TRUE;
    }
 
-   /* Remaining cases haven't been tested with alignment != 1 */
-   if (userUnpack->Alignment != 1)
-      return GL_FALSE;
-
-   if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) {
-      const GLchan *src = (const GLchan *) pixels
-         + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels);
-      if (simpleZoom) {
-         /* no zooming */
-         GLint row;
-         ASSERT(drawWidth <= MAX_WIDTH);
-         for (row = 0; row < drawHeight; row++) {
-            GLchan rgb[MAX_WIDTH][3];
-            GLint i;
-            for (i = 0;i<drawWidth;i++) {
-               rgb[i][0] = src[i];
-               rgb[i][1] = src[i];
-               rgb[i][2] = src[i];
-            }
-            rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL);
-            src += unpack.RowLength;
-            destY += yStep;
-         }
-      }
-      else {
-         /* with zooming */
-         GLint row;
-         ASSERT(drawWidth <= MAX_WIDTH);
-         for (row = 0; row < drawHeight; row++) {
-            GLchan rgb[MAX_WIDTH][3];
-            GLint i;
-            for (i = 0;i<drawWidth;i++) {
-               rgb[i][0] = src[i];
-               rgb[i][1] = src[i];
-               rgb[i][2] = src[i];
-            }
-            span.x = destX;
-            span.y = destY;
-            span.end = drawWidth;
-            _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, rgb);
-            src += unpack.RowLength;
-            destY++;
-         }
-      }
+   if (format == GL_RGBA &&
+       type == GL_UNSIGNED_BYTE &&
+       (rb->Format == MESA_FORMAT_B8G8R8X8_UNORM ||
+        rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) {
+      fast_draw_rgba_ubyte_pixels(ctx, rb, x, y, width, height,
+                                  &unpack, pixels, fb->FlipY);
       return GL_TRUE;
    }
 
-   if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE && rbType == CHAN_TYPE) {
-      const GLchan *src = (const GLchan *) pixels
-         + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels)*2;
-      if (simpleZoom) {
-         GLint row;
-         ASSERT(drawWidth <= MAX_WIDTH);
-         for (row = 0; row < drawHeight; row++) {
-            GLint i;
-            const GLchan *ptr = src;
-            for (i = 0;i<drawWidth;i++) {
-               span.array->rgba[i][0] = *ptr;
-               span.array->rgba[i][1] = *ptr;
-               span.array->rgba[i][2] = *ptr++;
-               span.array->rgba[i][3] = *ptr++;
-            }
-            rb->PutRow(ctx, rb, drawWidth, destX, destY,
-                       span.array->rgba, NULL);
-            src += unpack.RowLength*2;
-            destY += yStep;
-         }
-      }
-      else {
-         /* with zooming */
-         GLint row;
-         ASSERT(drawWidth <= MAX_WIDTH);
-         for (row = 0; row < drawHeight; row++) {
-            const GLchan *ptr = src;
-            GLint i;
-            for (i = 0;i<drawWidth;i++) {
-               span.array->rgba[i][0] = *ptr;
-               span.array->rgba[i][1] = *ptr;
-               span.array->rgba[i][2] = *ptr++;
-               span.array->rgba[i][3] = *ptr++;
-            }
-            span.x = destX;
-            span.y = destY;
-            span.end = drawWidth;
-            _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
-                                           span.array->rgba);
-            src += unpack.RowLength*2;
-            destY++;
-         }
-      }
+   if (_mesa_format_matches_format_and_type(rb->Format, format, type,
+                                            ctx->Unpack.SwapBytes, NULL)) {
+      fast_draw_generic_pixels(ctx, rb, x, y, width, height,
+                               format, type, &unpack, pixels,
+                               fb->FlipY);
       return GL_TRUE;
    }
 
-   if (format == GL_COLOR_INDEX && type == GL_UNSIGNED_BYTE) {
-      const GLubyte *src = (const GLubyte *) pixels
-         + unpack.SkipRows * unpack.RowLength + unpack.SkipPixels;
-      if (ctx->Visual.rgbMode && rbType == GL_UNSIGNED_BYTE) {
-         /* convert ubyte/CI data to ubyte/RGBA */
-         if (simpleZoom) {
-            GLint row;
-            for (row = 0; row < drawHeight; row++) {
-               ASSERT(drawWidth <= MAX_WIDTH);
-               _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
-                                      span.array->rgba8);
-               rb->PutRow(ctx, rb, drawWidth, destX, destY,
-                          span.array->rgba8, NULL);
-               src += unpack.RowLength;
-               destY += yStep;
-            }
-         }
-         else {
-            /* ubyte/CI to ubyte/RGBA with zooming */
-            GLint row;
-            for (row = 0; row < drawHeight; row++) {
-               ASSERT(drawWidth <= MAX_WIDTH);
-               _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
-                                      span.array->rgba8);
-               span.x = destX;
-               span.y = destY;
-               span.end = drawWidth;
-               _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
-                                              span.array->rgba8);
-               src += unpack.RowLength;
-               destY++;
-            }
-         }
-         return GL_TRUE;
-      }
-      else if (!ctx->Visual.rgbMode && rbType == GL_UNSIGNED_INT) {
-         /* write CI data to CI frame buffer */
-         GLint row;
-         if (simpleZoom) {
-            for (row = 0; row < drawHeight; row++) {
-               GLuint index32[MAX_WIDTH];
-               GLint col;
-               for (col = 0; col < drawWidth; col++)
-                  index32[col] = src[col];
-               rb->PutRow(ctx, rb, drawWidth, destX, destY, index32, NULL);
-               src += unpack.RowLength;
-               destY += yStep;
-            }
-            return GL_TRUE;
-         }
-      }
-   }
-
    /* can't handle this pixel format and/or data type */
    return GL_FALSE;
 }
 
 
 
-/*
- * Draw color index image.
- */
-static void
-draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
-                   GLsizei width, GLsizei height,
-                   GLenum type,
-                   const struct gl_pixelstore_attrib *unpack,
-                   const GLvoid *pixels )
-{
-   const GLint imgX = x, imgY = y;
-   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
-   GLint row, skipPixels;
-   SWspan span;
-
-   INIT_SPAN(span, GL_BITMAP);
-   span.arrayMask = SPAN_INDEX;
-   _swrast_span_default_attribs(ctx, &span);
-
-   /*
-    * General solution
-    */
-   skipPixels = 0;
-   while (skipPixels < width) {
-      const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
-      ASSERT(spanWidth <= MAX_WIDTH);
-      for (row = 0; row < height; row++) {
-         const GLvoid *source = _mesa_image_address2d(unpack, pixels,
-                                                      width, height,
-                                                      GL_COLOR_INDEX, type,
-                                                      row, skipPixels);
-         _mesa_unpack_index_span(ctx, spanWidth, GL_UNSIGNED_INT,
-                                 span.array->index, type, source, unpack,
-                                 ctx->_ImageTransferState);
-
-         /* These may get changed during writing/clipping */
-         span.x = x + skipPixels;
-         span.y = y + row;
-         span.end = spanWidth;
-         
-         if (zoom)
-            _swrast_write_zoomed_index_span(ctx, imgX, imgY, &span);
-         else
-            _swrast_write_index_span(ctx, &span);
-      }
-      skipPixels += spanWidth;
-   }
-}
-
-
-
 /*
  * Draw stencil image.
  */
 static void
-draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
+draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y,
                      GLsizei width, GLsizei height,
                      GLenum type,
                      const struct gl_pixelstore_attrib *unpack,
                      const GLvoid *pixels )
 {
-   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
-   GLint skipPixels;
-
-   /* if width > MAX_WIDTH, have to process image in chunks */
-   skipPixels = 0;
-   while (skipPixels < width) {
-      const GLint spanX = x + skipPixels;
-      const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
-      GLint row;
-      for (row = 0; row < height; row++) {
-         const GLint spanY = y + row;
-         GLstencil values[MAX_WIDTH];
-         GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
-                         ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
-         const GLvoid *source = _mesa_image_address2d(unpack, pixels,
-                                                      width, height,
-                                                      GL_COLOR_INDEX, type,
-                                                      row, skipPixels);
-         _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
-                                   type, source, unpack,
-                                   ctx->_ImageTransferState);
-         if (zoom) {
-            _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
-                                              spanX, spanY, values);
-         }
-         else {
-            _swrast_write_stencil_span(ctx, spanWidth, spanX, spanY, values);
-         }
+   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
+   const GLenum destType = GL_UNSIGNED_BYTE;
+   GLint row;
+   GLubyte *values;
+
+   values = malloc(width * sizeof(GLubyte));
+   if (!values) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+      return;
+   }
+
+   for (row = 0; row < height; row++) {
+      const GLvoid *source = _mesa_image_address2d(unpack, pixels,
+                                                   width, height,
+                                                   GL_STENCIL_INDEX, type,
+                                                   row, 0);
+      _mesa_unpack_stencil_span(ctx, width, destType, values,
+                                type, source, unpack,
+                                ctx->_ImageTransferState);
+      if (zoom) {
+         _swrast_write_zoomed_stencil_span(ctx, x, y, width,
+                                           x, y, values);
+      }
+      else {
+         _swrast_write_stencil_span(ctx, width, x, y, values);
       }
-      skipPixels += spanWidth;
+
+      y++;
    }
+
+   free(values);
 }
 
 
@@ -422,15 +310,15 @@ draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
  * Draw depth image.
  */
 static void
-draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
+draw_depth_pixels( struct gl_context *ctx, GLint x, GLint y,
                    GLsizei width, GLsizei height,
                    GLenum type,
                    const struct gl_pixelstore_attrib *unpack,
                    const GLvoid *pixels )
 {
    const GLboolean scaleOrBias
-      = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
-   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
+      = ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
+   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0f || ctx->Pixel.ZoomY != 1.0f;
    SWspan span;
 
    INIT_SPAN(span, GL_BITMAP);
@@ -441,8 +329,7 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
        && ctx->DrawBuffer->Visual.depthBits == 16
        && !scaleOrBias
        && !zoom
-       && ctx->Visual.rgbMode
-       && width <= MAX_WIDTH
+       && width <= SWRAST_MAX_WIDTH
        && !unpack->SwapBytes) {
       /* Special case: directly write 16-bit depth values */
       GLint row;
@@ -462,8 +349,7 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
    else if (type == GL_UNSIGNED_INT
             && !scaleOrBias
             && !zoom
-            && ctx->Visual.rgbMode
-            && width <= MAX_WIDTH
+            && width <= SWRAST_MAX_WIDTH
             && !unpack->SwapBytes) {
       /* Special case: shift 32-bit values down to Visual.depthBits */
       const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits;
@@ -473,7 +359,7 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
             _mesa_image_address2d(unpack, pixels, width, height,
                                   GL_DEPTH_COMPONENT, type, row, 0);
          if (shift == 0) {
-            _mesa_memcpy(span.array->z, zSrc, width * sizeof(GLuint));
+            memcpy(span.array->z, zSrc, width * sizeof(GLuint));
          }
          else {
             GLint col;
@@ -491,11 +377,11 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
       const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
       GLint skipPixels = 0;
 
-      /* in case width > MAX_WIDTH do the copy in chunks */
+      /* in case width > SWRAST_MAX_WIDTH do the copy in chunks */
       while (skipPixels < width) {
-         const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
+         const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
          GLint row;
-         ASSERT(span.end <= MAX_WIDTH);
+         assert(span.end <= SWRAST_MAX_WIDTH);
          for (row = 0; row < height; row++) {
             const GLvoid *zSrc = _mesa_image_address2d(unpack,
                                                       pixels, width, height,
@@ -515,11 +401,8 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
             if (zoom) {
                _swrast_write_zoomed_depth_span(ctx, x, y, &span);
             }
-            else if (ctx->Visual.rgbMode) {
-               _swrast_write_rgba_span(ctx, &span);
-            }
             else {
-               _swrast_write_index_span(ctx, &span);
+               _swrast_write_rgba_span(ctx, &span);
             }
          }
          skipPixels += spanWidth;
@@ -533,15 +416,14 @@ draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
  * Draw RGBA image.
  */
 static void
-draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
+draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y,
                   GLsizei width, GLsizei height,
                   GLenum format, GLenum type,
                   const struct gl_pixelstore_attrib *unpack,
                   const GLvoid *pixels )
 {
    const GLint imgX = x, imgY = y;
-   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
-   GLfloat *convImage = NULL;
+   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
    GLbitfield transferOps = ctx->_ImageTransferState;
    SWspan span;
 
@@ -551,120 +433,113 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
       return;
    }
 
+   swrast_render_start(ctx);
+
    INIT_SPAN(span, GL_BITMAP);
    _swrast_span_default_attribs(ctx, &span);
    span.arrayMask = SPAN_RGBA;
-   span.arrayAttribs = FRAG_BIT_COL0; /* we're fill in COL0 attrib values */
-
-   if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
-      /* Convolution has to be handled specially.  We'll create an
-       * intermediate image, applying all pixel transfer operations
-       * up to convolution.  Then we'll convolve the image.  Then
-       * we'll proceed with the rest of the transfer operations and
-       * rasterize the image.
-       */
-      GLint row;
-      GLfloat *dest, *tmpImage;
-
-      tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
-      if (!tmpImage) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
-         return;
-      }
-      convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
-      if (!convImage) {
-         _mesa_free(tmpImage);
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
-         return;
-      }
-
-      /* Unpack the image and apply transfer ops up to convolution */
-      dest = tmpImage;
-      for (row = 0; row < height; row++) {
-         const GLvoid *source = _mesa_image_address2d(unpack,
-                                  pixels, width, height, format, type, row, 0);
-         _mesa_unpack_color_span_float(ctx, width, GL_RGBA, (GLfloat *) dest,
-                                     format, type, source, unpack,
-                                     transferOps & IMAGE_PRE_CONVOLUTION_BITS);
-         dest += width * 4;
-      }
-
-      /* do convolution */
-      if (ctx->Pixel.Convolution2DEnabled) {
-         _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
+   span.arrayAttribs = VARYING_BIT_COL0; /* we're fill in COL0 attrib values */
+
+   if (ctx->DrawBuffer->_NumColorDrawBuffers > 0) {
+      GLenum datatype = _mesa_get_format_datatype(
+                 ctx->DrawBuffer->_ColorDrawBuffers[0]->Format);
+      if (datatype != GL_FLOAT &&
+          ctx->Color.ClampFragmentColor != GL_FALSE) {
+         /* need to clamp colors before applying fragment ops */
+         transferOps |= IMAGE_CLAMP_BIT;
       }
-      else {
-         ASSERT(ctx->Pixel.Separable2DEnabled);
-         _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
-      }
-      _mesa_free(tmpImage);
-
-      /* continue transfer ops and draw the convolved image */
-      unpack = &ctx->DefaultPacking;
-      pixels = convImage;
-      format = GL_RGBA;
-      type = GL_FLOAT;
-      transferOps &= IMAGE_POST_CONVOLUTION_BITS;
-   }
-   else if (ctx->Pixel.Convolution1DEnabled) {
-      /* we only want to apply 1D convolution to glTexImage1D */
-      transferOps &= ~(IMAGE_CONVOLUTION_BIT |
-                       IMAGE_POST_CONVOLUTION_SCALE_BIAS);
-   }
-
-   if (ctx->DrawBuffer->_NumColorDrawBuffers > 0 &&
-       ctx->DrawBuffer->_ColorDrawBuffers[0]->DataType != GL_FLOAT &&
-       ctx->Color.ClampFragmentColor != GL_FALSE) {
-      /* need to clamp colors before applying fragment ops */
-      transferOps |= IMAGE_CLAMP_BIT;
    }
 
    /*
     * General solution
     */
    {
-      const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
-         || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
       const GLbitfield interpMask = span.interpMask;
       const GLbitfield arrayMask = span.arrayMask;
-      const GLint srcStride
-         = _mesa_image_row_stride(unpack, width, format, type);
       GLint skipPixels = 0;
       /* use span array for temp color storage */
-      GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0];
+      GLfloat *rgba = (GLfloat *) span.array->attribs[VARYING_SLOT_COL0];
+      void *tempImage = NULL;
 
-      /* if the span is wider than MAX_WIDTH we have to do it in chunks */
+      /* We have to deal with GL_COLOR_INDEX manually because
+       * _mesa_format_convert does not handle this format. So what we do here is
+       * convert it to RGBA ubyte first and then convert from that to dst as
+       * usual.
+       */
+      if (format == GL_COLOR_INDEX) {
+         /* This will handle byte swapping and transferops if needed */
+         tempImage =
+            _mesa_unpack_color_index_to_rgba_ubyte(ctx, 2,
+                                                   pixels, format, type,
+                                                   width, height, 1,
+                                                   unpack,
+                                                   transferOps);
+         if (!tempImage) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+            return;
+         }
+
+         transferOps = 0;
+         pixels = tempImage;
+         format = GL_RGBA;
+         type = GL_UNSIGNED_BYTE;
+      } else if (unpack->SwapBytes) {
+         /* We have to handle byte-swapping scenarios before calling
+          * _mesa_format_convert
+          */
+         GLint swapSize = _mesa_sizeof_packed_type(type);
+         if (swapSize == 2 || swapSize == 4) {
+            int imageStride = _mesa_image_image_stride(unpack, width, height, format, type);
+
+            tempImage = malloc(imageStride);
+            if (!tempImage) {
+               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+               return;
+            }
+
+            _mesa_swap_bytes_2d_image(format, type, unpack,
+                                      width, height, tempImage, pixels);
+
+            pixels = tempImage;
+         }
+      }
+
+      const GLint srcStride
+         = _mesa_image_row_stride(unpack, width, format, type);
+
+      /* if the span is wider than SWRAST_MAX_WIDTH we have to do it in chunks */
       while (skipPixels < width) {
-         const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
+         const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH);
          const GLubyte *source
             = (const GLubyte *) _mesa_image_address2d(unpack, pixels,
                                                       width, height, format,
                                                       type, 0, skipPixels);
          GLint row;
 
+         /* get image row as float/RGBA */
+         uint32_t srcMesaFormat = _mesa_format_from_format_and_type(format, type);
          for (row = 0; row < height; row++) {
-            /* get image row as float/RGBA */
-            _mesa_unpack_color_span_float(ctx, spanWidth, GL_RGBA, rgba,
-                                     format, type, source, unpack,
-                                     transferOps);
-            /* draw the span */
-            if (!sink) {
-               /* Set these for each row since the _swrast_write_* functions
-                * may change them while clipping/rendering.
-                */
-               span.array->ChanType = GL_FLOAT;
-               span.x = x + skipPixels;
-               span.y = y + row;
-               span.end = spanWidth;
-               span.arrayMask = arrayMask;
-               span.interpMask = interpMask;
-               if (zoom) {
-                  _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
-               }
-               else {
-                  _swrast_write_rgba_span(ctx, &span);
-               }
-            }
+            int dstRowStride = 4 * width * sizeof(float);
+            _mesa_format_convert(rgba, RGBA32_FLOAT, dstRowStride,
+                                 (void*)source, srcMesaFormat, srcStride,
+                                 spanWidth, 1, NULL);
+            if (transferOps)
+               _mesa_apply_rgba_transfer_ops(ctx, transferOps, spanWidth, (GLfloat (*)[4])rgba);
+           /* Set these for each row since the _swrast_write_* functions
+            * may change them while clipping/rendering.
+            */
+           span.array->ChanType = GL_FLOAT;
+           span.x = x + skipPixels;
+           span.y = y + row;
+           span.end = spanWidth;
+           span.arrayMask = arrayMask;
+           span.interpMask = interpMask;
+           if (zoom) {
+              _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
+           }
+           else {
+              _swrast_write_rgba_span(ctx, &span);
+           }
 
             source += srcStride;
          } /* for row */
@@ -674,14 +549,50 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
 
       /* XXX this is ugly/temporary, to undo above change */
       span.array->ChanType = CHAN_TYPE;
+
+      free(tempImage);
    }
 
-   if (convImage) {
-      _mesa_free(convImage);
+   swrast_render_finish(ctx);
+}
+
+
+/**
+ * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_Z24_UNORM_S8_UINT
+ * renderbuffer.  No masking, zooming, scaling, etc.
+ */
+static void
+fast_draw_depth_stencil(struct gl_context *ctx, GLint x, GLint y,
+                        GLsizei width, GLsizei height,
+                        const struct gl_pixelstore_attrib *unpack,
+                        const GLvoid *pixels)
+{
+   const GLenum format = GL_DEPTH_STENCIL_EXT;
+   const GLenum type = GL_UNSIGNED_INT_24_8;
+   struct gl_renderbuffer *rb =
+      ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+   GLubyte *src, *dst;
+   GLint srcRowStride, dstRowStride;
+   GLint i;
+
+   src = _mesa_image_address2d(unpack, pixels, width, height,
+                               format, type, 0, 0);
+   srcRowStride = _mesa_image_row_stride(unpack, width, format, type);
+
+   dst = _swrast_pixel_address(rb, x, y);
+   dstRowStride = srb->RowStride;
+
+   for (i = 0; i < height; i++) {
+      _mesa_pack_uint_24_8_depth_stencil_row(rb->Format, width,
+                                             (const GLuint *) src, dst);
+      dst += dstRowStride;
+      src += srcRowStride;
    }
 }
 
 
+
 /**
  * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
  * The only per-pixel operations that apply are depth scale/bias,
@@ -691,19 +602,17 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
  * color buffer(s).
  */
 static void
-draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
+draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
                           GLsizei width, GLsizei height, GLenum type,
                           const struct gl_pixelstore_attrib *unpack,
                           const GLvoid *pixels)
 {
    const GLint imgX = x, imgY = y;
    const GLboolean scaleOrBias
-      = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
-   const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
+      = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
    const GLuint stencilMask = ctx->Stencil.WriteMask[0];
-   const GLuint stencilType = (STENCIL_BITS == 8) ? 
-      GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
-   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
+   const GLenum stencilType = GL_UNSIGNED_BYTE;
+   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F;
    struct gl_renderbuffer *depthRb, *stencilRb;
    struct gl_pixelstore_attrib clippedUnpack = *unpack;
 
@@ -714,40 +623,36 @@ draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
          return;
       }
    }
-   
+
    depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
    stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
-   ASSERT(depthRb);
-   ASSERT(stencilRb);
+   assert(depthRb);
+   assert(stencilRb);
 
-   if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
-       stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
-       depthRb == stencilRb &&
+   if (depthRb == stencilRb &&
+       (depthRb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM ||
+        depthRb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) &&
+       type == GL_UNSIGNED_INT_24_8 &&
        !scaleOrBias &&
        !zoom &&
        ctx->Depth.Mask &&
        (stencilMask & 0xff) == 0xff) {
-      /* This is the ideal case.
-       * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer.
-       * Plus, no pixel transfer ops, zooming, or masking needed.
-       */
-      GLint i;
-      for (i = 0; i < height; i++) {
-         const GLuint *src = (const GLuint *) 
-            _mesa_image_address2d(&clippedUnpack, pixels, width, height,
-                                  GL_DEPTH_STENCIL_EXT, type, i, 0);
-         depthRb->PutRow(ctx, depthRb, width, x, y + i, src, NULL);
-      }
+      fast_draw_depth_stencil(ctx, x, y, width, height,
+                              &clippedUnpack, pixels);
    }
    else {
       /* sub-optimal cases:
        * Separate depth/stencil buffers, or pixel transfer ops required.
        */
       /* XXX need to handle very wide images (skippixels) */
+      GLuint *zValues;  /* 32-bit Z values */
       GLint i;
 
-      depthRb = ctx->DrawBuffer->_DepthBuffer;
-      stencilRb = ctx->DrawBuffer->_StencilBuffer;
+      zValues = malloc(width * sizeof(GLuint));
+      if (!zValues) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
+         return;
+      }
 
       for (i = 0; i < height; i++) {
          const GLuint *depthStencilSrc = (const GLuint *)
@@ -755,52 +660,25 @@ draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
                                   GL_DEPTH_STENCIL_EXT, type, i, 0);
 
          if (ctx->Depth.Mask) {
-            if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24) {
-               /* fast path 24-bit zbuffer */
-               GLuint zValues[MAX_WIDTH];
-               GLint j;
-               ASSERT(depthRb->DataType == GL_UNSIGNED_INT);
-               for (j = 0; j < width; j++) {
-                  zValues[j] = depthStencilSrc[j] >> 8;
-               }
-               if (zoom)
-                  _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
-                                              x, y + i, zValues);
-               else
-                  depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
-            }
-            else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16) {
-               /* fast path 16-bit zbuffer */
-               GLushort zValues[MAX_WIDTH];
-               GLint j;
-               ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT);
-               for (j = 0; j < width; j++) {
-                  zValues[j] = depthStencilSrc[j] >> 16;
-               }
-               if (zoom)
-                  _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
-                                              x, y + i, zValues);
-               else
-                  depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
+            _mesa_unpack_depth_span(ctx, width,
+                                    GL_UNSIGNED_INT, /* dest type */
+                                    zValues,         /* dest addr */
+                                    0xffffffff,      /* depth max */
+                                    type,            /* src type */
+                                    depthStencilSrc, /* src addr */
+                                    &clippedUnpack);
+            if (zoom) {
+               _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
+                                           y + i, zValues);
             }
             else {
-               /* general case */
-               GLuint zValues[MAX_WIDTH];  /* 16 or 32-bit Z value storage */
-               _mesa_unpack_depth_span(ctx, width,
-                                       depthRb->DataType, zValues, depthMax,
-                                       type, depthStencilSrc, &clippedUnpack);
-               if (zoom) {
-                  _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
-                                              y + i, zValues);
-               }
-               else {
-                  depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
-               }
+               GLubyte *dst = _swrast_pixel_address(depthRb, x, y + i);
+               _mesa_pack_uint_z_row(depthRb->Format, width, zValues, dst);
             }
          }
 
          if (stencilMask != 0x0) {
-            GLstencil stencilValues[MAX_WIDTH];
+            GLubyte *stencilValues = (GLubyte *) zValues; /* re-use buffer */
             /* get stencil values, with shift/offset/mapping */
             _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues,
                                       type, depthStencilSrc, &clippedUnpack,
@@ -812,6 +690,8 @@ draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
                _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues);
          }
       }
+
+      free(zValues);
    }
 }
 
@@ -821,7 +701,7 @@ draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
  * By time we get here, all error checking will have been done.
  */
 void
-_swrast_DrawPixels( GLcontext *ctx,
+_swrast_DrawPixels( struct gl_context *ctx,
                    GLint x, GLint y,
                    GLsizei width, GLsizei height,
                    GLenum format, GLenum type,
@@ -844,57 +724,42 @@ _swrast_DrawPixels( GLcontext *ctx,
     */
    _mesa_set_vp_override(ctx, GL_TRUE);
 
-   swrast_render_start(ctx);
-
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
    if (swrast->NewState)
       _swrast_validate_derived( ctx );
 
-    pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
-    if (!pixels) {
-       swrast_render_finish(ctx);
-       _mesa_set_vp_override(ctx, save_vp_override);
-       return;
-    }
+   pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
+   if (!pixels) {
+      _mesa_set_vp_override(ctx, save_vp_override);
+      return;
+   }
 
+   /*
+    * By time we get here, all error checking should have been done.
+    */
    switch (format) {
    case GL_STENCIL_INDEX:
+      swrast_render_start(ctx);
       draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
+      swrast_render_finish(ctx);
       break;
    case GL_DEPTH_COMPONENT:
+      swrast_render_start(ctx);
       draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
-      break;
-   case GL_COLOR_INDEX:
-      if (ctx->Visual.rgbMode)
-        draw_rgba_pixels(ctx, x,y, width, height, format, type, unpack, pixels);
-      else
-        draw_index_pixels(ctx, x, y, width, height, type, unpack, pixels);
-      break;
-   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:
-      draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
+      swrast_render_finish(ctx);
       break;
    case GL_DEPTH_STENCIL_EXT:
-      draw_depth_stencil_pixels(ctx, x, y, width, height,
-                                type, unpack, pixels);
+      swrast_render_start(ctx);
+      draw_depth_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
+      swrast_render_finish(ctx);
       break;
    default:
-      _mesa_problem(ctx, "unexpected format in _swrast_DrawPixels");
-      /* don't return yet, clean-up */
+      /* all other formats should be color formats */
+      draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
    }
 
-   swrast_render_finish(ctx);
    _mesa_set_vp_override(ctx, save_vp_override);
 
    _mesa_unmap_pbo_source(ctx, unpack);