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