drawpix.c revision f93b3dd69e744cf1dd6b102a11cdb07c2df4a967
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* $Id: drawpix.c,v 1.31 2000/08/30 18:22:28 brianp Exp $ */
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Mesa 3-D graphics library
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Version:  3.5
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Permission is hereby granted, free of charge, to any person obtaining a
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * copy of this software and associated documentation files (the "Software"),
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * to deal in the Software without restriction, including without limitation
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * and/or sell copies of the Software, and to permit persons to whom the
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Software is furnished to do so, subject to the following conditions:
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The above copyright notice and this permission notice shall be included
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * in all copies or substantial portions of the Software.
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef PC_HEADER
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "all.h"
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "glheader.h"
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "context.h"
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "convolve.h"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drawpix.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "feedback.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "image.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "macros.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "mem.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "mmath.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pixel.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pixeltex.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "span.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "state.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "stencil.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "texture.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "types.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "zoom.h"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Given the dest position, size and skipPixels and skipRows values
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * for a glDrawPixels command, perform clipping of the image bounds
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * so the result lies withing the context's buffer bounds.
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return:  GL_TRUE if image is ready for drawing
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *          GL_FALSE if image was completely clipped away (draw nothing)
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownGLboolean
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown_mesa_clip_pixelrect(const GLcontext *ctx,
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     GLint *destX, GLint *destY,
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     GLsizei *width, GLsizei *height,
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     GLint *skipPixels, GLint *skipRows)
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const GLframebuffer *buffer = ctx->DrawBuffer;
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* left clipping */
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (*destX < buffer->Xmin) {
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *skipPixels += (buffer->Xmin - *destX);
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *width -= (buffer->Xmin - *destX);
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *destX = buffer->Xmin;
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* right clipping */
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (*destX + *width > buffer->Xmax)
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *width -= (*destX + *width - buffer->Xmax - 1);
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (*width <= 0)
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return GL_FALSE;
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* bottom clipping */
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (*destY < buffer->Ymin) {
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *skipRows += (buffer->Ymin - *destY);
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *height -= (buffer->Ymin - *destY);
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *destY = buffer->Ymin;
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* top clipping */
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (*destY + *height > buffer->Ymax)
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *height -= (*destY + *height - buffer->Ymax - 1);
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (*height <= 0)
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return GL_TRUE;
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return GL_TRUE;
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Try to do a fast and simple RGB(a) glDrawPixels.
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic GLboolean
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 GLsizei width, GLsizei height,
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 GLenum format, GLenum type, const GLvoid *pixels)
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const GLuint cantTransferBits =
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_SCALE_BIAS_BIT |
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_SHIFT_OFFSET_BIT |
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_MAP_COLOR_BIT |
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_COLOR_TABLE_BIT |
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_CONVOLUTION_BIT |
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT |
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_COLOR_MATRIX_BIT |
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT |
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_HISTOGRAM_BIT |
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IMAGE_MIN_MAX_BIT;
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GLubyte rgb[MAX_WIDTH][3];
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GLubyte rgba[MAX_WIDTH][4];
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels",
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						  GL_FALSE);
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ctx->Current.RasterPosValid) {
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return GL_TRUE;      /* no-op */
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (ctx->ImageTransferState & cantTransferBits) == 0
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && ctx->Texture.ReallyEnabled == 0
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && unpack->Alignment == 1
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && !unpack->SwapBytes
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && !unpack->LsbFirst) {
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLint destX = x;
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLint destY = y;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLint drawWidth = width;           /* actual width drawn */
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLint drawHeight = height;         /* actual height drawn */
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLint skipPixels = unpack->SkipPixels;
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLint skipRows = unpack->SkipRows;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLint rowLength;
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLdepth zSpan[MAX_WIDTH];  /* only used when zooming */
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLint zoomY0;
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (unpack->RowLength > 0)
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rowLength = unpack->RowLength;
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rowLength = width;
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If we're not using pixel zoom then do all clipping calculations
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * now.  Otherwise, we'll let the gl_write_zoomed_*_span() functions
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * handle the clipping.
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* horizontal clipping */
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (destX < ctx->DrawBuffer->Xmin) {
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skipPixels += (ctx->DrawBuffer->Xmin - destX);
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            drawWidth  -= (ctx->DrawBuffer->Xmin - destX);
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            destX = ctx->DrawBuffer->Xmin;
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (destX + drawWidth > ctx->DrawBuffer->Xmax)
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax - 1);
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (drawWidth <= 0)
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return GL_TRUE;
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* vertical clipping */
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (destY < ctx->DrawBuffer->Ymin) {
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skipRows   += (ctx->DrawBuffer->Ymin - destY);
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            drawHeight -= (ctx->DrawBuffer->Ymin - destY);
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            destY = ctx->DrawBuffer->Ymin;
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (destY + drawHeight > ctx->DrawBuffer->Ymax)
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            drawHeight -= (destY + drawHeight - ctx->DrawBuffer->Ymax - 1);
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (drawHeight <= 0)
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return GL_TRUE;
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zoomY0 = 0;  /* not used - silence compiler warning */
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* upside-down image */
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* horizontal clipping */
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (destX < ctx->DrawBuffer->Xmin) {
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skipPixels += (ctx->DrawBuffer->Xmin - destX);
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            drawWidth  -= (ctx->DrawBuffer->Xmin - destX);
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            destX = ctx->DrawBuffer->Xmin;
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (destX + drawWidth > ctx->DrawBuffer->Xmax)
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax - 1);
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (drawWidth <= 0)
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return GL_TRUE;
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* vertical clipping */
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (destY > ctx->DrawBuffer->Ymax) {
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            skipRows   += (destY - ctx->DrawBuffer->Ymax - 1);
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            drawHeight -= (destY - ctx->DrawBuffer->Ymax - 1);
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            destY = ctx->DrawBuffer->Ymax + 1;
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (destY - drawHeight < ctx->DrawBuffer->Ymin)
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            drawHeight -= (ctx->DrawBuffer->Ymin - (destY - drawHeight));
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (drawHeight <= 0)
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return GL_TRUE;
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* setup array of fragment Z value to pass to zoom function */
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         GLint i;
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ASSERT(drawWidth < MAX_WIDTH);
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i=0; i<drawWidth; i++)
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            zSpan[i] = z;
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* save Y value of first row */
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * Ready to draw!
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * The window region at (destX, destY) of size (drawWidth, drawHeight)
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * will be written to.
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * We'll take pixel data from buffer pointed to by "pixels" but we'll
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * skip "skipRows" rows and skip "skipPixels" pixels/row.
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ctx->Visual->RGBAflag) {
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            GLubyte *src = (GLubyte *) pixels
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               + (skipRows * rowLength + skipPixels) * 4;
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* no zooming */
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               (void *) src, NULL);
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength * 4;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* upside-down */
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY--;
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              (void *) src, NULL);
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength * 4;
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else {
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* with zooming */
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            zSpan, (void *) src, zoomY0);
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength * 4;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return GL_TRUE;
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) {
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ctx->Visual->RGBAflag) {
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            GLubyte *src = (GLubyte *) pixels
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               + (skipRows * rowLength + skipPixels) * 3;
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              (void *) src, NULL);
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength * 3;
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* upside-down */
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY--;
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              (void *) src, NULL);
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength * 3;
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else {
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* with zooming */
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           zSpan, (void *) src, zoomY0);
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength * 3;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return GL_TRUE;
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) {
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ctx->Visual->RGBAflag) {
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            GLubyte *src = (GLubyte *) pixels
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               + (skipRows * rowLength + skipPixels);
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* no zooming */
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ASSERT(drawWidth < MAX_WIDTH);
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  GLint i;
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  for (i=0;i<drawWidth;i++) {
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgb[i][0] = src[i];
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgb[i][1] = src[i];
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgb[i][2] = src[i];
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  }
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              (void *) rgb, NULL);
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength;
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* upside-down */
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ASSERT(drawWidth < MAX_WIDTH);
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  GLint i;
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  for (i=0;i<drawWidth;i++) {
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgb[i][0] = src[i];
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgb[i][1] = src[i];
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgb[i][2] = src[i];
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY--;
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              (void *) rgb, NULL);
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength;
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else {
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* with zooming */
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ASSERT(drawWidth < MAX_WIDTH);
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  GLint i;
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  for (i=0;i<drawWidth;i++) {
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgb[i][0] = src[i];
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgb[i][1] = src[i];
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgb[i][2] = src[i];
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  }
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           zSpan, (void *) rgb, zoomY0);
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength;
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return GL_TRUE;
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) {
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ctx->Visual->RGBAflag) {
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            GLubyte *src = (GLubyte *) pixels
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               + (skipRows * rowLength + skipPixels)*2;
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* no zooming */
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ASSERT(drawWidth < MAX_WIDTH);
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  GLint i;
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  GLubyte *ptr = src;
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  for (i=0;i<drawWidth;i++) {
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][0] = *ptr;
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][1] = *ptr;
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][2] = *ptr++;
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][3] = *ptr++;
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  }
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               (void *) rgba, NULL);
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength*2;
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* upside-down */
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ASSERT(drawWidth < MAX_WIDTH);
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  GLint i;
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  GLubyte *ptr = src;
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  for (i=0;i<drawWidth;i++) {
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][0] = *ptr;
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][1] = *ptr;
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][2] = *ptr++;
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][3] = *ptr++;
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY--;
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               (void *) rgba, NULL);
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength*2;
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else {
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* with zooming */
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ASSERT(drawWidth < MAX_WIDTH);
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  GLubyte *ptr = src;
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  GLint i;
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  for (i=0;i<drawWidth;i++) {
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][0] = *ptr;
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][1] = *ptr;
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][2] = *ptr++;
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     rgba[i][3] = *ptr++;
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  }
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            zSpan, (void *) rgba, zoomY0);
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength*2;
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return GL_TRUE;
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ctx->Visual->RGBAflag) {
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* convert CI data to RGBA */
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* no zooming */
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ASSERT(drawWidth < MAX_WIDTH);
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               (const GLubyte (*)[4])rgba,
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					       NULL);
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength;
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return GL_TRUE;
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* upside-down */
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ASSERT(drawWidth < MAX_WIDTH);
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY--;
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               (const GLubyte (*)[4])rgba,
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               NULL);
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength;
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return GL_TRUE;
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else {
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* with zooming */
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               GLint row;
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ASSERT(drawWidth < MAX_WIDTH);
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  _mesa_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            zSpan, (void *) rgba, zoomY0);
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength;
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return GL_TRUE;
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else {
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* write CI data to CI frame buffer */
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            GLint row;
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* no zooming */
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for (row=0; row<drawHeight; row++) {
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              src, NULL);
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  src += rowLength;
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  destY++;
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return GL_TRUE;
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else {
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* with zooming */
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return GL_FALSE;
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* can't handle this pixel format and/or data type here */
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return GL_FALSE;
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* can't do a simple draw, have to use slow path */
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return GL_FALSE;
494}
495
496
497
498/*
499 * Do glDrawPixels of index pixels.
500 */
501static void
502draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
503                   GLsizei width, GLsizei height,
504                   GLenum type, const GLvoid *pixels )
505{
506   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
507   const GLint desty = y;
508   GLint row, drawWidth;
509   GLdepth zspan[MAX_WIDTH];
510
511   drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
512
513   /* Fragment depth values */
514   if (ctx->Depth.Test || ctx->Fog.Enabled) {
515      GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
516      GLint i;
517      for (i = 0; i < drawWidth; i++) {
518	 zspan[i] = zval;
519      }
520   }
521
522   /*
523    * General solution
524    */
525   for (row = 0; row < height; row++, y++) {
526      GLuint indexes[MAX_WIDTH];
527      const GLvoid *source = _mesa_image_address(&ctx->Unpack,
528                    pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
529      _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes,
530                              type, source, &ctx->Unpack,
531                              ctx->ImageTransferState);
532      if (zoom) {
533         gl_write_zoomed_index_span(ctx, drawWidth, x, y, zspan, indexes, desty);
534      }
535      else {
536         gl_write_index_span(ctx, drawWidth, x, y, zspan, indexes, GL_BITMAP);
537      }
538   }
539}
540
541
542
543/*
544 * Do glDrawPixels of stencil image.  The image datatype may either
545 * be GLubyte or GLbitmap.
546 */
547static void
548draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
549                     GLsizei width, GLsizei height,
550                     GLenum type, const GLvoid *pixels )
551{
552   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
553   const GLint desty = y;
554   GLint row, drawWidth;
555
556   if (type != GL_BYTE &&
557       type != GL_UNSIGNED_BYTE &&
558       type != GL_SHORT &&
559       type != GL_UNSIGNED_SHORT &&
560       type != GL_INT &&
561       type != GL_UNSIGNED_INT &&
562       type != GL_FLOAT &&
563       type != GL_BITMAP) {
564      gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)");
565      return;
566   }
567
568   drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
569
570   for (row = 0; row < height; row++, y++) {
571      GLstencil values[MAX_WIDTH];
572      GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
573                      ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
574      const GLvoid *source = _mesa_image_address(&ctx->Unpack,
575                    pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
576      _mesa_unpack_index_span(ctx, drawWidth, destType, values,
577                              type, source, &ctx->Unpack,
578                              ctx->ImageTransferState);
579      if (ctx->ImageTransferState & IMAGE_SHIFT_OFFSET_BIT) {
580         _mesa_shift_and_offset_stencil( ctx, drawWidth, values );
581      }
582      if (ctx->Pixel.MapStencilFlag) {
583         _mesa_map_stencil( ctx, drawWidth, values );
584      }
585
586      if (zoom) {
587         gl_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y,
588                                       values, desty );
589      }
590      else {
591         _mesa_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
592      }
593   }
594}
595
596
597
598/*
599 * Do a glDrawPixels of depth values.
600 */
601static void
602draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
603                   GLsizei width, GLsizei height,
604                   GLenum type, const GLvoid *pixels )
605{
606   const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
607   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
608   const GLint desty = y;
609   GLubyte rgba[MAX_WIDTH][4];
610   GLuint ispan[MAX_WIDTH];
611   GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
612
613   if (type != GL_BYTE
614       && type != GL_UNSIGNED_BYTE
615       && type != GL_SHORT
616       && type != GL_UNSIGNED_SHORT
617       && type != GL_INT
618       && type != GL_UNSIGNED_INT
619       && type != GL_FLOAT) {
620      gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)");
621      return;
622   }
623
624   /* Colors or indexes */
625   if (ctx->Visual->RGBAflag) {
626      GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
627      GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
628      GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
629      GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
630      GLint i;
631      for (i = 0; i < drawWidth; i++) {
632         rgba[i][RCOMP] = r;
633         rgba[i][GCOMP] = g;
634         rgba[i][BCOMP] = b;
635         rgba[i][ACOMP] = a;
636      }
637   }
638   else {
639      GLint i;
640      for (i = 0; i < drawWidth; i++) {
641	 ispan[i] = ctx->Current.RasterIndex;
642      }
643   }
644
645   if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
646       && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
647      /* Special case: directly write 16-bit depth values */
648      GLint row;
649      for (row = 0; row < height; row++, y++) {
650         GLdepth zspan[MAX_WIDTH];
651         const GLushort *zptr = _mesa_image_address(&ctx->Unpack,
652                pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
653         GLint i;
654         for (i = 0; i < width; i++)
655            zspan[i] = zptr[i];
656         gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
657      }
658   }
659   else if (type==GL_UNSIGNED_INT && ctx->Visual->DepthBits == 32
660       && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
661      /* Special case: directly write 32-bit depth values */
662      GLint row;
663      for (row = 0; row < height; row++, y++) {
664         const GLuint *zptr = _mesa_image_address(&ctx->Unpack,
665                pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
666         gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
667      }
668   }
669   else {
670      /* General case */
671      GLint row;
672      for (row = 0; row < height; row++, y++) {
673         GLdepth zspan[MAX_WIDTH];
674         const GLvoid *src = _mesa_image_address(&ctx->Unpack,
675                pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
676         _mesa_unpack_depth_span( ctx, drawWidth, zspan, type, src,
677                                  &ctx->Unpack, ctx->ImageTransferState );
678         if (ctx->Visual->RGBAflag) {
679            if (zoom) {
680               gl_write_zoomed_rgba_span(ctx, width, x, y, zspan,
681                                         (const GLubyte (*)[4])rgba, desty);
682            }
683            else {
684               gl_write_rgba_span(ctx, width, x, y, zspan, rgba, GL_BITMAP);
685            }
686         }
687         else {
688            if (zoom) {
689               gl_write_zoomed_index_span(ctx, width, x, y, zspan,
690                                          ispan, GL_BITMAP);
691            }
692            else {
693               gl_write_index_span(ctx, width, x, y, zspan, ispan, GL_BITMAP);
694            }
695         }
696
697      }
698   }
699}
700
701
702/*
703 * Do glDrawPixels of RGBA pixels.
704 */
705static void
706draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
707                  GLsizei width, GLsizei height,
708                  GLenum format, GLenum type, const GLvoid *pixels )
709{
710   const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
711   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
712   const GLint desty = y;
713   GLdepth zspan[MAX_WIDTH];
714   GLboolean quickDraw;
715   GLfloat *convImage = NULL;
716   GLuint transferOps = ctx->ImageTransferState;
717
718   /* Try an optimized glDrawPixels first */
719   if (fast_draw_pixels(ctx, x, y, width, height, format, type, pixels))
720      return;
721
722   /* Fragment depth values */
723   if (ctx->Depth.Test || ctx->Fog.Enabled) {
724      /* fill in array of z values */
725      GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
726      GLint i;
727      for (i=0;i<width;i++) {
728	 zspan[i] = z;
729      }
730   }
731
732
733   if (ctx->RasterMask == 0 && !zoom && x >= 0 && y >= 0
734       && x + width <= ctx->DrawBuffer->Width
735       && y + height <= ctx->DrawBuffer->Height) {
736      quickDraw = GL_TRUE;
737   }
738   else {
739      quickDraw = GL_FALSE;
740   }
741
742   if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
743      /* Convolution has to be handled specially.  We'll create an
744       * intermediate image, applying all pixel transfer operations
745       * up to convolution.  Then we'll convolve the image.  Then
746       * we'll proceed with the rest of the transfer operations and
747       * rasterize the image.
748       */
749      GLint row;
750      GLfloat *dest, *tmpImage;
751
752      tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
753      if (!tmpImage) {
754         gl_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
755         return;
756      }
757      convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
758      if (!convImage) {
759         FREE(tmpImage);
760         gl_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
761         return;
762      }
763
764      /* Unpack the image and apply transfer ops up to convolution */
765      dest = tmpImage;
766      for (row = 0; row < height; row++) {
767         const GLvoid *source = _mesa_image_address(unpack,
768                  pixels, width, height, format, type, 0, row, 0);
769         _mesa_unpack_float_color_span(ctx, width, GL_RGBA, (void *) dest,
770                                      format, type, source, unpack,
771                                      transferOps & IMAGE_PRE_CONVOLUTION_BITS,
772                                      GL_FALSE);
773         dest += width * 4;
774      }
775
776      /* do convolution */
777      if (ctx->Pixel.Convolution2DEnabled) {
778         _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
779      }
780      else {
781         ASSERT(ctx->Pixel.Separable2DEnabled);
782         _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
783      }
784      FREE(tmpImage);
785
786      /* continue transfer ops and draw the convolved image */
787      unpack = &_mesa_native_packing;
788      pixels = convImage;
789      format = GL_RGBA;
790      type = GL_FLOAT;
791      transferOps &= IMAGE_POST_CONVOLUTION_BITS;
792   }
793
794   /*
795    * General solution
796    */
797   {
798      GLubyte rgba[MAX_WIDTH][4];
799      GLint row;
800      if (width > MAX_WIDTH)
801         width = MAX_WIDTH;
802      for (row = 0; row < height; row++, y++) {
803         const GLvoid *source = _mesa_image_address(unpack,
804                  pixels, width, height, format, type, 0, row, 0);
805         _mesa_unpack_ubyte_color_span(ctx, width, GL_RGBA, (void*) rgba,
806                                       format, type, source, unpack,
807                                       transferOps);
808         if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) ||
809             (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink))
810            continue;
811
812         if (ctx->Texture.ReallyEnabled && ctx->Pixel.PixelTextureEnabled) {
813            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH];
814            GLubyte primary_rgba[MAX_WIDTH][4];
815            GLuint unit;
816            /* XXX not sure how multitexture is supposed to work here */
817
818            MEMCPY(primary_rgba, rgba, 4 * width * sizeof(GLubyte));
819
820            for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++) {
821               _mesa_pixeltexgen(ctx, width, (const GLubyte (*)[4]) rgba,
822                                 s, t, r, q);
823               gl_texture_pixels(ctx, unit, width, s, t, r, NULL,
824                                 primary_rgba, rgba);
825            }
826         }
827
828         if (quickDraw) {
829            (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
830                                          (CONST GLubyte (*)[]) rgba, NULL);
831         }
832         else if (zoom) {
833            gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
834				       (CONST GLubyte (*)[]) rgba, desty );
835         }
836         else {
837            gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
838         }
839      }
840   }
841
842   if (convImage) {
843      FREE(convImage);
844   }
845}
846
847
848
849/*
850 * Execute glDrawPixels
851 */
852void
853_mesa_DrawPixels( GLsizei width, GLsizei height,
854                  GLenum format, GLenum type, const GLvoid *pixels )
855{
856   GET_CURRENT_CONTEXT(ctx);
857   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels");
858
859   if (ctx->RenderMode==GL_RENDER) {
860      GLint x, y;
861      if (!pixels || !ctx->Current.RasterPosValid) {
862	 return;
863      }
864
865      if (ctx->NewState) {
866         gl_update_state(ctx);
867      }
868
869      if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
870         _mesa_update_image_transfer_state(ctx);
871
872      x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
873      y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
874
875      ctx->OcclusionResult = GL_TRUE;
876
877      /* see if device driver can do the drawpix */
878      if (ctx->Driver.DrawPixels
879          && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
880                                       &ctx->Unpack, pixels)) {
881         return;
882      }
883
884      switch (format) {
885	 case GL_STENCIL_INDEX:
886	    draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
887	    break;
888	 case GL_DEPTH_COMPONENT:
889	    draw_depth_pixels( ctx, x, y, width, height, type, pixels );
890	    break;
891	 case GL_COLOR_INDEX:
892            if (ctx->Visual->RGBAflag)
893               draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
894            else
895               draw_index_pixels(ctx, x, y, width, height, type, pixels);
896	    break;
897	 case GL_RED:
898	 case GL_GREEN:
899	 case GL_BLUE:
900	 case GL_ALPHA:
901	 case GL_LUMINANCE:
902	 case GL_LUMINANCE_ALPHA:
903	 case GL_RGB:
904         case GL_BGR:
905	 case GL_RGBA:
906	 case GL_BGRA:
907	 case GL_ABGR_EXT:
908            draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels);
909	    break;
910	 default:
911	    gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" );
912            return;
913      }
914   }
915   else if (ctx->RenderMode==GL_FEEDBACK) {
916      if (ctx->Current.RasterPosValid) {
917         GLfloat color[4];
918	 GLfloat texcoord[4], invq;
919	 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor);
920         invq = 1.0F / ctx->Current.Texcoord[0][3];
921         texcoord[0] = ctx->Current.Texcoord[0][0] * invq;
922         texcoord[1] = ctx->Current.Texcoord[0][1] * invq;
923         texcoord[2] = ctx->Current.Texcoord[0][2] * invq;
924         texcoord[3] = ctx->Current.Texcoord[0][3];
925         FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
926         gl_feedback_vertex( ctx,
927                             ctx->Current.RasterPos,
928                             color, ctx->Current.Index, texcoord );
929      }
930   }
931   else if (ctx->RenderMode==GL_SELECT) {
932      if (ctx->Current.RasterPosValid) {
933         gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
934      }
935   }
936}
937
938