source: trunk/src/opengl/mesa/readpix.c@ 2938

Last change on this file since 2938 was 2938, checked in by sandervl, 25 years ago

created

File size: 21.0 KB
Line 
1/* $Id: readpix.c,v 1.1 2000-02-29 00:50:09 sandervl Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28
29
30
31#ifdef PC_HEADER
32#include "all.h"
33#else
34#ifndef XFree86Server
35#include <math.h>
36#include <stdlib.h>
37#include <string.h>
38#else
39#include "GL/xf86glx.h"
40#endif
41#include "alphabuf.h"
42#include "context.h"
43#include "depth.h"
44#include "feedback.h"
45#include "image.h"
46#include "macros.h"
47#include "pixel.h"
48#include "readpix.h"
49#include "span.h"
50#include "stencil.h"
51#include "types.h"
52#endif
53
54
55
56
57/*
58 * Read a block of color index pixels.
59 */
60static void read_index_pixels( GLcontext *ctx,
61 GLint x, GLint y,
62 GLsizei width, GLsizei height,
63 GLenum type, GLvoid *pixels,
64 const struct gl_pixelstore_attrib *packing )
65{
66 GLint i, j, readWidth;
67
68 /* error checking */
69 if (ctx->Visual->RGBAflag) {
70 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
71 return;
72 }
73
74 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
75
76 readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
77
78 /* process image row by row */
79 for (j=0;j<height;j++,y++) {
80 GLuint index[MAX_WIDTH];
81 GLvoid *dest;
82
83 (*ctx->Driver.ReadCI32Span)( ctx, readWidth, x, y, index );
84
85 if (ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0) {
86 gl_shift_and_offset_ci( ctx, readWidth, index);
87 }
88
89 if (ctx->Pixel.MapColorFlag) {
90 gl_map_ci(ctx, readWidth, index);
91 }
92
93 dest = gl_pixel_addr_in_image(packing, pixels,
94 width, height, GL_COLOR_INDEX, type, 0, j, 0);
95
96 switch (type) {
97 case GL_UNSIGNED_BYTE:
98 {
99 GLubyte *dst = (GLubyte *) dest;
100 for (i=0;i<readWidth;i++) {
101 *dst++ = (GLubyte) index[i];
102 }
103 }
104 break;
105 case GL_BYTE:
106 {
107 GLbyte *dst = (GLbyte *) dest;
108 for (i=0;i<readWidth;i++) {
109 dst[i] = (GLbyte) index[i];
110 }
111 }
112 break;
113 case GL_UNSIGNED_SHORT:
114 {
115 GLushort *dst = (GLushort *) dest;
116 for (i=0;i<readWidth;i++) {
117 dst[i] = (GLushort) index[i];
118 }
119 if (packing->SwapBytes) {
120 gl_swap2( (GLushort *) dst, readWidth );
121 }
122 }
123 break;
124 case GL_SHORT:
125 {
126 GLshort *dst = (GLshort *) dest;
127 for (i=0;i<readWidth;i++) {
128 dst[i] = (GLshort) index[i];
129 }
130 if (packing->SwapBytes) {
131 gl_swap2( (GLushort *) dst, readWidth );
132 }
133 }
134 break;
135 case GL_UNSIGNED_INT:
136 {
137 GLuint *dst = (GLuint *) dest;
138 for (i=0;i<readWidth;i++) {
139 dst[i] = (GLuint) index[i];
140 }
141 if (packing->SwapBytes) {
142 gl_swap4( (GLuint *) dst, readWidth );
143 }
144 }
145 break;
146 case GL_INT:
147 {
148 GLint *dst = (GLint *) dest;
149 for (i=0;i<readWidth;i++) {
150 dst[i] = (GLint) index[i];
151 }
152 if (packing->SwapBytes) {
153 gl_swap4( (GLuint *) dst, readWidth );
154 }
155 }
156 break;
157 case GL_FLOAT:
158 {
159 GLfloat *dst = (GLfloat *) dest;
160 for (i=0;i<readWidth;i++) {
161 dst[i] = (GLfloat) index[i];
162 }
163 if (packing->SwapBytes) {
164 gl_swap4( (GLuint *) dst, readWidth );
165 }
166 }
167 break;
168 default:
169 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
170 j = height + 1; /* exit loop */
171 }
172 }
173
174 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
175}
176
177
178
179static void read_depth_pixels( GLcontext *ctx,
180 GLint x, GLint y,
181 GLsizei width, GLsizei height,
182 GLenum type, GLvoid *pixels,
183 const struct gl_pixelstore_attrib *packing )
184{
185 GLint i, j, readWidth;
186 GLboolean bias_or_scale;
187
188 /* Error checking */
189 if (ctx->Visual->DepthBits <= 0) {
190 /* No depth buffer */
191 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
192 return;
193 }
194
195 readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
196
197 if (type != GL_BYTE &&
198 type != GL_UNSIGNED_BYTE &&
199 type != GL_SHORT &&
200 type != GL_UNSIGNED_SHORT &&
201 type != GL_INT &&
202 type != GL_UNSIGNED_INT &&
203 type != GL_FLOAT) {
204 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels(depth type)");
205 return;
206 }
207
208 bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
209
210 if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
211 && !bias_or_scale && !packing->SwapBytes) {
212 /* Special case: directly read 16-bit unsigned depth values. */
213 for (j=0;j<height;j++,y++) {
214 GLushort *dst = (GLushort*) gl_pixel_addr_in_image( packing, pixels,
215 width, height, GL_DEPTH_COMPONENT, type, 0, j, 0 );
216 (*ctx->Driver.ReadDepthSpanInt)( ctx, width, x, y, (GLdepth*) dst);
217 }
218 }
219 else if (type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
220 && !bias_or_scale && !packing->SwapBytes) {
221 /* Special case: directly read 32-bit unsigned depth values. */
222 /* Compute shift value to scale depth values up to 32-bit uints. */
223 GLuint shift = 0;
224 GLuint max = MAX_DEPTH;
225 while ((max&0x80000000)==0) {
226 max = max << 1;
227 shift++;
228 }
229 for (j=0;j<height;j++,y++) {
230 GLuint *dst = (GLuint *) gl_pixel_addr_in_image( packing, pixels,
231 width, height, GL_DEPTH_COMPONENT, type, 0, j, 0 );
232 (*ctx->Driver.ReadDepthSpanInt)( ctx, width, x, y, (GLdepth*) dst);
233 for (i=0;i<width;i++) {
234 dst[i] = dst[i] << shift;
235 }
236 }
237 }
238 else {
239 /* General case (slow) */
240 for (j=0;j<height;j++,y++) {
241 GLfloat depth[MAX_WIDTH];
242 GLvoid *dest;
243
244 (*ctx->Driver.ReadDepthSpanFloat)( ctx, readWidth, x, y, depth );
245
246 if (bias_or_scale) {
247 for (i=0;i<readWidth;i++) {
248 GLfloat d;
249 d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
250 depth[i] = CLAMP( d, 0.0F, 1.0F );
251 }
252 }
253
254 dest = gl_pixel_addr_in_image(packing, pixels,
255 width, height, GL_DEPTH_COMPONENT, type, 0, j, 0);
256
257 switch (type) {
258 case GL_UNSIGNED_BYTE:
259 {
260 GLubyte *dst = (GLubyte *) dest;
261 for (i=0;i<readWidth;i++) {
262 dst[i] = FLOAT_TO_UBYTE( depth[i] );
263 }
264 }
265 break;
266 case GL_BYTE:
267 {
268 GLbyte *dst = (GLbyte *) dest;
269 for (i=0;i<readWidth;i++) {
270 dst[i] = FLOAT_TO_BYTE( depth[i] );
271 }
272 }
273 break;
274 case GL_UNSIGNED_SHORT:
275 {
276 GLushort *dst = (GLushort *) dest;
277 for (i=0;i<readWidth;i++) {
278 dst[i] = FLOAT_TO_USHORT( depth[i] );
279 }
280 if (packing->SwapBytes) {
281 gl_swap2( (GLushort *) dst, readWidth );
282 }
283 }
284 break;
285 case GL_SHORT:
286 {
287 GLshort *dst = (GLshort *) dest;
288 for (i=0;i<readWidth;i++) {
289 dst[i] = FLOAT_TO_SHORT( depth[i] );
290 }
291 if (packing->SwapBytes) {
292 gl_swap2( (GLushort *) dst, readWidth );
293 }
294 }
295 break;
296 case GL_UNSIGNED_INT:
297 {
298 GLuint *dst = (GLuint *) dest;
299 for (i=0;i<readWidth;i++) {
300 dst[i] = FLOAT_TO_UINT( depth[i] );
301 }
302 if (packing->SwapBytes) {
303 gl_swap4( (GLuint *) dst, readWidth );
304 }
305 }
306 break;
307 case GL_INT:
308 {
309 GLint *dst = (GLint *) dest;
310 for (i=0;i<readWidth;i++) {
311 dst[i] = FLOAT_TO_INT( depth[i] );
312 }
313 if (packing->SwapBytes) {
314 gl_swap4( (GLuint *) dst, readWidth );
315 }
316 }
317 break;
318 case GL_FLOAT:
319 {
320 GLfloat *dst = (GLfloat *) dest;
321 for (i=0;i<readWidth;i++) {
322 dst[i] = depth[i];
323 }
324 if (packing->SwapBytes) {
325 gl_swap4( (GLuint *) dst, readWidth );
326 }
327 }
328 break;
329 default:
330 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
331 }
332 }
333 }
334}
335
336
337
338
339static void read_stencil_pixels( GLcontext *ctx,
340 GLint x, GLint y,
341 GLsizei width, GLsizei height,
342 GLenum type, GLvoid *pixels,
343 const struct gl_pixelstore_attrib *packing )
344{
345 GLboolean shift_or_offset;
346 GLint i, j, readWidth;
347
348 if (type != GL_BYTE &&
349 type != GL_UNSIGNED_BYTE &&
350 type != GL_SHORT &&
351 type != GL_UNSIGNED_SHORT &&
352 type != GL_INT &&
353 type != GL_UNSIGNED_INT &&
354 type != GL_FLOAT &&
355 type != GL_BITMAP) {
356 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels(stencil type)");
357 return;
358 }
359
360 readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
361
362 if (ctx->Visual->StencilBits<=0) {
363 /* No stencil buffer */
364 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
365 return;
366 }
367
368 shift_or_offset = ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0;
369
370 /* process image row by row */
371 for (j=0;j<height;j++,y++) {
372 GLvoid *dest;
373 GLstencil stencil[MAX_WIDTH];
374
375 gl_read_stencil_span( ctx, readWidth, x, y, stencil );
376
377 if (shift_or_offset) {
378 gl_shift_and_offset_stencil( ctx, readWidth, stencil );
379 }
380
381 if (ctx->Pixel.MapStencilFlag) {
382 gl_map_stencil( ctx, readWidth, stencil );
383 }
384
385 dest = gl_pixel_addr_in_image( packing, pixels,
386 width, height, GL_STENCIL_INDEX, type, 0, j, 0 );
387
388 switch (type) {
389 case GL_UNSIGNED_BYTE:
390 if (sizeof(GLstencil) == 8) {
391 MEMCPY( dest, stencil, readWidth );
392 }
393 else {
394 GLubyte *dst = (GLubyte *) dest;
395 for (i=0;i<readWidth;i++) {
396 dst[i] = (GLubyte) stencil[i];
397 }
398 }
399 break;
400 case GL_BYTE:
401 if (sizeof(GLstencil) == 8) {
402 MEMCPY( dest, stencil, readWidth );
403 }
404 else {
405 GLbyte *dst = (GLbyte *) dest;
406 for (i=0;i<readWidth;i++) {
407 dst[i] = (GLbyte) stencil[i];
408 }
409 }
410 break;
411 case GL_UNSIGNED_SHORT:
412 {
413 GLushort *dst = (GLushort *) dest;
414 for (i=0;i<readWidth;i++) {
415 dst[i] = (GLushort) stencil[i];
416 }
417 if (packing->SwapBytes) {
418 gl_swap2( (GLushort *) dst, readWidth );
419 }
420 }
421 break;
422 case GL_SHORT:
423 {
424 GLshort *dst = (GLshort *) dest;
425 for (i=0;i<readWidth;i++) {
426 dst[i] = (GLshort) stencil[i];
427 }
428 if (packing->SwapBytes) {
429 gl_swap2( (GLushort *) dst, readWidth );
430 }
431 }
432 break;
433 case GL_UNSIGNED_INT:
434 {
435 GLuint *dst = (GLuint *) dest;
436 for (i=0;i<readWidth;i++) {
437 dst[i] = (GLuint) stencil[i];
438 }
439 if (packing->SwapBytes) {
440 gl_swap4( (GLuint *) dst, readWidth );
441 }
442 }
443 break;
444 case GL_INT:
445 {
446 GLint *dst = (GLint *) dest;
447 for (i=0;i<readWidth;i++) {
448 *dst++ = (GLint) stencil[i];
449 }
450 if (packing->SwapBytes) {
451 gl_swap4( (GLuint *) dst, readWidth );
452 }
453 }
454 break;
455 case GL_FLOAT:
456 {
457 GLfloat *dst = (GLfloat *) dest;
458 for (i=0;i<readWidth;i++) {
459 dst[i] = (GLfloat) stencil[i];
460 }
461 if (packing->SwapBytes) {
462 gl_swap4( (GLuint *) dst, readWidth );
463 }
464 }
465 break;
466 case GL_BITMAP:
467 if (packing->LsbFirst) {
468 GLubyte *dst = (GLubyte*) dest;
469 GLint shift = 0;
470 for (i = 0; i < readWidth; i++) {
471 if (shift == 0)
472 *dst = 0;
473 *dst |= ((stencil != 0) << shift);
474 shift++;
475 if (shift == 8) {
476 shift = 0;
477 dst++;
478 }
479 }
480 }
481 else {
482 GLubyte *dst = (GLubyte*) dest;
483 GLint shift = 7;
484 for (i = 0; i < readWidth; i++) {
485 if (shift == 7)
486 *dst = 0;
487 *dst |= ((stencil != 0) << shift);
488 shift--;
489 if (shift < 0) {
490 shift = 7;
491 dst++;
492 }
493 }
494 }
495 break;
496 default:
497 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
498 }
499 }
500}
501
502
503
504/*
505 * Optimized glReadPixels for particular pixel formats:
506 * GL_UNSIGNED_BYTE, GL_RGBA
507 * when pixel scaling, biasing and mapping are disabled.
508 */
509static GLboolean
510read_fast_rgba_pixels( GLcontext *ctx,
511 GLint x, GLint y,
512 GLsizei width, GLsizei height,
513 GLenum format, GLenum type,
514 GLvoid *pixels,
515 const struct gl_pixelstore_attrib *packing )
516{
517 /* can't do scale, bias or mapping */
518 if (ctx->Pixel.ScaleOrBiasRGBA || ctx->Pixel.MapColorFlag)
519 return GL_FALSE;
520
521 /* can't do fancy pixel packing */
522 if (packing->Alignment != 1 || packing->SwapBytes || packing->LsbFirst)
523 return GL_FALSE;
524
525 {
526 GLint srcX = x;
527 GLint srcY = y;
528 GLint readWidth = width; /* actual width read */
529 GLint readHeight = height; /* actual height read */
530 GLint skipPixels = packing->SkipPixels;
531 GLint skipRows = packing->SkipRows;
532 GLint rowLength;
533
534 if (packing->RowLength > 0)
535 rowLength = packing->RowLength;
536 else
537 rowLength = width;
538
539 /* horizontal clipping */
540 if (srcX < ctx->Buffer->Xmin) {
541 skipPixels += (ctx->Buffer->Xmin - srcX);
542 readWidth -= (ctx->Buffer->Xmin - srcX);
543 srcX = ctx->Buffer->Xmin;
544 }
545 if (srcX + readWidth > ctx->Buffer->Xmax)
546 readWidth -= (srcX + readWidth - ctx->Buffer->Xmax - 1);
547 if (readWidth <= 0)
548 return GL_TRUE;
549
550 /* vertical clipping */
551 if (srcY < ctx->Buffer->Ymin) {
552 skipRows += (ctx->Buffer->Ymin - srcY);
553 readHeight -= (ctx->Buffer->Ymin - srcY);
554 srcY = ctx->Buffer->Ymin;
555 }
556 if (srcY + readHeight > ctx->Buffer->Ymax)
557 readHeight -= (srcY + readHeight - ctx->Buffer->Ymax - 1);
558 if (readHeight <= 0)
559 return GL_TRUE;
560
561 /*
562 * Ready to read!
563 * The window region at (destX, destY) of size (readWidth, readHeight)
564 * will be read back.
565 * We'll write pixel data to buffer pointed to by "pixels" but we'll
566 * skip "skipRows" rows and skip "skipPixels" pixels/row.
567 */
568 if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
569 GLubyte *dest = (GLubyte *) pixels
570 + (skipRows * rowLength + skipPixels) * 4;
571 GLint row;
572 for (row=0; row<readHeight; row++) {
573 (*ctx->Driver.ReadRGBASpan)(ctx, readWidth, srcX, srcY,
574 (GLubyte (*)[4]) dest);
575 if (ctx->Visual->SoftwareAlpha) {
576 gl_read_alpha_span(ctx, readWidth, srcX, srcY,
577 (GLubyte (*)[4]) dest);
578 }
579 dest += rowLength * 4;
580 srcY++;
581 }
582 return GL_TRUE;
583 }
584 else {
585 /* can't do this format/type combination */
586 return GL_FALSE;
587 }
588 }
589}
590
591
592
593/*
594 * Read R, G, B, A, RGB, L, or LA pixels.
595 */
596static void read_rgba_pixels( GLcontext *ctx,
597 GLint x, GLint y,
598 GLsizei width, GLsizei height,
599 GLenum format, GLenum type, GLvoid *pixels,
600 const struct gl_pixelstore_attrib *packing )
601{
602 GLint readWidth;
603
604 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
605
606 /* Try optimized path first */
607 if (read_fast_rgba_pixels( ctx, x, y, width, height,
608 format, type, pixels, packing )) {
609
610 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
611 return; /* done! */
612 }
613
614 readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
615
616 /* do error checking on pixel type, format was already checked by caller */
617 switch (type) {
618 case GL_UNSIGNED_BYTE:
619 case GL_BYTE:
620 case GL_UNSIGNED_SHORT:
621 case GL_SHORT:
622 case GL_UNSIGNED_INT:
623 case GL_INT:
624 case GL_FLOAT:
625 case GL_UNSIGNED_BYTE_3_3_2:
626 case GL_UNSIGNED_BYTE_2_3_3_REV:
627 case GL_UNSIGNED_SHORT_5_6_5:
628 case GL_UNSIGNED_SHORT_5_6_5_REV:
629 case GL_UNSIGNED_SHORT_4_4_4_4:
630 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
631 case GL_UNSIGNED_SHORT_5_5_5_1:
632 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
633 case GL_UNSIGNED_INT_8_8_8_8:
634 case GL_UNSIGNED_INT_8_8_8_8_REV:
635 case GL_UNSIGNED_INT_10_10_10_2:
636 case GL_UNSIGNED_INT_2_10_10_10_REV:
637 /* valid pixel type */
638 break;
639 default:
640 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
641 return;
642 }
643
644 if (!gl_is_legal_format_and_type(format, type)) {
645 gl_error(ctx, GL_INVALID_OPERATION, "glReadPixels(format or type)");
646 return;
647 }
648
649 if (ctx->Visual->RGBAflag) {
650 GLint j;
651 for (j=0;j<height;j++,y++) {
652 GLubyte rgba[MAX_WIDTH][4];
653 GLvoid *dest;
654
655 gl_read_rgba_span( ctx, readWidth, x, y, rgba );
656
657 dest = gl_pixel_addr_in_image( packing, pixels, width, height,
658 format, type, 0, j, 0);
659
660 gl_pack_rgba_span( ctx, readWidth, (const GLubyte (*)[4]) rgba,
661 format, type, dest, packing, GL_TRUE );
662 }
663 }
664 else {
665 GLint j;
666 for (j=0;j<height;j++,y++) {
667 GLubyte rgba[MAX_WIDTH][4];
668 GLuint index[MAX_WIDTH];
669 GLvoid *dest;
670
671 (*ctx->Driver.ReadCI32Span)( ctx, readWidth, x, y, index );
672
673 if (ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0) {
674 gl_map_ci( ctx, readWidth, index );
675 }
676
677 gl_map_ci_to_rgba(ctx, readWidth, index, rgba );
678
679 dest = gl_pixel_addr_in_image( packing, pixels, width, height,
680 format, type, 0, j, 0);
681
682 gl_pack_rgba_span( ctx, readWidth, (const GLubyte (*)[4]) rgba,
683 format, type, dest, packing, GL_TRUE );
684 }
685 }
686
687 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
688}
689
690
691
692void gl_ReadPixels( GLcontext *ctx,
693 GLint x, GLint y, GLsizei width, GLsizei height,
694 GLenum format, GLenum type, GLvoid *pixels )
695{
696 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glReadPixels");
697
698 if (!pixels) {
699 gl_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" );
700 return;
701 }
702
703 switch (format) {
704 case GL_COLOR_INDEX:
705 read_index_pixels( ctx, x, y, width, height, type, pixels, &ctx->Pack );
706 break;
707 case GL_STENCIL_INDEX:
708 read_stencil_pixels( ctx, x, y, width, height, type, pixels, &ctx->Pack );
709 break;
710 case GL_DEPTH_COMPONENT:
711 read_depth_pixels( ctx, x, y, width, height, type, pixels, &ctx->Pack );
712 break;
713 case GL_RED:
714 case GL_GREEN:
715 case GL_BLUE:
716 case GL_ALPHA:
717 case GL_RGB:
718 case GL_LUMINANCE:
719 case GL_LUMINANCE_ALPHA:
720 case GL_RGBA:
721 case GL_BGR:
722 case GL_BGRA:
723 case GL_ABGR_EXT:
724 read_rgba_pixels( ctx, x, y, width, height, format, type, pixels, &ctx->Pack );
725 break;
726 default:
727 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(format)" );
728 }
729}
Note: See TracBrowser for help on using the repository browser.