added dispatch override mechanism, used by trace extension
[mesa.git] / src / mesa / swrast / s_readpix.c
1 /* $Id: s_readpix.c,v 1.5 2000/12/13 00:46:22 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 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 #include "glheader.h"
29 #include "colormac.h"
30 #include "convolve.h"
31 #include "context.h"
32 #include "feedback.h"
33 #include "image.h"
34 #include "macros.h"
35 #include "mem.h"
36 #include "pixel.h"
37
38 #include "s_alphabuf.h"
39 #include "s_context.h"
40 #include "s_depth.h"
41 #include "s_span.h"
42 #include "s_stencil.h"
43
44
45
46 /*
47 * Read a block of color index pixels.
48 */
49 static void read_index_pixels( GLcontext *ctx,
50 GLint x, GLint y,
51 GLsizei width, GLsizei height,
52 GLenum type, GLvoid *pixels,
53 const struct gl_pixelstore_attrib *packing )
54 {
55 GLint i, j, readWidth;
56
57 /* error checking */
58 if (ctx->Visual.RGBAflag) {
59 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
60 return;
61 }
62
63 ASSERT(ctx->Driver.SetReadBuffer);
64 (*ctx->Driver.SetReadBuffer)(ctx, ctx->ReadBuffer, ctx->Pixel.DriverReadBuffer);
65
66 readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
67
68 /* process image row by row */
69 for (j=0;j<height;j++,y++) {
70 GLuint index[MAX_WIDTH];
71 GLvoid *dest;
72
73 (*ctx->Driver.ReadCI32Span)( ctx, readWidth, x, y, index );
74
75 if (ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0) {
76 _mesa_shift_and_offset_ci( ctx, readWidth, index);
77 }
78
79 if (ctx->Pixel.MapColorFlag) {
80 _mesa_map_ci(ctx, readWidth, index);
81 }
82
83 dest = _mesa_image_address(packing, pixels,
84 width, height, GL_COLOR_INDEX, type, 0, j, 0);
85
86 switch (type) {
87 case GL_UNSIGNED_BYTE:
88 {
89 GLubyte *dst = (GLubyte *) dest;
90 for (i=0;i<readWidth;i++) {
91 *dst++ = (GLubyte) index[i];
92 }
93 }
94 break;
95 case GL_BYTE:
96 {
97 GLbyte *dst = (GLbyte *) dest;
98 for (i=0;i<readWidth;i++) {
99 dst[i] = (GLbyte) index[i];
100 }
101 }
102 break;
103 case GL_UNSIGNED_SHORT:
104 {
105 GLushort *dst = (GLushort *) dest;
106 for (i=0;i<readWidth;i++) {
107 dst[i] = (GLushort) index[i];
108 }
109 if (packing->SwapBytes) {
110 _mesa_swap2( (GLushort *) dst, readWidth );
111 }
112 }
113 break;
114 case GL_SHORT:
115 {
116 GLshort *dst = (GLshort *) dest;
117 for (i=0;i<readWidth;i++) {
118 dst[i] = (GLshort) index[i];
119 }
120 if (packing->SwapBytes) {
121 _mesa_swap2( (GLushort *) dst, readWidth );
122 }
123 }
124 break;
125 case GL_UNSIGNED_INT:
126 {
127 GLuint *dst = (GLuint *) dest;
128 for (i=0;i<readWidth;i++) {
129 dst[i] = (GLuint) index[i];
130 }
131 if (packing->SwapBytes) {
132 _mesa_swap4( (GLuint *) dst, readWidth );
133 }
134 }
135 break;
136 case GL_INT:
137 {
138 GLint *dst = (GLint *) dest;
139 for (i=0;i<readWidth;i++) {
140 dst[i] = (GLint) index[i];
141 }
142 if (packing->SwapBytes) {
143 _mesa_swap4( (GLuint *) dst, readWidth );
144 }
145 }
146 break;
147 case GL_FLOAT:
148 {
149 GLfloat *dst = (GLfloat *) dest;
150 for (i=0;i<readWidth;i++) {
151 dst[i] = (GLfloat) index[i];
152 }
153 if (packing->SwapBytes) {
154 _mesa_swap4( (GLuint *) dst, readWidth );
155 }
156 }
157 break;
158 default:
159 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
160 j = height + 1; /* exit loop */
161 }
162 }
163
164 (*ctx->Driver.SetReadBuffer)(ctx, ctx->DrawBuffer, ctx->Color.DriverDrawBuffer);
165 }
166
167
168
169 static void read_depth_pixels( GLcontext *ctx,
170 GLint x, GLint y,
171 GLsizei width, GLsizei height,
172 GLenum type, GLvoid *pixels,
173 const struct gl_pixelstore_attrib *packing )
174 {
175 GLint i, j, readWidth;
176 GLboolean bias_or_scale;
177
178 /* Error checking */
179 if (ctx->Visual.DepthBits <= 0) {
180 /* No depth buffer */
181 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
182 return;
183 }
184
185 readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
186
187 if (type != GL_BYTE &&
188 type != GL_UNSIGNED_BYTE &&
189 type != GL_SHORT &&
190 type != GL_UNSIGNED_SHORT &&
191 type != GL_INT &&
192 type != GL_UNSIGNED_INT &&
193 type != GL_FLOAT) {
194 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels(depth type)");
195 return;
196 }
197
198 bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
199
200 if (type==GL_UNSIGNED_SHORT && ctx->Visual.DepthBits == 16
201 && !bias_or_scale && !packing->SwapBytes) {
202 /* Special case: directly read 16-bit unsigned depth values. */
203 for (j=0;j<height;j++,y++) {
204 GLdepth depth[MAX_WIDTH];
205 GLushort *dst = (GLushort*) _mesa_image_address( packing, pixels,
206 width, height, GL_DEPTH_COMPONENT, type, 0, j, 0 );
207 GLint i;
208 _mesa_read_depth_span(ctx, width, x, y, depth);
209 for (i = 0; i < width; i++)
210 dst[i] = depth[i];
211 }
212 }
213 else if (type==GL_UNSIGNED_INT && ctx->Visual.DepthBits == 32
214 && !bias_or_scale && !packing->SwapBytes) {
215 /* Special case: directly read 32-bit unsigned depth values. */
216 for (j=0;j<height;j++,y++) {
217 GLdepth *dst = (GLdepth *) _mesa_image_address( packing, pixels,
218 width, height, GL_DEPTH_COMPONENT, type, 0, j, 0 );
219 _mesa_read_depth_span(ctx, width, x, y, dst);
220 }
221 }
222 else {
223 /* General case (slower) */
224 for (j=0;j<height;j++,y++) {
225 GLfloat depth[MAX_WIDTH];
226 GLvoid *dest;
227
228 _mesa_read_depth_span_float(ctx, readWidth, x, y, depth);
229
230 if (bias_or_scale) {
231 for (i=0;i<readWidth;i++) {
232 GLfloat d;
233 d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
234 depth[i] = CLAMP( d, 0.0F, 1.0F );
235 }
236 }
237
238 dest = _mesa_image_address(packing, pixels,
239 width, height, GL_DEPTH_COMPONENT, type, 0, j, 0);
240
241 switch (type) {
242 case GL_UNSIGNED_BYTE:
243 {
244 GLubyte *dst = (GLubyte *) dest;
245 for (i=0;i<readWidth;i++) {
246 dst[i] = FLOAT_TO_UBYTE( depth[i] );
247 }
248 }
249 break;
250 case GL_BYTE:
251 {
252 GLbyte *dst = (GLbyte *) dest;
253 for (i=0;i<readWidth;i++) {
254 dst[i] = FLOAT_TO_BYTE( depth[i] );
255 }
256 }
257 break;
258 case GL_UNSIGNED_SHORT:
259 {
260 GLushort *dst = (GLushort *) dest;
261 for (i=0;i<readWidth;i++) {
262 dst[i] = FLOAT_TO_USHORT( depth[i] );
263 }
264 if (packing->SwapBytes) {
265 _mesa_swap2( (GLushort *) dst, readWidth );
266 }
267 }
268 break;
269 case GL_SHORT:
270 {
271 GLshort *dst = (GLshort *) dest;
272 for (i=0;i<readWidth;i++) {
273 dst[i] = FLOAT_TO_SHORT( depth[i] );
274 }
275 if (packing->SwapBytes) {
276 _mesa_swap2( (GLushort *) dst, readWidth );
277 }
278 }
279 break;
280 case GL_UNSIGNED_INT:
281 {
282 GLuint *dst = (GLuint *) dest;
283 for (i=0;i<readWidth;i++) {
284 dst[i] = FLOAT_TO_UINT( depth[i] );
285 }
286 if (packing->SwapBytes) {
287 _mesa_swap4( (GLuint *) dst, readWidth );
288 }
289 }
290 break;
291 case GL_INT:
292 {
293 GLint *dst = (GLint *) dest;
294 for (i=0;i<readWidth;i++) {
295 dst[i] = FLOAT_TO_INT( depth[i] );
296 }
297 if (packing->SwapBytes) {
298 _mesa_swap4( (GLuint *) dst, readWidth );
299 }
300 }
301 break;
302 case GL_FLOAT:
303 {
304 GLfloat *dst = (GLfloat *) dest;
305 for (i=0;i<readWidth;i++) {
306 dst[i] = depth[i];
307 }
308 if (packing->SwapBytes) {
309 _mesa_swap4( (GLuint *) dst, readWidth );
310 }
311 }
312 break;
313 default:
314 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
315 }
316 }
317 }
318 }
319
320
321
322 static void read_stencil_pixels( GLcontext *ctx,
323 GLint x, GLint y,
324 GLsizei width, GLsizei height,
325 GLenum type, GLvoid *pixels,
326 const struct gl_pixelstore_attrib *packing )
327 {
328 GLboolean shift_or_offset;
329 GLint i, j, readWidth;
330
331 if (type != GL_BYTE &&
332 type != GL_UNSIGNED_BYTE &&
333 type != GL_SHORT &&
334 type != GL_UNSIGNED_SHORT &&
335 type != GL_INT &&
336 type != GL_UNSIGNED_INT &&
337 type != GL_FLOAT &&
338 type != GL_BITMAP) {
339 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels(stencil type)");
340 return;
341 }
342
343 readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
344
345 if (ctx->Visual.StencilBits<=0) {
346 /* No stencil buffer */
347 gl_error( ctx, GL_INVALID_OPERATION, "glReadPixels" );
348 return;
349 }
350
351 shift_or_offset = ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0;
352
353 /* process image row by row */
354 for (j=0;j<height;j++,y++) {
355 GLvoid *dest;
356 GLstencil stencil[MAX_WIDTH];
357
358 _mesa_read_stencil_span( ctx, readWidth, x, y, stencil );
359
360 if (shift_or_offset) {
361 _mesa_shift_and_offset_stencil( ctx, readWidth, stencil );
362 }
363
364 if (ctx->Pixel.MapStencilFlag) {
365 _mesa_map_stencil( ctx, readWidth, stencil );
366 }
367
368 dest = _mesa_image_address( packing, pixels,
369 width, height, GL_STENCIL_INDEX, type, 0, j, 0 );
370
371 switch (type) {
372 case GL_UNSIGNED_BYTE:
373 if (sizeof(GLstencil) == 8) {
374 MEMCPY( dest, stencil, readWidth );
375 }
376 else {
377 GLubyte *dst = (GLubyte *) dest;
378 for (i=0;i<readWidth;i++) {
379 dst[i] = (GLubyte) stencil[i];
380 }
381 }
382 break;
383 case GL_BYTE:
384 if (sizeof(GLstencil) == 8) {
385 MEMCPY( dest, stencil, readWidth );
386 }
387 else {
388 GLbyte *dst = (GLbyte *) dest;
389 for (i=0;i<readWidth;i++) {
390 dst[i] = (GLbyte) stencil[i];
391 }
392 }
393 break;
394 case GL_UNSIGNED_SHORT:
395 {
396 GLushort *dst = (GLushort *) dest;
397 for (i=0;i<readWidth;i++) {
398 dst[i] = (GLushort) stencil[i];
399 }
400 if (packing->SwapBytes) {
401 _mesa_swap2( (GLushort *) dst, readWidth );
402 }
403 }
404 break;
405 case GL_SHORT:
406 {
407 GLshort *dst = (GLshort *) dest;
408 for (i=0;i<readWidth;i++) {
409 dst[i] = (GLshort) stencil[i];
410 }
411 if (packing->SwapBytes) {
412 _mesa_swap2( (GLushort *) dst, readWidth );
413 }
414 }
415 break;
416 case GL_UNSIGNED_INT:
417 {
418 GLuint *dst = (GLuint *) dest;
419 for (i=0;i<readWidth;i++) {
420 dst[i] = (GLuint) stencil[i];
421 }
422 if (packing->SwapBytes) {
423 _mesa_swap4( (GLuint *) dst, readWidth );
424 }
425 }
426 break;
427 case GL_INT:
428 {
429 GLint *dst = (GLint *) dest;
430 for (i=0;i<readWidth;i++) {
431 *dst++ = (GLint) stencil[i];
432 }
433 if (packing->SwapBytes) {
434 _mesa_swap4( (GLuint *) dst, readWidth );
435 }
436 }
437 break;
438 case GL_FLOAT:
439 {
440 GLfloat *dst = (GLfloat *) dest;
441 for (i=0;i<readWidth;i++) {
442 dst[i] = (GLfloat) stencil[i];
443 }
444 if (packing->SwapBytes) {
445 _mesa_swap4( (GLuint *) dst, readWidth );
446 }
447 }
448 break;
449 case GL_BITMAP:
450 if (packing->LsbFirst) {
451 GLubyte *dst = (GLubyte*) dest;
452 GLint shift = 0;
453 for (i = 0; i < readWidth; i++) {
454 if (shift == 0)
455 *dst = 0;
456 *dst |= ((stencil != 0) << shift);
457 shift++;
458 if (shift == 8) {
459 shift = 0;
460 dst++;
461 }
462 }
463 }
464 else {
465 GLubyte *dst = (GLubyte*) dest;
466 GLint shift = 7;
467 for (i = 0; i < readWidth; i++) {
468 if (shift == 7)
469 *dst = 0;
470 *dst |= ((stencil != 0) << shift);
471 shift--;
472 if (shift < 0) {
473 shift = 7;
474 dst++;
475 }
476 }
477 }
478 break;
479 default:
480 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
481 }
482 }
483 }
484
485
486
487 /*
488 * Optimized glReadPixels for particular pixel formats:
489 * GL_UNSIGNED_BYTE, GL_RGBA
490 * when pixel scaling, biasing and mapping are disabled.
491 */
492 static GLboolean
493 read_fast_rgba_pixels( GLcontext *ctx,
494 GLint x, GLint y,
495 GLsizei width, GLsizei height,
496 GLenum format, GLenum type,
497 GLvoid *pixels,
498 const struct gl_pixelstore_attrib *packing )
499 {
500 /* can't do scale, bias, mapping, etc */
501 if (ctx->_ImageTransferState)
502 return GL_FALSE;
503
504 /* can't do fancy pixel packing */
505 if (packing->Alignment != 1 || packing->SwapBytes || packing->LsbFirst)
506 return GL_FALSE;
507
508 {
509 GLint srcX = x;
510 GLint srcY = y;
511 GLint readWidth = width; /* actual width read */
512 GLint readHeight = height; /* actual height read */
513 GLint skipPixels = packing->SkipPixels;
514 GLint skipRows = packing->SkipRows;
515 GLint rowLength;
516
517 if (packing->RowLength > 0)
518 rowLength = packing->RowLength;
519 else
520 rowLength = width;
521
522 /* horizontal clipping */
523 if (srcX < ctx->ReadBuffer->_Xmin) {
524 skipPixels += (ctx->ReadBuffer->_Xmin - srcX);
525 readWidth -= (ctx->ReadBuffer->_Xmin - srcX);
526 srcX = ctx->ReadBuffer->_Xmin;
527 }
528 if (srcX + readWidth > ctx->ReadBuffer->_Xmax)
529 readWidth -= (srcX + readWidth - ctx->ReadBuffer->_Xmax);
530 if (readWidth <= 0)
531 return GL_TRUE;
532
533 /* vertical clipping */
534 if (srcY < ctx->ReadBuffer->_Ymin) {
535 skipRows += (ctx->ReadBuffer->_Ymin - srcY);
536 readHeight -= (ctx->ReadBuffer->_Ymin - srcY);
537 srcY = ctx->ReadBuffer->_Ymin;
538 }
539 if (srcY + readHeight > ctx->ReadBuffer->_Ymax)
540 readHeight -= (srcY + readHeight - ctx->ReadBuffer->_Ymax);
541 if (readHeight <= 0)
542 return GL_TRUE;
543
544 /*
545 * Ready to read!
546 * The window region at (destX, destY) of size (readWidth, readHeight)
547 * will be read back.
548 * We'll write pixel data to buffer pointed to by "pixels" but we'll
549 * skip "skipRows" rows and skip "skipPixels" pixels/row.
550 */
551 #if CHAN_BITS == 8
552 if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
553 #elif CHAN_BITS == 16
554 if (format == GL_RGBA && type == GL_UNSIGNED_SHORT) {
555 #else
556 if (0) {
557 #endif
558 GLchan *dest = (GLchan *) pixels
559 + (skipRows * rowLength + skipPixels) * 4;
560 GLint row;
561 for (row=0; row<readHeight; row++) {
562 (*ctx->Driver.ReadRGBASpan)(ctx, readWidth, srcX, srcY,
563 (GLchan (*)[4]) dest);
564 if (ctx->DrawBuffer->UseSoftwareAlphaBuffers) {
565 _mesa_read_alpha_span(ctx, readWidth, srcX, srcY,
566 (GLchan (*)[4]) dest);
567 }
568 dest += rowLength * 4;
569 srcY++;
570 }
571 return GL_TRUE;
572 }
573 else {
574 /* can't do this format/type combination */
575 return GL_FALSE;
576 }
577 }
578 }
579
580
581
582 /*
583 * Read R, G, B, A, RGB, L, or LA pixels.
584 */
585 static void read_rgba_pixels( GLcontext *ctx,
586 GLint x, GLint y,
587 GLsizei width, GLsizei height,
588 GLenum format, GLenum type, GLvoid *pixels,
589 const struct gl_pixelstore_attrib *packing )
590 {
591 GLint readWidth;
592
593 (*ctx->Driver.SetReadBuffer)(ctx, ctx->ReadBuffer, ctx->Pixel.DriverReadBuffer);
594
595 /* Try optimized path first */
596 if (read_fast_rgba_pixels( ctx, x, y, width, height,
597 format, type, pixels, packing )) {
598
599 (*ctx->Driver.SetReadBuffer)(ctx, ctx->DrawBuffer, ctx->Color.DriverDrawBuffer);
600 return; /* done! */
601 }
602
603 readWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
604
605 /* do error checking on pixel type, format was already checked by caller */
606 switch (type) {
607 case GL_UNSIGNED_BYTE:
608 case GL_BYTE:
609 case GL_UNSIGNED_SHORT:
610 case GL_SHORT:
611 case GL_UNSIGNED_INT:
612 case GL_INT:
613 case GL_FLOAT:
614 case GL_UNSIGNED_BYTE_3_3_2:
615 case GL_UNSIGNED_BYTE_2_3_3_REV:
616 case GL_UNSIGNED_SHORT_5_6_5:
617 case GL_UNSIGNED_SHORT_5_6_5_REV:
618 case GL_UNSIGNED_SHORT_4_4_4_4:
619 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
620 case GL_UNSIGNED_SHORT_5_5_5_1:
621 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
622 case GL_UNSIGNED_INT_8_8_8_8:
623 case GL_UNSIGNED_INT_8_8_8_8_REV:
624 case GL_UNSIGNED_INT_10_10_10_2:
625 case GL_UNSIGNED_INT_2_10_10_10_REV:
626 /* valid pixel type */
627 break;
628 default:
629 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(type)" );
630 return;
631 }
632
633 if (!_mesa_is_legal_format_and_type(format, type) ||
634 format == GL_INTENSITY) {
635 gl_error(ctx, GL_INVALID_OPERATION, "glReadPixels(format or type)");
636 return;
637 }
638
639 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
640 const GLuint transferOps = ctx->_ImageTransferState;
641 GLfloat *dest, *src, *tmpImage, *convImage;
642 GLint row;
643
644 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
645 if (!tmpImage) {
646 gl_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
647 return;
648 }
649 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
650 if (!convImage) {
651 FREE(tmpImage);
652 gl_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
653 return;
654 }
655
656 /* read full RGBA, FLOAT image */
657 dest = tmpImage;
658 for (row = 0; row < height; row++, y++) {
659 GLchan rgba[MAX_WIDTH][4];
660 if (ctx->Visual.RGBAflag) {
661 gl_read_rgba_span(ctx, ctx->ReadBuffer, readWidth, x, y, rgba);
662 }
663 else {
664 GLuint index[MAX_WIDTH];
665 (*ctx->Driver.ReadCI32Span)(ctx, readWidth, x, y, index);
666 if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset !=0 ) {
667 _mesa_map_ci(ctx, readWidth, index);
668 }
669 _mesa_map_ci_to_rgba_chan(ctx, readWidth, index, rgba);
670 }
671 _mesa_pack_rgba_span(ctx, readWidth, (const GLchan (*)[4]) rgba,
672 GL_RGBA, GL_FLOAT, dest, &_mesa_native_packing,
673 transferOps & IMAGE_PRE_CONVOLUTION_BITS);
674 dest += width * 4;
675 }
676
677 /* do convolution */
678 if (ctx->Pixel.Convolution2DEnabled) {
679 _mesa_convolve_2d_image(ctx, &readWidth, &height, tmpImage, convImage);
680 }
681 else {
682 ASSERT(ctx->Pixel.Separable2DEnabled);
683 _mesa_convolve_sep_image(ctx, &readWidth, &height, tmpImage, convImage);
684 }
685 FREE(tmpImage);
686
687 /* finish transfer ops and pack the resulting image */
688 src = convImage;
689 for (row = 0; row < height; row++) {
690 GLvoid *dest;
691 dest = _mesa_image_address(packing, pixels, readWidth, height,
692 format, type, 0, row, 0);
693 _mesa_pack_float_rgba_span(ctx, readWidth,
694 (const GLfloat (*)[4]) src,
695 format, type, dest, packing,
696 transferOps & IMAGE_POST_CONVOLUTION_BITS);
697 src += readWidth * 4;
698 }
699 }
700 else {
701 /* no convolution */
702 GLint row;
703 for (row = 0; row < height; row++, y++) {
704 GLchan rgba[MAX_WIDTH][4];
705 GLvoid *dst;
706 if (ctx->Visual.RGBAflag) {
707 gl_read_rgba_span(ctx, ctx->ReadBuffer, readWidth, x, y, rgba);
708 }
709 else {
710 GLuint index[MAX_WIDTH];
711 (*ctx->Driver.ReadCI32Span)(ctx, readWidth, x, y, index);
712 if (ctx->Pixel.IndexShift != 0 || ctx->Pixel.IndexOffset != 0) {
713 _mesa_map_ci(ctx, readWidth, index);
714 }
715 _mesa_map_ci_to_rgba_chan(ctx, readWidth, index, rgba);
716 }
717 dst = _mesa_image_address(packing, pixels, width, height,
718 format, type, 0, row, 0);
719 if (ctx->Visual.RedBits < CHAN_BITS ||
720 ctx->Visual.GreenBits < CHAN_BITS ||
721 ctx->Visual.BlueBits < CHAN_BITS) {
722 /* Requantize the color values into floating point and go from
723 * there. This fixes conformance failures with 16-bit color
724 * buffers, for example.
725 */
726 GLfloat rgbaf[MAX_WIDTH][4];
727 _mesa_chan_to_float_span(ctx, readWidth,
728 (CONST GLchan (*)[4]) rgba, rgbaf);
729 _mesa_pack_float_rgba_span(ctx, readWidth,
730 (CONST GLfloat (*)[4]) rgbaf,
731 format, type, dst, packing,
732 ctx->_ImageTransferState);
733 }
734 else {
735 /* GLubytes are fine */
736 _mesa_pack_rgba_span(ctx, readWidth, (CONST GLchan (*)[4]) rgba,
737 format, type, dst, packing,
738 ctx->_ImageTransferState);
739 }
740 }
741 }
742
743 (*ctx->Driver.SetReadBuffer)(ctx, ctx->DrawBuffer, ctx->Color.DriverDrawBuffer);
744 }
745
746
747
748 void
749 _swrast_ReadPixels( GLcontext *ctx,
750 GLint x, GLint y, GLsizei width, GLsizei height,
751 GLenum format, GLenum type,
752 const struct gl_pixelstore_attrib *pack,
753 GLvoid *pixels )
754 {
755 (void) pack;
756
757 if (SWRAST_CONTEXT(ctx)->NewState)
758 _swrast_validate_derived( ctx );
759
760 switch (format) {
761 case GL_COLOR_INDEX:
762 read_index_pixels(ctx, x, y, width, height, type, pixels, &ctx->Pack);
763 break;
764 case GL_STENCIL_INDEX:
765 read_stencil_pixels(ctx, x,y, width,height, type, pixels, &ctx->Pack);
766 break;
767 case GL_DEPTH_COMPONENT:
768 read_depth_pixels(ctx, x, y, width, height, type, pixels, &ctx->Pack);
769 break;
770 case GL_RED:
771 case GL_GREEN:
772 case GL_BLUE:
773 case GL_ALPHA:
774 case GL_RGB:
775 case GL_LUMINANCE:
776 case GL_LUMINANCE_ALPHA:
777 case GL_RGBA:
778 case GL_BGR:
779 case GL_BGRA:
780 case GL_ABGR_EXT:
781 read_rgba_pixels(ctx, x, y, width, height,
782 format, type, pixels, &ctx->Pack);
783 break;
784 default:
785 gl_error( ctx, GL_INVALID_ENUM, "glReadPixels(format)" );
786 }
787 }