xref: /reactos/dll/opengl/mesa/readpix.c (revision 5f2bebf7)
1*5f2bebf7SJérôme Gardou /* $Id: readpix.c,v 1.10 1997/07/24 01:25:18 brianp Exp $ */
2*5f2bebf7SJérôme Gardou 
3*5f2bebf7SJérôme Gardou /*
4*5f2bebf7SJérôme Gardou  * Mesa 3-D graphics library
5*5f2bebf7SJérôme Gardou  * Version:  2.4
6*5f2bebf7SJérôme Gardou  * Copyright (C) 1995-1997  Brian Paul
7*5f2bebf7SJérôme Gardou  *
8*5f2bebf7SJérôme Gardou  * This library is free software; you can redistribute it and/or
9*5f2bebf7SJérôme Gardou  * modify it under the terms of the GNU Library General Public
10*5f2bebf7SJérôme Gardou  * License as published by the Free Software Foundation; either
11*5f2bebf7SJérôme Gardou  * version 2 of the License, or (at your option) any later version.
12*5f2bebf7SJérôme Gardou  *
13*5f2bebf7SJérôme Gardou  * This library is distributed in the hope that it will be useful,
14*5f2bebf7SJérôme Gardou  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15*5f2bebf7SJérôme Gardou  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*5f2bebf7SJérôme Gardou  * Library General Public License for more details.
17*5f2bebf7SJérôme Gardou  *
18*5f2bebf7SJérôme Gardou  * You should have received a copy of the GNU Library General Public
19*5f2bebf7SJérôme Gardou  * License along with this library; if not, write to the Free
20*5f2bebf7SJérôme Gardou  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*5f2bebf7SJérôme Gardou  */
22*5f2bebf7SJérôme Gardou 
23*5f2bebf7SJérôme Gardou 
24*5f2bebf7SJérôme Gardou /*
25*5f2bebf7SJérôme Gardou  * $Log: readpix.c,v $
26*5f2bebf7SJérôme Gardou  * Revision 1.10  1997/07/24 01:25:18  brianp
27*5f2bebf7SJérôme Gardou  * changed precompiled header symbol from PCH to PC_HEADER
28*5f2bebf7SJérôme Gardou  *
29*5f2bebf7SJérôme Gardou  * Revision 1.9  1997/05/28 03:26:18  brianp
30*5f2bebf7SJérôme Gardou  * added precompiled header (PCH) support
31*5f2bebf7SJérôme Gardou  *
32*5f2bebf7SJérôme Gardou  * Revision 1.8  1997/05/08 01:43:50  brianp
33*5f2bebf7SJérôme Gardou  * added error check to gl_ReadPixels() for inside glBegin/glEnd
34*5f2bebf7SJérôme Gardou  *
35*5f2bebf7SJérôme Gardou  * Revision 1.7  1997/02/03 20:31:15  brianp
36*5f2bebf7SJérôme Gardou  * added a few DEFARRAY macros for BeOS
37*5f2bebf7SJérôme Gardou  *
38*5f2bebf7SJérôme Gardou  * Revision 1.6  1997/01/16 19:24:05  brianp
39*5f2bebf7SJérôme Gardou  * replaced a few abort()'s with gl_error() calls
40*5f2bebf7SJérôme Gardou  *
41*5f2bebf7SJérôme Gardou  * Revision 1.5  1996/12/20 20:28:04  brianp
42*5f2bebf7SJérôme Gardou  * use DEF/UNDEFARRAY() macros in read_color_pixels() for Mac compilers
43*5f2bebf7SJérôme Gardou  *
44*5f2bebf7SJérôme Gardou  * Revision 1.4  1996/11/01 03:20:47  brianp
45*5f2bebf7SJérôme Gardou  * reading GL_LUMINANCE pixels weren't clamped
46*5f2bebf7SJérôme Gardou  *
47*5f2bebf7SJérôme Gardou  * Revision 1.3  1996/09/27 01:29:47  brianp
48*5f2bebf7SJérôme Gardou  * added missing default cases to switches
49*5f2bebf7SJérôme Gardou  *
50*5f2bebf7SJérôme Gardou  * Revision 1.2  1996/09/15 14:18:37  brianp
51*5f2bebf7SJérôme Gardou  * now use GLframebuffer and GLvisual
52*5f2bebf7SJérôme Gardou  *
53*5f2bebf7SJérôme Gardou  * Revision 1.1  1996/09/13 01:38:16  brianp
54*5f2bebf7SJérôme Gardou  * Initial revision
55*5f2bebf7SJérôme Gardou  *
56*5f2bebf7SJérôme Gardou  */
57*5f2bebf7SJérôme Gardou 
58*5f2bebf7SJérôme Gardou 
59*5f2bebf7SJérôme Gardou #ifdef PC_HEADER
60*5f2bebf7SJérôme Gardou #include "all.h"
61*5f2bebf7SJérôme Gardou #else
62*5f2bebf7SJérôme Gardou #include <math.h>
63*5f2bebf7SJérôme Gardou #include <stdlib.h>
64*5f2bebf7SJérôme Gardou #include <string.h>
65*5f2bebf7SJérôme Gardou #include "alphabuf.h"
66*5f2bebf7SJérôme Gardou #include "context.h"
67*5f2bebf7SJérôme Gardou #include "depth.h"
68*5f2bebf7SJérôme Gardou #include "feedback.h"
69*5f2bebf7SJérôme Gardou #include "dlist.h"
70*5f2bebf7SJérôme Gardou #include "macros.h"
71*5f2bebf7SJérôme Gardou #include "image.h"
72*5f2bebf7SJérôme Gardou #include "readpix.h"
73*5f2bebf7SJérôme Gardou #include "span.h"
74*5f2bebf7SJérôme Gardou #include "stencil.h"
75*5f2bebf7SJérôme Gardou #include "types.h"
76*5f2bebf7SJérôme Gardou #endif
77*5f2bebf7SJérôme Gardou 
78*5f2bebf7SJérôme Gardou 
79*5f2bebf7SJérôme Gardou 
80*5f2bebf7SJérôme Gardou 
81*5f2bebf7SJérôme Gardou /*
82*5f2bebf7SJérôme Gardou  * Read a block of color index pixels.
83*5f2bebf7SJérôme Gardou  */
read_index_pixels(GLcontext * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels)84*5f2bebf7SJérôme Gardou static void read_index_pixels( GLcontext *ctx,
85*5f2bebf7SJérôme Gardou                                GLint x, GLint y,
86*5f2bebf7SJérôme Gardou 			       GLsizei width, GLsizei height,
87*5f2bebf7SJérôme Gardou 			       GLenum type, GLvoid *pixels )
88*5f2bebf7SJérôme Gardou {
89*5f2bebf7SJérôme Gardou    GLint i, j;
90*5f2bebf7SJérôme Gardou    GLuint a, s, k, l, start;
91*5f2bebf7SJérôme Gardou 
92*5f2bebf7SJérôme Gardou    /* error checking */
93*5f2bebf7SJérôme Gardou    if (ctx->Visual->RGBAflag) {
94*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
95*5f2bebf7SJérôme Gardou       return;
96*5f2bebf7SJérôme Gardou    }
97*5f2bebf7SJérôme Gardou 
98*5f2bebf7SJérôme Gardou    /* Size of each component */
99*5f2bebf7SJérôme Gardou    s = gl_sizeof_type( type );
100*5f2bebf7SJérôme Gardou    if (s<=0) {
101*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
102*5f2bebf7SJérôme Gardou       return;
103*5f2bebf7SJérôme Gardou    }
104*5f2bebf7SJérôme Gardou 
105*5f2bebf7SJérôme Gardou    /* Compute packing parameters */
106*5f2bebf7SJérôme Gardou    a = ctx->Pack.Alignment;
107*5f2bebf7SJérôme Gardou    if (ctx->Pack.RowLength>0) {
108*5f2bebf7SJérôme Gardou       l = ctx->Pack.RowLength;
109*5f2bebf7SJérôme Gardou    }
110*5f2bebf7SJérôme Gardou    else {
111*5f2bebf7SJérôme Gardou       l = width;
112*5f2bebf7SJérôme Gardou    }
113*5f2bebf7SJérôme Gardou    /* k = offset between rows in components */
114*5f2bebf7SJérôme Gardou    if (s>=a) {
115*5f2bebf7SJérôme Gardou       k = l;
116*5f2bebf7SJérôme Gardou    }
117*5f2bebf7SJérôme Gardou    else {
118*5f2bebf7SJérôme Gardou       k = a/s * CEILING( s*l, a );
119*5f2bebf7SJérôme Gardou    }
120*5f2bebf7SJérôme Gardou 
121*5f2bebf7SJérôme Gardou    /* offset to first component returned */
122*5f2bebf7SJérôme Gardou    start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels;
123*5f2bebf7SJérôme Gardou 
124*5f2bebf7SJérôme Gardou    /* process image row by row */
125*5f2bebf7SJérôme Gardou    for (j=0;j<height;j++,y++) {
126*5f2bebf7SJérôme Gardou       GLuint index[MAX_WIDTH];
127*5f2bebf7SJérôme Gardou       (*ctx->Driver.ReadIndexSpan)( ctx, width, x, y, index );
128*5f2bebf7SJérôme Gardou 
129*5f2bebf7SJérôme Gardou       if (ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0) {
130*5f2bebf7SJérôme Gardou 	 GLuint s;
131*5f2bebf7SJérôme Gardou 	 if (ctx->Pixel.IndexShift<0) {
132*5f2bebf7SJérôme Gardou 	    /* right shift */
133*5f2bebf7SJérôme Gardou 	    s = -ctx->Pixel.IndexShift;
134*5f2bebf7SJérôme Gardou 	    for (i=0;i<width;i++) {
135*5f2bebf7SJérôme Gardou 	       index[i] = (index[i] >> s) + ctx->Pixel.IndexOffset;
136*5f2bebf7SJérôme Gardou 	    }
137*5f2bebf7SJérôme Gardou 	 }
138*5f2bebf7SJérôme Gardou 	 else {
139*5f2bebf7SJérôme Gardou 	    /* left shift */
140*5f2bebf7SJérôme Gardou 	    s = ctx->Pixel.IndexShift;
141*5f2bebf7SJérôme Gardou 	    for (i=0;i<width;i++) {
142*5f2bebf7SJérôme Gardou 	       index[i] = (index[i] << s) + ctx->Pixel.IndexOffset;
143*5f2bebf7SJérôme Gardou 	    }
144*5f2bebf7SJérôme Gardou 	 }
145*5f2bebf7SJérôme Gardou       }
146*5f2bebf7SJérôme Gardou 
147*5f2bebf7SJérôme Gardou       if (ctx->Pixel.MapColorFlag) {
148*5f2bebf7SJérôme Gardou 	 for (i=0;i<width;i++) {
149*5f2bebf7SJérôme Gardou 	    index[i] = ctx->Pixel.MapItoI[ index[i] ];
150*5f2bebf7SJérôme Gardou 	 }
151*5f2bebf7SJérôme Gardou       }
152*5f2bebf7SJérôme Gardou 
153*5f2bebf7SJérôme Gardou       switch (type) {
154*5f2bebf7SJérôme Gardou 	 case GL_UNSIGNED_BYTE:
155*5f2bebf7SJérôme Gardou 	    {
156*5f2bebf7SJérôme Gardou 	       GLubyte *dst = (GLubyte *) pixels + start + j * k;
157*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
158*5f2bebf7SJérôme Gardou 		  *dst++ = (GLubyte) index[i];
159*5f2bebf7SJérôme Gardou 	       }
160*5f2bebf7SJérôme Gardou 	    }
161*5f2bebf7SJérôme Gardou 	    break;
162*5f2bebf7SJérôme Gardou 	 case GL_BYTE:
163*5f2bebf7SJérôme Gardou 	    {
164*5f2bebf7SJérôme Gardou 	       GLbyte *dst = (GLbyte *) pixels + start + j * k;
165*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
166*5f2bebf7SJérôme Gardou 		  *dst++ = (GLbyte) index[i];
167*5f2bebf7SJérôme Gardou 	       }
168*5f2bebf7SJérôme Gardou 	    }
169*5f2bebf7SJérôme Gardou 	    break;
170*5f2bebf7SJérôme Gardou 	 case GL_UNSIGNED_SHORT:
171*5f2bebf7SJérôme Gardou 	    {
172*5f2bebf7SJérôme Gardou 	       GLushort *dst = (GLushort *) pixels + start + j * k;
173*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
174*5f2bebf7SJérôme Gardou 		  *dst++ = (GLushort) index[i];
175*5f2bebf7SJérôme Gardou 	       }
176*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
177*5f2bebf7SJérôme Gardou 		  gl_swap2( (GLushort *) pixels + start + j * k, width );
178*5f2bebf7SJérôme Gardou 	       }
179*5f2bebf7SJérôme Gardou 	    }
180*5f2bebf7SJérôme Gardou 	    break;
181*5f2bebf7SJérôme Gardou 	 case GL_SHORT:
182*5f2bebf7SJérôme Gardou 	    {
183*5f2bebf7SJérôme Gardou 	       GLshort *dst = (GLshort *) pixels + start + j * k;
184*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
185*5f2bebf7SJérôme Gardou 		  *dst++ = (GLshort) index[i];
186*5f2bebf7SJérôme Gardou 	       }
187*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
188*5f2bebf7SJérôme Gardou 		  gl_swap2( (GLushort *) pixels + start + j * k, width );
189*5f2bebf7SJérôme Gardou 	       }
190*5f2bebf7SJérôme Gardou 	    }
191*5f2bebf7SJérôme Gardou 	    break;
192*5f2bebf7SJérôme Gardou 	 case GL_UNSIGNED_INT:
193*5f2bebf7SJérôme Gardou 	    {
194*5f2bebf7SJérôme Gardou 	       GLuint *dst = (GLuint *) pixels + start + j * k;
195*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
196*5f2bebf7SJérôme Gardou 		  *dst++ = (GLuint) index[i];
197*5f2bebf7SJérôme Gardou 	       }
198*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
199*5f2bebf7SJérôme Gardou 		  gl_swap4( (GLuint *) pixels + start + j * k, width );
200*5f2bebf7SJérôme Gardou 	       }
201*5f2bebf7SJérôme Gardou 	    }
202*5f2bebf7SJérôme Gardou 	    break;
203*5f2bebf7SJérôme Gardou 	 case GL_INT:
204*5f2bebf7SJérôme Gardou 	    {
205*5f2bebf7SJérôme Gardou 	       GLint *dst = (GLint *) pixels + start + j * k;
206*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
207*5f2bebf7SJérôme Gardou 		  *dst++ = (GLint) index[i];
208*5f2bebf7SJérôme Gardou 	       }
209*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
210*5f2bebf7SJérôme Gardou 		  gl_swap4( (GLuint *) pixels + start + j * k, width );
211*5f2bebf7SJérôme Gardou 	       }
212*5f2bebf7SJérôme Gardou 	    }
213*5f2bebf7SJérôme Gardou 	    break;
214*5f2bebf7SJérôme Gardou 	 case GL_FLOAT:
215*5f2bebf7SJérôme Gardou 	    {
216*5f2bebf7SJérôme Gardou 	       GLfloat *dst = (GLfloat *) pixels + start + j * k;
217*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
218*5f2bebf7SJérôme Gardou 		  *dst++ = (GLfloat) index[i];
219*5f2bebf7SJérôme Gardou 	       }
220*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
221*5f2bebf7SJérôme Gardou 		  gl_swap4( (GLuint *) pixels + start + j * k, width );
222*5f2bebf7SJérôme Gardou 	       }
223*5f2bebf7SJérôme Gardou 	    }
224*5f2bebf7SJérôme Gardou 	    break;
225*5f2bebf7SJérôme Gardou          default:
226*5f2bebf7SJérôme Gardou             gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
227*5f2bebf7SJérôme Gardou       }
228*5f2bebf7SJérôme Gardou    }
229*5f2bebf7SJérôme Gardou }
230*5f2bebf7SJérôme Gardou 
231*5f2bebf7SJérôme Gardou 
232*5f2bebf7SJérôme Gardou 
read_depth_pixels(GLcontext * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels)233*5f2bebf7SJérôme Gardou static void read_depth_pixels( GLcontext *ctx,
234*5f2bebf7SJérôme Gardou                                GLint x, GLint y,
235*5f2bebf7SJérôme Gardou 			       GLsizei width, GLsizei height,
236*5f2bebf7SJérôme Gardou 			       GLenum type, GLvoid *pixels )
237*5f2bebf7SJérôme Gardou {
238*5f2bebf7SJérôme Gardou    GLint i, j;
239*5f2bebf7SJérôme Gardou    GLuint a, s, k, l, start;
240*5f2bebf7SJérôme Gardou    GLboolean bias_or_scale;
241*5f2bebf7SJérôme Gardou 
242*5f2bebf7SJérôme Gardou    /* Error checking */
243*5f2bebf7SJérôme Gardou    if (ctx->Visual->DepthBits<=0) {
244*5f2bebf7SJérôme Gardou       /* No depth buffer */
245*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
246*5f2bebf7SJérôme Gardou       return;
247*5f2bebf7SJérôme Gardou    }
248*5f2bebf7SJérôme Gardou 
249*5f2bebf7SJérôme Gardou    bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
250*5f2bebf7SJérôme Gardou 
251*5f2bebf7SJérôme Gardou    /* Size of each component */
252*5f2bebf7SJérôme Gardou    s = gl_sizeof_type( type );
253*5f2bebf7SJérôme Gardou    if (s<=0) {
254*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
255*5f2bebf7SJérôme Gardou       return;
256*5f2bebf7SJérôme Gardou    }
257*5f2bebf7SJérôme Gardou 
258*5f2bebf7SJérôme Gardou    /* Compute packing parameters */
259*5f2bebf7SJérôme Gardou    a = ctx->Pack.Alignment;
260*5f2bebf7SJérôme Gardou    if (ctx->Pack.RowLength>0) {
261*5f2bebf7SJérôme Gardou       l = ctx->Pack.RowLength;
262*5f2bebf7SJérôme Gardou    }
263*5f2bebf7SJérôme Gardou    else {
264*5f2bebf7SJérôme Gardou       l = width;
265*5f2bebf7SJérôme Gardou    }
266*5f2bebf7SJérôme Gardou    /* k = offset between rows in components */
267*5f2bebf7SJérôme Gardou    if (s>=a) {
268*5f2bebf7SJérôme Gardou       k = l;
269*5f2bebf7SJérôme Gardou    }
270*5f2bebf7SJérôme Gardou    else {
271*5f2bebf7SJérôme Gardou       k = a/s * CEILING( s*l, a );
272*5f2bebf7SJérôme Gardou    }
273*5f2bebf7SJérôme Gardou 
274*5f2bebf7SJérôme Gardou    /* offset to first component returned */
275*5f2bebf7SJérôme Gardou    start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels;
276*5f2bebf7SJérôme Gardou 
277*5f2bebf7SJérôme Gardou    if (type==GL_UNSIGNED_INT && !bias_or_scale && !ctx->Pack.SwapBytes) {
278*5f2bebf7SJérôme Gardou       /* Special case: directly read 32-bit unsigned depth values. */
279*5f2bebf7SJérôme Gardou       /* Compute shift value to scale depth values up to 32-bit uints. */
280*5f2bebf7SJérôme Gardou       GLuint shift = 0;
281*5f2bebf7SJérôme Gardou       GLuint max = MAX_DEPTH;
282*5f2bebf7SJérôme Gardou       while ((max&0x80000000)==0) {
283*5f2bebf7SJérôme Gardou          max = max << 1;
284*5f2bebf7SJérôme Gardou          shift++;
285*5f2bebf7SJérôme Gardou       }
286*5f2bebf7SJérôme Gardou       for (j=0;j<height;j++,y++) {
287*5f2bebf7SJérôme Gardou          GLuint *dst = (GLuint *) pixels + start + j * k;
288*5f2bebf7SJérôme Gardou          (*ctx->Driver.ReadDepthSpanInt)( ctx, width, x, y, (GLdepth*) dst);
289*5f2bebf7SJérôme Gardou          for (i=0;i<width;i++) {
290*5f2bebf7SJérôme Gardou             dst[i] = dst[i] << shift;
291*5f2bebf7SJérôme Gardou          }
292*5f2bebf7SJérôme Gardou       }
293*5f2bebf7SJérôme Gardou    }
294*5f2bebf7SJérôme Gardou    else {
295*5f2bebf7SJérôme Gardou       /* General case (slow) */
296*5f2bebf7SJérôme Gardou       for (j=0;j<height;j++,y++) {
297*5f2bebf7SJérôme Gardou          GLfloat depth[MAX_WIDTH];
298*5f2bebf7SJérôme Gardou 
299*5f2bebf7SJérôme Gardou          (*ctx->Driver.ReadDepthSpanFloat)( ctx, width, x, y, depth );
300*5f2bebf7SJérôme Gardou 
301*5f2bebf7SJérôme Gardou          if (bias_or_scale) {
302*5f2bebf7SJérôme Gardou             for (i=0;i<width;i++) {
303*5f2bebf7SJérôme Gardou                GLfloat d;
304*5f2bebf7SJérôme Gardou                d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
305*5f2bebf7SJérôme Gardou                depth[i] = CLAMP( d, 0.0, 1.0 );
306*5f2bebf7SJérôme Gardou             }
307*5f2bebf7SJérôme Gardou          }
308*5f2bebf7SJérôme Gardou 
309*5f2bebf7SJérôme Gardou          switch (type) {
310*5f2bebf7SJérôme Gardou             case GL_UNSIGNED_BYTE:
311*5f2bebf7SJérôme Gardou                {
312*5f2bebf7SJérôme Gardou                   GLubyte *dst = (GLubyte *) pixels + start + j * k;
313*5f2bebf7SJérôme Gardou                   for (i=0;i<width;i++) {
314*5f2bebf7SJérôme Gardou                      *dst++ = FLOAT_TO_UBYTE( depth[i] );
315*5f2bebf7SJérôme Gardou                   }
316*5f2bebf7SJérôme Gardou                }
317*5f2bebf7SJérôme Gardou                break;
318*5f2bebf7SJérôme Gardou             case GL_BYTE:
319*5f2bebf7SJérôme Gardou                {
320*5f2bebf7SJérôme Gardou                   GLbyte *dst = (GLbyte *) pixels + start + j * k;
321*5f2bebf7SJérôme Gardou                   for (i=0;i<width;i++) {
322*5f2bebf7SJérôme Gardou                      *dst++ = FLOAT_TO_BYTE( depth[i] );
323*5f2bebf7SJérôme Gardou                   }
324*5f2bebf7SJérôme Gardou                }
325*5f2bebf7SJérôme Gardou                break;
326*5f2bebf7SJérôme Gardou             case GL_UNSIGNED_SHORT:
327*5f2bebf7SJérôme Gardou                {
328*5f2bebf7SJérôme Gardou                   GLushort *dst = (GLushort *) pixels + start + j * k;
329*5f2bebf7SJérôme Gardou                   for (i=0;i<width;i++) {
330*5f2bebf7SJérôme Gardou                      *dst++ = FLOAT_TO_USHORT( depth[i] );
331*5f2bebf7SJérôme Gardou                   }
332*5f2bebf7SJérôme Gardou                   if (ctx->Pack.SwapBytes) {
333*5f2bebf7SJérôme Gardou                      gl_swap2( (GLushort *) pixels + start + j * k, width );
334*5f2bebf7SJérôme Gardou                   }
335*5f2bebf7SJérôme Gardou                }
336*5f2bebf7SJérôme Gardou                break;
337*5f2bebf7SJérôme Gardou             case GL_SHORT:
338*5f2bebf7SJérôme Gardou                {
339*5f2bebf7SJérôme Gardou                   GLshort *dst = (GLshort *) pixels + start + j * k;
340*5f2bebf7SJérôme Gardou                   for (i=0;i<width;i++) {
341*5f2bebf7SJérôme Gardou                      *dst++ = FLOAT_TO_SHORT( depth[i] );
342*5f2bebf7SJérôme Gardou                   }
343*5f2bebf7SJérôme Gardou                   if (ctx->Pack.SwapBytes) {
344*5f2bebf7SJérôme Gardou                      gl_swap2( (GLushort *) pixels + start + j * k, width );
345*5f2bebf7SJérôme Gardou                   }
346*5f2bebf7SJérôme Gardou                }
347*5f2bebf7SJérôme Gardou                break;
348*5f2bebf7SJérôme Gardou             case GL_UNSIGNED_INT:
349*5f2bebf7SJérôme Gardou                {
350*5f2bebf7SJérôme Gardou                   GLuint *dst = (GLuint *) pixels + start + j * k;
351*5f2bebf7SJérôme Gardou                   for (i=0;i<width;i++) {
352*5f2bebf7SJérôme Gardou                      *dst++ = FLOAT_TO_UINT( depth[i] );
353*5f2bebf7SJérôme Gardou                   }
354*5f2bebf7SJérôme Gardou                   if (ctx->Pack.SwapBytes) {
355*5f2bebf7SJérôme Gardou                      gl_swap4( (GLuint *) pixels + start + j * k, width );
356*5f2bebf7SJérôme Gardou                   }
357*5f2bebf7SJérôme Gardou                }
358*5f2bebf7SJérôme Gardou                break;
359*5f2bebf7SJérôme Gardou             case GL_INT:
360*5f2bebf7SJérôme Gardou                {
361*5f2bebf7SJérôme Gardou                   GLint *dst = (GLint *) pixels + start + j * k;
362*5f2bebf7SJérôme Gardou                   for (i=0;i<width;i++) {
363*5f2bebf7SJérôme Gardou                      *dst++ = FLOAT_TO_INT( depth[i] );
364*5f2bebf7SJérôme Gardou                   }
365*5f2bebf7SJérôme Gardou                   if (ctx->Pack.SwapBytes) {
366*5f2bebf7SJérôme Gardou                      gl_swap4( (GLuint *) pixels + start + j * k, width );
367*5f2bebf7SJérôme Gardou                   }
368*5f2bebf7SJérôme Gardou                }
369*5f2bebf7SJérôme Gardou                break;
370*5f2bebf7SJérôme Gardou             case GL_FLOAT:
371*5f2bebf7SJérôme Gardou                {
372*5f2bebf7SJérôme Gardou                   GLfloat *dst = (GLfloat *) pixels + start + j * k;
373*5f2bebf7SJérôme Gardou                   for (i=0;i<width;i++) {
374*5f2bebf7SJérôme Gardou                      *dst++ = depth[i];
375*5f2bebf7SJérôme Gardou                   }
376*5f2bebf7SJérôme Gardou                   if (ctx->Pack.SwapBytes) {
377*5f2bebf7SJérôme Gardou                      gl_swap4( (GLuint *) pixels + start + j * k, width );
378*5f2bebf7SJérôme Gardou                   }
379*5f2bebf7SJérôme Gardou                }
380*5f2bebf7SJérôme Gardou                break;
381*5f2bebf7SJérôme Gardou             default:
382*5f2bebf7SJérôme Gardou                gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
383*5f2bebf7SJérôme Gardou          }
384*5f2bebf7SJérôme Gardou       }
385*5f2bebf7SJérôme Gardou    }
386*5f2bebf7SJérôme Gardou }
387*5f2bebf7SJérôme Gardou 
388*5f2bebf7SJérôme Gardou 
389*5f2bebf7SJérôme Gardou 
390*5f2bebf7SJérôme Gardou 
read_stencil_pixels(GLcontext * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels)391*5f2bebf7SJérôme Gardou static void read_stencil_pixels( GLcontext *ctx,
392*5f2bebf7SJérôme Gardou                                  GLint x, GLint y,
393*5f2bebf7SJérôme Gardou 				 GLsizei width, GLsizei height,
394*5f2bebf7SJérôme Gardou 				 GLenum type, GLvoid *pixels )
395*5f2bebf7SJérôme Gardou {
396*5f2bebf7SJérôme Gardou    GLint i, j;
397*5f2bebf7SJérôme Gardou    GLuint a, s, k, l, start;
398*5f2bebf7SJérôme Gardou    GLboolean shift_or_offset;
399*5f2bebf7SJérôme Gardou 
400*5f2bebf7SJérôme Gardou    if (ctx->Visual->StencilBits<=0) {
401*5f2bebf7SJérôme Gardou       /* No stencil buffer */
402*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
403*5f2bebf7SJérôme Gardou       return;
404*5f2bebf7SJérôme Gardou    }
405*5f2bebf7SJérôme Gardou 
406*5f2bebf7SJérôme Gardou    shift_or_offset = ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0;
407*5f2bebf7SJérôme Gardou 
408*5f2bebf7SJérôme Gardou    /* Size of each component */
409*5f2bebf7SJérôme Gardou    s = gl_sizeof_type( type );
410*5f2bebf7SJérôme Gardou    if (s<=0) {
411*5f2bebf7SJérôme Gardou       gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
412*5f2bebf7SJérôme Gardou       return;
413*5f2bebf7SJérôme Gardou    }
414*5f2bebf7SJérôme Gardou 
415*5f2bebf7SJérôme Gardou    /* Compute packing parameters */
416*5f2bebf7SJérôme Gardou    a = ctx->Pack.Alignment;
417*5f2bebf7SJérôme Gardou    if (ctx->Pack.RowLength>0) {
418*5f2bebf7SJérôme Gardou       l = ctx->Pack.RowLength;
419*5f2bebf7SJérôme Gardou    }
420*5f2bebf7SJérôme Gardou    else {
421*5f2bebf7SJérôme Gardou       l = width;
422*5f2bebf7SJérôme Gardou    }
423*5f2bebf7SJérôme Gardou    /* k = offset between rows in components */
424*5f2bebf7SJérôme Gardou    if (s>=a) {
425*5f2bebf7SJérôme Gardou       k = l;
426*5f2bebf7SJérôme Gardou    }
427*5f2bebf7SJérôme Gardou    else {
428*5f2bebf7SJérôme Gardou       k = a/s * CEILING( s*l, a );
429*5f2bebf7SJérôme Gardou    }
430*5f2bebf7SJérôme Gardou 
431*5f2bebf7SJérôme Gardou    /* offset to first component returned */
432*5f2bebf7SJérôme Gardou    start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels;
433*5f2bebf7SJérôme Gardou 
434*5f2bebf7SJérôme Gardou    /* process image row by row */
435*5f2bebf7SJérôme Gardou    for (j=0;j<height;j++,y++) {
436*5f2bebf7SJérôme Gardou       GLubyte stencil[MAX_WIDTH];
437*5f2bebf7SJérôme Gardou 
438*5f2bebf7SJérôme Gardou       gl_read_stencil_span( ctx, width, x, y, stencil );
439*5f2bebf7SJérôme Gardou 
440*5f2bebf7SJérôme Gardou       if (shift_or_offset) {
441*5f2bebf7SJérôme Gardou 	 GLuint s;
442*5f2bebf7SJérôme Gardou 	 if (ctx->Pixel.IndexShift<0) {
443*5f2bebf7SJérôme Gardou 	    /* right shift */
444*5f2bebf7SJérôme Gardou 	    s = -ctx->Pixel.IndexShift;
445*5f2bebf7SJérôme Gardou 	    for (i=0;i<width;i++) {
446*5f2bebf7SJérôme Gardou 	       stencil[i] = (stencil[i] >> s) + ctx->Pixel.IndexOffset;
447*5f2bebf7SJérôme Gardou 	    }
448*5f2bebf7SJérôme Gardou 	 }
449*5f2bebf7SJérôme Gardou 	 else {
450*5f2bebf7SJérôme Gardou 	    /* left shift */
451*5f2bebf7SJérôme Gardou 	    s = ctx->Pixel.IndexShift;
452*5f2bebf7SJérôme Gardou 	    for (i=0;i<width;i++) {
453*5f2bebf7SJérôme Gardou 	       stencil[i] = (stencil[i] << s) + ctx->Pixel.IndexOffset;
454*5f2bebf7SJérôme Gardou 	    }
455*5f2bebf7SJérôme Gardou 	 }
456*5f2bebf7SJérôme Gardou       }
457*5f2bebf7SJérôme Gardou 
458*5f2bebf7SJérôme Gardou       if (ctx->Pixel.MapStencilFlag) {
459*5f2bebf7SJérôme Gardou 	 for (i=0;i<width;i++) {
460*5f2bebf7SJérôme Gardou 	    stencil[i] = ctx->Pixel.MapStoS[ stencil[i] ];
461*5f2bebf7SJérôme Gardou 	 }
462*5f2bebf7SJérôme Gardou       }
463*5f2bebf7SJérôme Gardou 
464*5f2bebf7SJérôme Gardou       switch (type) {
465*5f2bebf7SJérôme Gardou 	 case GL_UNSIGNED_BYTE:
466*5f2bebf7SJérôme Gardou 	    {
467*5f2bebf7SJérôme Gardou 	       GLubyte *dst = (GLubyte *) pixels + start + j * k;
468*5f2bebf7SJérôme Gardou 	       MEMCPY( dst, stencil, width );
469*5f2bebf7SJérôme Gardou 	    }
470*5f2bebf7SJérôme Gardou 	    break;
471*5f2bebf7SJérôme Gardou 	 case GL_BYTE:
472*5f2bebf7SJérôme Gardou 	    {
473*5f2bebf7SJérôme Gardou 	       GLbyte *dst = (GLbyte  *) pixels + start + j * k;
474*5f2bebf7SJérôme Gardou 	       MEMCPY( dst, stencil, width );
475*5f2bebf7SJérôme Gardou 	    }
476*5f2bebf7SJérôme Gardou 	    break;
477*5f2bebf7SJérôme Gardou 	 case GL_UNSIGNED_SHORT:
478*5f2bebf7SJérôme Gardou 	    {
479*5f2bebf7SJérôme Gardou 	       GLushort *dst = (GLushort *) pixels + start + j * k;
480*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
481*5f2bebf7SJérôme Gardou 		  *dst++ = (GLushort) stencil[i];
482*5f2bebf7SJérôme Gardou 	       }
483*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
484*5f2bebf7SJérôme Gardou 		  gl_swap2( (GLushort *) pixels + start +j * k, width );
485*5f2bebf7SJérôme Gardou 	       }
486*5f2bebf7SJérôme Gardou 	    }
487*5f2bebf7SJérôme Gardou 	    break;
488*5f2bebf7SJérôme Gardou 	 case GL_SHORT:
489*5f2bebf7SJérôme Gardou 	    {
490*5f2bebf7SJérôme Gardou 	       GLshort *dst = (GLshort *) pixels + start + j * k;
491*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
492*5f2bebf7SJérôme Gardou 		  *dst++ = (GLshort) stencil[i];
493*5f2bebf7SJérôme Gardou 	       }
494*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
495*5f2bebf7SJérôme Gardou 		  gl_swap2( (GLushort *) pixels + start +j * k, width );
496*5f2bebf7SJérôme Gardou 	       }
497*5f2bebf7SJérôme Gardou 	    }
498*5f2bebf7SJérôme Gardou 	    break;
499*5f2bebf7SJérôme Gardou 	 case GL_UNSIGNED_INT:
500*5f2bebf7SJérôme Gardou 	    {
501*5f2bebf7SJérôme Gardou 	       GLuint *dst = (GLuint *) pixels + start + j * k;
502*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
503*5f2bebf7SJérôme Gardou 		  *dst++ = (GLuint) stencil[i];
504*5f2bebf7SJérôme Gardou 	       }
505*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
506*5f2bebf7SJérôme Gardou 		  gl_swap4( (GLuint *) pixels + start +j * k, width );
507*5f2bebf7SJérôme Gardou 	       }
508*5f2bebf7SJérôme Gardou 	    }
509*5f2bebf7SJérôme Gardou 	    break;
510*5f2bebf7SJérôme Gardou 	 case GL_INT:
511*5f2bebf7SJérôme Gardou 	    {
512*5f2bebf7SJérôme Gardou 	       GLint *dst = (GLint *) pixels + start + j * k;
513*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
514*5f2bebf7SJérôme Gardou 		  *dst++ = (GLint) stencil[i];
515*5f2bebf7SJérôme Gardou 	       }
516*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
517*5f2bebf7SJérôme Gardou 		  gl_swap4( (GLuint *) pixels + start +j * k, width );
518*5f2bebf7SJérôme Gardou 	       }
519*5f2bebf7SJérôme Gardou 	    }
520*5f2bebf7SJérôme Gardou 	    break;
521*5f2bebf7SJérôme Gardou 	 case GL_FLOAT:
522*5f2bebf7SJérôme Gardou 	    {
523*5f2bebf7SJérôme Gardou 	       GLfloat *dst = (GLfloat *) pixels + start + j * k;
524*5f2bebf7SJérôme Gardou 	       for (i=0;i<width;i++) {
525*5f2bebf7SJérôme Gardou 		  *dst++ = (GLfloat) stencil[i];
526*5f2bebf7SJérôme Gardou 	       }
527*5f2bebf7SJérôme Gardou 	       if (ctx->Pack.SwapBytes) {
528*5f2bebf7SJérôme Gardou 		  gl_swap4( (GLuint *) pixels + start +j * k, width );
529*5f2bebf7SJérôme Gardou 	       }
530*5f2bebf7SJérôme Gardou 	    }
531*5f2bebf7SJérôme Gardou 	    break;
532*5f2bebf7SJérôme Gardou          default:
533*5f2bebf7SJérôme Gardou             gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
534*5f2bebf7SJérôme Gardou       }
535*5f2bebf7SJérôme Gardou    }
536*5f2bebf7SJérôme Gardou }
537*5f2bebf7SJérôme Gardou 
538*5f2bebf7SJérôme Gardou 
539*5f2bebf7SJérôme Gardou 
540*5f2bebf7SJérôme Gardou /*
541*5f2bebf7SJérôme Gardou  * Test if scaling or biasing of colors is needed.
542*5f2bebf7SJérôme Gardou  */
scale_or_bias_rgba(GLcontext * ctx)543*5f2bebf7SJérôme Gardou static GLboolean scale_or_bias_rgba( GLcontext *ctx )
544*5f2bebf7SJérôme Gardou {
545*5f2bebf7SJérôme Gardou    if (ctx->Pixel.RedScale!=1.0F   || ctx->Pixel.RedBias!=0.0F ||
546*5f2bebf7SJérôme Gardou        ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F ||
547*5f2bebf7SJérôme Gardou        ctx->Pixel.BlueScale!=1.0F  || ctx->Pixel.BlueBias!=0.0F ||
548*5f2bebf7SJérôme Gardou        ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) {
549*5f2bebf7SJérôme Gardou       return GL_TRUE;
550*5f2bebf7SJérôme Gardou    }
551*5f2bebf7SJérôme Gardou    else {
552*5f2bebf7SJérôme Gardou       return GL_FALSE;
553*5f2bebf7SJérôme Gardou    }
554*5f2bebf7SJérôme Gardou }
555*5f2bebf7SJérôme Gardou 
556*5f2bebf7SJérôme Gardou 
557*5f2bebf7SJérôme Gardou 
558*5f2bebf7SJérôme Gardou /*
559*5f2bebf7SJérôme Gardou  * Apply scale and bias factors to an array of RGBA pixels.
560*5f2bebf7SJérôme Gardou  */
scale_and_bias_rgba(GLcontext * ctx,GLint n,GLfloat red[],GLfloat green[],GLfloat blue[],GLfloat alpha[])561*5f2bebf7SJérôme Gardou static void scale_and_bias_rgba( GLcontext *ctx,
562*5f2bebf7SJérôme Gardou                                  GLint n,
563*5f2bebf7SJérôme Gardou 				 GLfloat red[], GLfloat green[],
564*5f2bebf7SJérôme Gardou 				 GLfloat blue[], GLfloat alpha[] )
565*5f2bebf7SJérôme Gardou {
566*5f2bebf7SJérôme Gardou    register GLint i;
567*5f2bebf7SJérôme Gardou    register GLfloat r, g, b, a;
568*5f2bebf7SJérôme Gardou 
569*5f2bebf7SJérôme Gardou    for (i=0;i<n;i++) {
570*5f2bebf7SJérôme Gardou       r = red[i]   * ctx->Pixel.RedScale   + ctx->Pixel.RedBias;
571*5f2bebf7SJérôme Gardou       g = green[i] * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
572*5f2bebf7SJérôme Gardou       b = blue[i]  * ctx->Pixel.BlueScale  + ctx->Pixel.BlueBias;
573*5f2bebf7SJérôme Gardou       a = alpha[i] * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
574*5f2bebf7SJérôme Gardou       red[i]   = CLAMP( r, 0.0F, 1.0F );
575*5f2bebf7SJérôme Gardou       green[i] = CLAMP( g, 0.0F, 1.0F );
576*5f2bebf7SJérôme Gardou       blue[i]  = CLAMP( b, 0.0F, 1.0F );
577*5f2bebf7SJérôme Gardou       alpha[i] = CLAMP( a, 0.0F, 1.0F );
578*5f2bebf7SJérôme Gardou    }
579*5f2bebf7SJérôme Gardou }
580*5f2bebf7SJérôme Gardou 
581*5f2bebf7SJérôme Gardou 
582*5f2bebf7SJérôme Gardou 
583*5f2bebf7SJérôme Gardou /*
584*5f2bebf7SJérôme Gardou  * Apply pixel mapping to an array of RGBA pixels.
585*5f2bebf7SJérôme Gardou  */
map_rgba(GLcontext * ctx,GLint n,GLfloat red[],GLfloat green[],GLfloat blue[],GLfloat alpha[])586*5f2bebf7SJérôme Gardou static void map_rgba( GLcontext *ctx,
587*5f2bebf7SJérôme Gardou                       GLint n,
588*5f2bebf7SJérôme Gardou 		      GLfloat red[], GLfloat green[],
589*5f2bebf7SJérôme Gardou 		      GLfloat blue[], GLfloat alpha[] )
590*5f2bebf7SJérôme Gardou {
591*5f2bebf7SJérôme Gardou    GLfloat rscale = ctx->Pixel.MapRtoRsize-1;
592*5f2bebf7SJérôme Gardou    GLfloat gscale = ctx->Pixel.MapGtoGsize-1;
593*5f2bebf7SJérôme Gardou    GLfloat bscale = ctx->Pixel.MapBtoBsize-1;
594*5f2bebf7SJérôme Gardou    GLfloat ascale = ctx->Pixel.MapAtoAsize-1;
595*5f2bebf7SJérôme Gardou    GLint i;
596*5f2bebf7SJérôme Gardou 
597*5f2bebf7SJérôme Gardou    for (i=0;i<n;i++) {
598*5f2bebf7SJérôme Gardou       red[i]   = ctx->Pixel.MapRtoR[ (GLint) (red[i]   * rscale) ];
599*5f2bebf7SJérôme Gardou       green[i] = ctx->Pixel.MapGtoG[ (GLint) (green[i] * gscale) ];
600*5f2bebf7SJérôme Gardou       blue[i]  = ctx->Pixel.MapBtoB[ (GLint) (blue[i]  * bscale) ];
601*5f2bebf7SJérôme Gardou       alpha[i] = ctx->Pixel.MapAtoA[ (GLint) (alpha[i] * ascale) ];
602*5f2bebf7SJérôme Gardou    }
603*5f2bebf7SJérôme Gardou }
604*5f2bebf7SJérôme Gardou 
605*5f2bebf7SJérôme Gardou 
606*5f2bebf7SJérôme Gardou 
607*5f2bebf7SJérôme Gardou 
608*5f2bebf7SJérôme Gardou /*
609*5f2bebf7SJérôme Gardou  * Read R, G, B, A, RGB, L, or LA pixels.
610*5f2bebf7SJérôme Gardou  */
read_color_pixels(GLcontext * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)611*5f2bebf7SJérôme Gardou static void read_color_pixels(GLcontext *ctx, GLint x, GLint y, GLsizei width,
612*5f2bebf7SJérôme Gardou         GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
613*5f2bebf7SJérôme Gardou {
614*5f2bebf7SJérôme Gardou     GLint i, j, n, a, s, l, k;
615*5f2bebf7SJérôme Gardou     GLboolean scale_or_bias;
616*5f2bebf7SJérôme Gardou     DEFARRAY(GLfloat, red, MAX_WIDTH);
617*5f2bebf7SJérôme Gardou     DEFARRAY(GLfloat, green, MAX_WIDTH);
618*5f2bebf7SJérôme Gardou     DEFARRAY(GLfloat, blue, MAX_WIDTH);
619*5f2bebf7SJérôme Gardou     DEFARRAY(GLfloat, alpha, MAX_WIDTH);
620*5f2bebf7SJérôme Gardou     DEFARRAY(GLfloat, luminance, MAX_WIDTH);
621*5f2bebf7SJérôme Gardou     GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
622*5f2bebf7SJérôme Gardou     GLboolean is_bgr = GL_FALSE;
623*5f2bebf7SJérôme Gardou     GLuint start;
624*5f2bebf7SJérôme Gardou 
625*5f2bebf7SJérôme Gardou     scale_or_bias = scale_or_bias_rgba(ctx);
626*5f2bebf7SJérôme Gardou 
627*5f2bebf7SJérôme Gardou     /* Determine how many / which components to return */
628*5f2bebf7SJérôme Gardou     r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
629*5f2bebf7SJérôme Gardou     switch (format)
630*5f2bebf7SJérôme Gardou     {
631*5f2bebf7SJérôme Gardou     case GL_RED:
632*5f2bebf7SJérôme Gardou         r_flag = GL_TRUE;
633*5f2bebf7SJérôme Gardou         n = 1;
634*5f2bebf7SJérôme Gardou         break;
635*5f2bebf7SJérôme Gardou     case GL_GREEN:
636*5f2bebf7SJérôme Gardou         g_flag = GL_TRUE;
637*5f2bebf7SJérôme Gardou         n = 1;
638*5f2bebf7SJérôme Gardou         break;
639*5f2bebf7SJérôme Gardou     case GL_BLUE:
640*5f2bebf7SJérôme Gardou         b_flag = GL_TRUE;
641*5f2bebf7SJérôme Gardou         n = 1;
642*5f2bebf7SJérôme Gardou         break;
643*5f2bebf7SJérôme Gardou     case GL_ALPHA:
644*5f2bebf7SJérôme Gardou         a_flag = GL_TRUE;
645*5f2bebf7SJérôme Gardou         n = 1;
646*5f2bebf7SJérôme Gardou         break;
647*5f2bebf7SJérôme Gardou     case GL_LUMINANCE:
648*5f2bebf7SJérôme Gardou         l_flag = GL_TRUE;
649*5f2bebf7SJérôme Gardou         n = 1;
650*5f2bebf7SJérôme Gardou         break;
651*5f2bebf7SJérôme Gardou     case GL_LUMINANCE_ALPHA:
652*5f2bebf7SJérôme Gardou         l_flag = a_flag = GL_TRUE;
653*5f2bebf7SJérôme Gardou         n = 2;
654*5f2bebf7SJérôme Gardou         break;
655*5f2bebf7SJérôme Gardou     case GL_RGB:
656*5f2bebf7SJérôme Gardou         r_flag = g_flag = b_flag = GL_TRUE;
657*5f2bebf7SJérôme Gardou         n = 3;
658*5f2bebf7SJérôme Gardou         break;
659*5f2bebf7SJérôme Gardou     case GL_BGR_EXT:
660*5f2bebf7SJérôme Gardou         r_flag = g_flag = b_flag = GL_TRUE;
661*5f2bebf7SJérôme Gardou         n = 3;
662*5f2bebf7SJérôme Gardou         is_bgr = GL_TRUE;
663*5f2bebf7SJérôme Gardou         break;
664*5f2bebf7SJérôme Gardou     case GL_RGBA:
665*5f2bebf7SJérôme Gardou         r_flag = g_flag = b_flag = a_flag = GL_TRUE;
666*5f2bebf7SJérôme Gardou         n = 4;
667*5f2bebf7SJérôme Gardou         break;
668*5f2bebf7SJérôme Gardou     case GL_BGRA_EXT:
669*5f2bebf7SJérôme Gardou         r_flag = g_flag = b_flag = a_flag = GL_TRUE;
670*5f2bebf7SJérôme Gardou         n = 4;
671*5f2bebf7SJérôme Gardou         is_bgr = GL_TRUE;
672*5f2bebf7SJérôme Gardou         break;
673*5f2bebf7SJérôme Gardou     default:
674*5f2bebf7SJérôme Gardou         gl_error(ctx, GL_INVALID_ENUM, "glReadPixels(format)");
675*5f2bebf7SJérôme Gardou         UNDEFARRAY( red );
676*5f2bebf7SJérôme Gardou         UNDEFARRAY( green );
677*5f2bebf7SJérôme Gardou         UNDEFARRAY( blue );
678*5f2bebf7SJérôme Gardou         UNDEFARRAY( alpha );
679*5f2bebf7SJérôme Gardou         UNDEFARRAY( luminance );
680*5f2bebf7SJérôme Gardou         return;
681*5f2bebf7SJérôme Gardou     }
682*5f2bebf7SJérôme Gardou 
683*5f2bebf7SJérôme Gardou     /* Size of each component */
684*5f2bebf7SJérôme Gardou     s = gl_sizeof_type(type);
685*5f2bebf7SJérôme Gardou     if (s <= 0)
686*5f2bebf7SJérôme Gardou     {
687*5f2bebf7SJérôme Gardou         gl_error(ctx, GL_INVALID_ENUM, "glReadPixels(type)");
688*5f2bebf7SJérôme Gardou         UNDEFARRAY( red );
689*5f2bebf7SJérôme Gardou         UNDEFARRAY( green );
690*5f2bebf7SJérôme Gardou         UNDEFARRAY( blue );
691*5f2bebf7SJérôme Gardou         UNDEFARRAY( alpha );
692*5f2bebf7SJérôme Gardou         UNDEFARRAY( luminance );
693*5f2bebf7SJérôme Gardou         return;
694*5f2bebf7SJérôme Gardou     }
695*5f2bebf7SJérôme Gardou 
696*5f2bebf7SJérôme Gardou     /* Compute packing parameters */
697*5f2bebf7SJérôme Gardou     a = ctx->Pack.Alignment;
698*5f2bebf7SJérôme Gardou     if (ctx->Pack.RowLength > 0)
699*5f2bebf7SJérôme Gardou     {
700*5f2bebf7SJérôme Gardou         l = ctx->Pack.RowLength;
701*5f2bebf7SJérôme Gardou     }
702*5f2bebf7SJérôme Gardou     else
703*5f2bebf7SJérôme Gardou     {
704*5f2bebf7SJérôme Gardou         l = width;
705*5f2bebf7SJérôme Gardou     }
706*5f2bebf7SJérôme Gardou     /* k = offset between rows in components */
707*5f2bebf7SJérôme Gardou     if (s >= a)
708*5f2bebf7SJérôme Gardou     {
709*5f2bebf7SJérôme Gardou         k = n * l;
710*5f2bebf7SJérôme Gardou     }
711*5f2bebf7SJérôme Gardou     else
712*5f2bebf7SJérôme Gardou     {
713*5f2bebf7SJérôme Gardou         k = a / s * CEILING(s * n * l, a);
714*5f2bebf7SJérôme Gardou     }
715*5f2bebf7SJérôme Gardou 
716*5f2bebf7SJérôme Gardou     /* offset to first component returned */
717*5f2bebf7SJérôme Gardou     start = ctx->Pack.SkipRows * k + ctx->Pack.SkipPixels * n;
718*5f2bebf7SJérôme Gardou 
719*5f2bebf7SJérôme Gardou     /* process image row by row */
720*5f2bebf7SJérôme Gardou     for (j = 0; j < height; j++, y++)
721*5f2bebf7SJérôme Gardou     {
722*5f2bebf7SJérôme Gardou         /*
723*5f2bebf7SJérôme Gardou          * Read the pixels from frame buffer
724*5f2bebf7SJérôme Gardou          */
725*5f2bebf7SJérôme Gardou         if (ctx->Visual->RGBAflag)
726*5f2bebf7SJérôme Gardou         {
727*5f2bebf7SJérôme Gardou             DEFARRAY(GLubyte, r, MAX_WIDTH);
728*5f2bebf7SJérôme Gardou             DEFARRAY(GLubyte, g, MAX_WIDTH);
729*5f2bebf7SJérôme Gardou             DEFARRAY(GLubyte, b, MAX_WIDTH);
730*5f2bebf7SJérôme Gardou             DEFARRAY(GLubyte, a, MAX_WIDTH);
731*5f2bebf7SJérôme Gardou             GLfloat rscale = 1.0F * ctx->Visual->InvRedScale;
732*5f2bebf7SJérôme Gardou             GLfloat gscale = 1.0F * ctx->Visual->InvGreenScale;
733*5f2bebf7SJérôme Gardou             GLfloat bscale = 1.0F * ctx->Visual->InvBlueScale;
734*5f2bebf7SJérôme Gardou             GLfloat ascale = 1.0F * ctx->Visual->InvAlphaScale;
735*5f2bebf7SJérôme Gardou 
736*5f2bebf7SJérôme Gardou             /* read colors and convert to floats */
737*5f2bebf7SJérôme Gardou             (*ctx->Driver.ReadColorSpan)(ctx, width, x, y, r, g, b, a);
738*5f2bebf7SJérôme Gardou             if (ctx->RasterMask & ALPHABUF_BIT)
739*5f2bebf7SJérôme Gardou             {
740*5f2bebf7SJérôme Gardou                 gl_read_alpha_span(ctx, width, x, y, a);
741*5f2bebf7SJérôme Gardou             }
742*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
743*5f2bebf7SJérôme Gardou             {
744*5f2bebf7SJérôme Gardou                 red[i] = r[i] * rscale;
745*5f2bebf7SJérôme Gardou                 green[i] = g[i] * gscale;
746*5f2bebf7SJérôme Gardou                 blue[i] = b[i] * bscale;
747*5f2bebf7SJérôme Gardou                 alpha[i] = a[i] * ascale;
748*5f2bebf7SJérôme Gardou             }
749*5f2bebf7SJérôme Gardou 
750*5f2bebf7SJérôme Gardou             if (scale_or_bias)
751*5f2bebf7SJérôme Gardou             {
752*5f2bebf7SJérôme Gardou                 scale_and_bias_rgba(ctx, width, red, green, blue, alpha);
753*5f2bebf7SJérôme Gardou             }
754*5f2bebf7SJérôme Gardou             if (ctx->Pixel.MapColorFlag)
755*5f2bebf7SJérôme Gardou             {
756*5f2bebf7SJérôme Gardou                 map_rgba(ctx, width, red, green, blue, alpha);
757*5f2bebf7SJérôme Gardou             }
758*5f2bebf7SJérôme Gardou             UNDEFARRAY(r);
759*5f2bebf7SJérôme Gardou             UNDEFARRAY(g);
760*5f2bebf7SJérôme Gardou             UNDEFARRAY(b);
761*5f2bebf7SJérôme Gardou             UNDEFARRAY(a);
762*5f2bebf7SJérôme Gardou         }
763*5f2bebf7SJérôme Gardou         else
764*5f2bebf7SJérôme Gardou         {
765*5f2bebf7SJérôme Gardou             /* convert CI values to RGBA */
766*5f2bebf7SJérôme Gardou             GLuint index[MAX_WIDTH];
767*5f2bebf7SJérôme Gardou             (*ctx->Driver.ReadIndexSpan)(ctx, width, x, y, index);
768*5f2bebf7SJérôme Gardou 
769*5f2bebf7SJérôme Gardou             if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0)
770*5f2bebf7SJérôme Gardou             {
771*5f2bebf7SJérôme Gardou                 GLuint s;
772*5f2bebf7SJérôme Gardou                 if (ctx->Pixel.IndexShift < 0)
773*5f2bebf7SJérôme Gardou                 {
774*5f2bebf7SJérôme Gardou                     /* right shift */
775*5f2bebf7SJérôme Gardou                     s = -ctx->Pixel.IndexShift;
776*5f2bebf7SJérôme Gardou                     for (i = 0; i < width; i++)
777*5f2bebf7SJérôme Gardou                     {
778*5f2bebf7SJérôme Gardou                         index[i] = (index[i] >> s) + ctx->Pixel.IndexOffset;
779*5f2bebf7SJérôme Gardou                     }
780*5f2bebf7SJérôme Gardou                 }
781*5f2bebf7SJérôme Gardou                 else
782*5f2bebf7SJérôme Gardou                 {
783*5f2bebf7SJérôme Gardou                     /* left shift */
784*5f2bebf7SJérôme Gardou                     s = ctx->Pixel.IndexShift;
785*5f2bebf7SJérôme Gardou                     for (i = 0; i < width; i++)
786*5f2bebf7SJérôme Gardou                     {
787*5f2bebf7SJérôme Gardou                         index[i] = (index[i] << s) + ctx->Pixel.IndexOffset;
788*5f2bebf7SJérôme Gardou                     }
789*5f2bebf7SJérôme Gardou                 }
790*5f2bebf7SJérôme Gardou             }
791*5f2bebf7SJérôme Gardou 
792*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
793*5f2bebf7SJérôme Gardou             {
794*5f2bebf7SJérôme Gardou                 red[i] = ctx->Pixel.MapItoR[index[i]];
795*5f2bebf7SJérôme Gardou                 green[i] = ctx->Pixel.MapItoG[index[i]];
796*5f2bebf7SJérôme Gardou                 blue[i] = ctx->Pixel.MapItoB[index[i]];
797*5f2bebf7SJérôme Gardou                 alpha[i] = ctx->Pixel.MapItoA[index[i]];
798*5f2bebf7SJérôme Gardou             }
799*5f2bebf7SJérôme Gardou         }
800*5f2bebf7SJérôme Gardou 
801*5f2bebf7SJérôme Gardou         if (l_flag)
802*5f2bebf7SJérôme Gardou         {
803*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
804*5f2bebf7SJérôme Gardou             {
805*5f2bebf7SJérôme Gardou                 GLfloat sum = red[i] + green[i] + blue[i];
806*5f2bebf7SJérôme Gardou                 luminance[i] = CLAMP(sum, 0.0F, 1.0F);
807*5f2bebf7SJérôme Gardou             }
808*5f2bebf7SJérôme Gardou         }
809*5f2bebf7SJérôme Gardou 
810*5f2bebf7SJérôme Gardou         /*
811*5f2bebf7SJérôme Gardou          * Pack/transfer/store the pixels
812*5f2bebf7SJérôme Gardou          */
813*5f2bebf7SJérôme Gardou 
814*5f2bebf7SJérôme Gardou         switch (type)
815*5f2bebf7SJérôme Gardou         {
816*5f2bebf7SJérôme Gardou         case GL_UNSIGNED_BYTE:
817*5f2bebf7SJérôme Gardou         {
818*5f2bebf7SJérôme Gardou             GLubyte *dst = (GLubyte *) pixels + start + j * k;
819*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
820*5f2bebf7SJérôme Gardou             {
821*5f2bebf7SJérôme Gardou                 if (is_bgr)
822*5f2bebf7SJérôme Gardou                 {
823*5f2bebf7SJérôme Gardou                     if (b_flag)
824*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UBYTE(blue[i]);
825*5f2bebf7SJérôme Gardou                     if (g_flag)
826*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UBYTE(green[i]);
827*5f2bebf7SJérôme Gardou                     if (r_flag)
828*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UBYTE(red[i]);
829*5f2bebf7SJérôme Gardou                 }
830*5f2bebf7SJérôme Gardou                 else
831*5f2bebf7SJérôme Gardou                 {
832*5f2bebf7SJérôme Gardou                     if (r_flag)
833*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UBYTE(red[i]);
834*5f2bebf7SJérôme Gardou                     if (g_flag)
835*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UBYTE(green[i]);
836*5f2bebf7SJérôme Gardou                     if (b_flag)
837*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UBYTE(blue[i]);
838*5f2bebf7SJérôme Gardou                 }
839*5f2bebf7SJérôme Gardou                 if (l_flag)
840*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_UBYTE(luminance[i]);
841*5f2bebf7SJérôme Gardou                 if (a_flag)
842*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_UBYTE(alpha[i]);
843*5f2bebf7SJérôme Gardou             }
844*5f2bebf7SJérôme Gardou             break;
845*5f2bebf7SJérôme Gardou         }
846*5f2bebf7SJérôme Gardou         case GL_BYTE:
847*5f2bebf7SJérôme Gardou         {
848*5f2bebf7SJérôme Gardou             GLbyte *dst = (GLbyte *) pixels + start + j * k;
849*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
850*5f2bebf7SJérôme Gardou             {
851*5f2bebf7SJérôme Gardou                 if (is_bgr)
852*5f2bebf7SJérôme Gardou                 {
853*5f2bebf7SJérôme Gardou                     if (b_flag)
854*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_BYTE(blue[i]);
855*5f2bebf7SJérôme Gardou                     if (g_flag)
856*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_BYTE(green[i]);
857*5f2bebf7SJérôme Gardou                     if (r_flag)
858*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_BYTE(red[i]);
859*5f2bebf7SJérôme Gardou                 }
860*5f2bebf7SJérôme Gardou                 else
861*5f2bebf7SJérôme Gardou                 {
862*5f2bebf7SJérôme Gardou                     if (r_flag)
863*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_BYTE(red[i]);
864*5f2bebf7SJérôme Gardou                     if (g_flag)
865*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_BYTE(green[i]);
866*5f2bebf7SJérôme Gardou                     if (b_flag)
867*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_BYTE(blue[i]);
868*5f2bebf7SJérôme Gardou                 }
869*5f2bebf7SJérôme Gardou                 if (l_flag)
870*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_BYTE(luminance[i]);
871*5f2bebf7SJérôme Gardou                 if (a_flag)
872*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_BYTE(alpha[i]);
873*5f2bebf7SJérôme Gardou             }
874*5f2bebf7SJérôme Gardou             break;
875*5f2bebf7SJérôme Gardou         }
876*5f2bebf7SJérôme Gardou         case GL_UNSIGNED_SHORT:
877*5f2bebf7SJérôme Gardou         {
878*5f2bebf7SJérôme Gardou             GLushort *dst = (GLushort *) pixels + start + j * k;
879*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
880*5f2bebf7SJérôme Gardou             {
881*5f2bebf7SJérôme Gardou                 if (is_bgr)
882*5f2bebf7SJérôme Gardou                 {
883*5f2bebf7SJérôme Gardou                     if (b_flag)
884*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_USHORT(blue[i]);
885*5f2bebf7SJérôme Gardou                     if (g_flag)
886*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_USHORT(green[i]);
887*5f2bebf7SJérôme Gardou                     if (r_flag)
888*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_USHORT(red[i]);
889*5f2bebf7SJérôme Gardou                 }
890*5f2bebf7SJérôme Gardou                 else
891*5f2bebf7SJérôme Gardou                 {
892*5f2bebf7SJérôme Gardou                     if (r_flag)
893*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_USHORT(red[i]);
894*5f2bebf7SJérôme Gardou                     if (g_flag)
895*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_USHORT(green[i]);
896*5f2bebf7SJérôme Gardou                     if (b_flag)
897*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_USHORT(blue[i]);
898*5f2bebf7SJérôme Gardou                 }
899*5f2bebf7SJérôme Gardou                 if (l_flag)
900*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_USHORT(luminance[i]);
901*5f2bebf7SJérôme Gardou                 if (a_flag)
902*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_USHORT(alpha[i]);
903*5f2bebf7SJérôme Gardou             }
904*5f2bebf7SJérôme Gardou             if (ctx->Pack.SwapBytes)
905*5f2bebf7SJérôme Gardou             {
906*5f2bebf7SJérôme Gardou                 gl_swap2((GLushort *) pixels + start + j * k, width * n);
907*5f2bebf7SJérôme Gardou             }
908*5f2bebf7SJérôme Gardou             break;
909*5f2bebf7SJérôme Gardou         }
910*5f2bebf7SJérôme Gardou         case GL_SHORT:
911*5f2bebf7SJérôme Gardou         {
912*5f2bebf7SJérôme Gardou             GLshort *dst = (GLshort *) pixels + start + j * k;
913*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
914*5f2bebf7SJérôme Gardou             {
915*5f2bebf7SJérôme Gardou                 if (is_bgr)
916*5f2bebf7SJérôme Gardou                 {
917*5f2bebf7SJérôme Gardou                     if (b_flag)
918*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_SHORT(blue[i]);
919*5f2bebf7SJérôme Gardou                     if (g_flag)
920*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_SHORT(green[i]);
921*5f2bebf7SJérôme Gardou                     if (r_flag)
922*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_SHORT(red[i]);
923*5f2bebf7SJérôme Gardou                 }
924*5f2bebf7SJérôme Gardou                 else
925*5f2bebf7SJérôme Gardou                 {
926*5f2bebf7SJérôme Gardou                     if (r_flag)
927*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_SHORT(red[i]);
928*5f2bebf7SJérôme Gardou                     if (g_flag)
929*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_SHORT(green[i]);
930*5f2bebf7SJérôme Gardou                     if (b_flag)
931*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_SHORT(blue[i]);
932*5f2bebf7SJérôme Gardou                 }
933*5f2bebf7SJérôme Gardou                 if (l_flag)
934*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_SHORT(luminance[i]);
935*5f2bebf7SJérôme Gardou                 if (a_flag)
936*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_SHORT(alpha[i]);
937*5f2bebf7SJérôme Gardou             }
938*5f2bebf7SJérôme Gardou             if (ctx->Pack.SwapBytes)
939*5f2bebf7SJérôme Gardou             {
940*5f2bebf7SJérôme Gardou                 gl_swap2((GLushort *) pixels + start + j * k, width * n);
941*5f2bebf7SJérôme Gardou             }
942*5f2bebf7SJérôme Gardou             break;
943*5f2bebf7SJérôme Gardou         }
944*5f2bebf7SJérôme Gardou         case GL_UNSIGNED_INT:
945*5f2bebf7SJérôme Gardou         {
946*5f2bebf7SJérôme Gardou             GLuint *dst = (GLuint *) pixels + start + j * k;
947*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
948*5f2bebf7SJérôme Gardou             {
949*5f2bebf7SJérôme Gardou                 if (is_bgr)
950*5f2bebf7SJérôme Gardou                 {
951*5f2bebf7SJérôme Gardou                     if (b_flag)
952*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UINT(blue[i]);
953*5f2bebf7SJérôme Gardou                     if (g_flag)
954*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UINT(green[i]);
955*5f2bebf7SJérôme Gardou                     if (r_flag)
956*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UINT(red[i]);
957*5f2bebf7SJérôme Gardou                 }
958*5f2bebf7SJérôme Gardou                 else
959*5f2bebf7SJérôme Gardou                 {
960*5f2bebf7SJérôme Gardou                     if (r_flag)
961*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UINT(red[i]);
962*5f2bebf7SJérôme Gardou                     if (g_flag)
963*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UINT(green[i]);
964*5f2bebf7SJérôme Gardou                     if (b_flag)
965*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_UINT(blue[i]);
966*5f2bebf7SJérôme Gardou                 }
967*5f2bebf7SJérôme Gardou                 if (l_flag)
968*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_UINT(luminance[i]);
969*5f2bebf7SJérôme Gardou                 if (a_flag)
970*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_UINT(alpha[i]);
971*5f2bebf7SJérôme Gardou             }
972*5f2bebf7SJérôme Gardou             if (ctx->Pack.SwapBytes)
973*5f2bebf7SJérôme Gardou             {
974*5f2bebf7SJérôme Gardou                 gl_swap4((GLuint *) pixels + start + j * k, width * n);
975*5f2bebf7SJérôme Gardou             }
976*5f2bebf7SJérôme Gardou             break;
977*5f2bebf7SJérôme Gardou         }
978*5f2bebf7SJérôme Gardou         case GL_INT:
979*5f2bebf7SJérôme Gardou         {
980*5f2bebf7SJérôme Gardou             GLint *dst = (GLint *) pixels + start + j * k;
981*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
982*5f2bebf7SJérôme Gardou             {
983*5f2bebf7SJérôme Gardou                 if (is_bgr)
984*5f2bebf7SJérôme Gardou                 {
985*5f2bebf7SJérôme Gardou                     if (b_flag)
986*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_INT(blue[i]);
987*5f2bebf7SJérôme Gardou                     if (g_flag)
988*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_INT(green[i]);
989*5f2bebf7SJérôme Gardou                     if (r_flag)
990*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_INT(red[i]);
991*5f2bebf7SJérôme Gardou                 }
992*5f2bebf7SJérôme Gardou                 else
993*5f2bebf7SJérôme Gardou                 {
994*5f2bebf7SJérôme Gardou                     if (r_flag)
995*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_INT(red[i]);
996*5f2bebf7SJérôme Gardou                     if (g_flag)
997*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_INT(green[i]);
998*5f2bebf7SJérôme Gardou                     if (b_flag)
999*5f2bebf7SJérôme Gardou                         *dst++ = FLOAT_TO_INT(blue[i]);
1000*5f2bebf7SJérôme Gardou                 }
1001*5f2bebf7SJérôme Gardou                 if (l_flag)
1002*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_INT(luminance[i]);
1003*5f2bebf7SJérôme Gardou                 if (a_flag)
1004*5f2bebf7SJérôme Gardou                     *dst++ = FLOAT_TO_INT(alpha[i]);
1005*5f2bebf7SJérôme Gardou             }
1006*5f2bebf7SJérôme Gardou             if (ctx->Pack.SwapBytes)
1007*5f2bebf7SJérôme Gardou             {
1008*5f2bebf7SJérôme Gardou                 gl_swap4((GLuint *) pixels + start + j * k, width * n);
1009*5f2bebf7SJérôme Gardou             }
1010*5f2bebf7SJérôme Gardou             break;
1011*5f2bebf7SJérôme Gardou         }
1012*5f2bebf7SJérôme Gardou         case GL_FLOAT:
1013*5f2bebf7SJérôme Gardou         {
1014*5f2bebf7SJérôme Gardou             GLfloat *dst = (GLfloat *) pixels + start + j * k;
1015*5f2bebf7SJérôme Gardou             for (i = 0; i < width; i++)
1016*5f2bebf7SJérôme Gardou             {
1017*5f2bebf7SJérôme Gardou                 if (is_bgr)
1018*5f2bebf7SJérôme Gardou                 {
1019*5f2bebf7SJérôme Gardou                     if (b_flag)
1020*5f2bebf7SJérôme Gardou                         *dst++ = blue[i];
1021*5f2bebf7SJérôme Gardou                     if (g_flag)
1022*5f2bebf7SJérôme Gardou                         *dst++ = green[i];
1023*5f2bebf7SJérôme Gardou                     if (r_flag)
1024*5f2bebf7SJérôme Gardou                         *dst++ = red[i];
1025*5f2bebf7SJérôme Gardou                 }
1026*5f2bebf7SJérôme Gardou                 else
1027*5f2bebf7SJérôme Gardou                 {
1028*5f2bebf7SJérôme Gardou                     if (r_flag)
1029*5f2bebf7SJérôme Gardou                         *dst++ = red[i];
1030*5f2bebf7SJérôme Gardou                     if (g_flag)
1031*5f2bebf7SJérôme Gardou                         *dst++ = green[i];
1032*5f2bebf7SJérôme Gardou                     if (b_flag)
1033*5f2bebf7SJérôme Gardou                         *dst++ = blue[i];
1034*5f2bebf7SJérôme Gardou                 }
1035*5f2bebf7SJérôme Gardou                 if (l_flag)
1036*5f2bebf7SJérôme Gardou                     *dst++ = luminance[i];
1037*5f2bebf7SJérôme Gardou                 if (a_flag)
1038*5f2bebf7SJérôme Gardou                     *dst++ = alpha[i];
1039*5f2bebf7SJérôme Gardou             }
1040*5f2bebf7SJérôme Gardou             if (ctx->Pack.SwapBytes)
1041*5f2bebf7SJérôme Gardou             {
1042*5f2bebf7SJérôme Gardou                 gl_swap4((GLuint *) pixels + start + j * k, width * n);
1043*5f2bebf7SJérôme Gardou             }
1044*5f2bebf7SJérôme Gardou             break;
1045*5f2bebf7SJérôme Gardou         }
1046*5f2bebf7SJérôme Gardou         default:
1047*5f2bebf7SJérôme Gardou             gl_error(ctx, GL_INVALID_ENUM, "glReadPixels(type)");
1048*5f2bebf7SJérôme Gardou         }
1049*5f2bebf7SJérôme Gardou     }
1050*5f2bebf7SJérôme Gardou     UNDEFARRAY( red );
1051*5f2bebf7SJérôme Gardou     UNDEFARRAY( green );
1052*5f2bebf7SJérôme Gardou     UNDEFARRAY( blue );
1053*5f2bebf7SJérôme Gardou     UNDEFARRAY( alpha );
1054*5f2bebf7SJérôme Gardou     UNDEFARRAY( luminance );
1055*5f2bebf7SJérôme Gardou }
1056*5f2bebf7SJérôme Gardou 
1057*5f2bebf7SJérôme Gardou 
1058*5f2bebf7SJérôme Gardou 
gl_ReadPixels(GLcontext * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)1059*5f2bebf7SJérôme Gardou void gl_ReadPixels( GLcontext *ctx,
1060*5f2bebf7SJérôme Gardou                     GLint x, GLint y, GLsizei width, GLsizei height,
1061*5f2bebf7SJérôme Gardou 		    GLenum format, GLenum type, GLvoid *pixels )
1062*5f2bebf7SJérôme Gardou {
1063*5f2bebf7SJérôme Gardou     if (INSIDE_BEGIN_END(ctx))
1064*5f2bebf7SJérôme Gardou     {
1065*5f2bebf7SJérôme Gardou         gl_error(ctx, GL_INVALID_OPERATION, "glReadPixels");
1066*5f2bebf7SJérôme Gardou         return;
1067*5f2bebf7SJérôme Gardou     }
1068*5f2bebf7SJérôme Gardou 
1069*5f2bebf7SJérôme Gardou     (void) (*ctx->Driver.SetBuffer)(ctx, ctx->Pixel.ReadBuffer);
1070*5f2bebf7SJérôme Gardou 
1071*5f2bebf7SJérôme Gardou     switch (format)
1072*5f2bebf7SJérôme Gardou     {
1073*5f2bebf7SJérôme Gardou     case GL_COLOR_INDEX:
1074*5f2bebf7SJérôme Gardou         read_index_pixels(ctx, x, y, width, height, type, pixels);
1075*5f2bebf7SJérôme Gardou         break;
1076*5f2bebf7SJérôme Gardou     case GL_STENCIL_INDEX:
1077*5f2bebf7SJérôme Gardou         read_stencil_pixels(ctx, x, y, width, height, type, pixels);
1078*5f2bebf7SJérôme Gardou         break;
1079*5f2bebf7SJérôme Gardou     case GL_DEPTH_COMPONENT:
1080*5f2bebf7SJérôme Gardou         read_depth_pixels(ctx, x, y, width, height, type, pixels);
1081*5f2bebf7SJérôme Gardou         break;
1082*5f2bebf7SJérôme Gardou     case GL_RED:
1083*5f2bebf7SJérôme Gardou     case GL_GREEN:
1084*5f2bebf7SJérôme Gardou     case GL_BLUE:
1085*5f2bebf7SJérôme Gardou     case GL_ALPHA:
1086*5f2bebf7SJérôme Gardou     case GL_RGB:
1087*5f2bebf7SJérôme Gardou     case GL_BGR_EXT:
1088*5f2bebf7SJérôme Gardou     case GL_LUMINANCE:
1089*5f2bebf7SJérôme Gardou     case GL_LUMINANCE_ALPHA:
1090*5f2bebf7SJérôme Gardou     case GL_RGBA:
1091*5f2bebf7SJérôme Gardou     case GL_BGRA_EXT:
1092*5f2bebf7SJérôme Gardou         read_color_pixels(ctx, x, y, width, height, format, type, pixels);
1093*5f2bebf7SJérôme Gardou         break;
1094*5f2bebf7SJérôme Gardou     default:
1095*5f2bebf7SJérôme Gardou         gl_error(ctx, GL_INVALID_ENUM, "glReadPixels(format)");
1096*5f2bebf7SJérôme Gardou     }
1097*5f2bebf7SJérôme Gardou 
1098*5f2bebf7SJérôme Gardou     (void) (*ctx->Driver.SetBuffer)(ctx, ctx->Color.DrawBuffer);
1099*5f2bebf7SJérôme Gardou }
1100