1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "glheader.h"
26
27 #include "blend.h"
28 #include "bufferobj.h"
29 #include "context.h"
30 #include "enums.h"
31 #include "readpix.h"
32 #include "framebuffer.h"
33 #include "formats.h"
34 #include "format_unpack.h"
35 #include "image.h"
36 #include "mtypes.h"
37 #include "pack.h"
38 #include "pbo.h"
39 #include "pixel.h"
40 #include "state.h"
41 #include "glformats.h"
42 #include "fbobject.h"
43 #include "format_utils.h"
44 #include "pixeltransfer.h"
45
46
47 /**
48 * Return true if the conversion L=R+G+B is needed.
49 */
50 GLboolean
_mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat,GLenum dstBaseFormat)51 _mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat,
52 GLenum dstBaseFormat)
53 {
54 return (srcBaseFormat == GL_RG ||
55 srcBaseFormat == GL_RGB ||
56 srcBaseFormat == GL_RGBA) &&
57 (dstBaseFormat == GL_LUMINANCE ||
58 dstBaseFormat == GL_LUMINANCE_ALPHA);
59 }
60
61 /**
62 * Return true if the conversion L,I to RGB conversion is needed.
63 */
64 GLboolean
_mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat,GLenum dstBaseFormat)65 _mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat,
66 GLenum dstBaseFormat)
67 {
68 return (srcBaseFormat == GL_LUMINANCE ||
69 srcBaseFormat == GL_LUMINANCE_ALPHA ||
70 srcBaseFormat == GL_INTENSITY) &&
71 (dstBaseFormat == GL_GREEN ||
72 dstBaseFormat == GL_BLUE ||
73 dstBaseFormat == GL_RG ||
74 dstBaseFormat == GL_RGB ||
75 dstBaseFormat == GL_BGR ||
76 dstBaseFormat == GL_RGBA ||
77 dstBaseFormat == GL_BGRA);
78 }
79
80 /**
81 * Return transfer op flags for this ReadPixels operation.
82 */
83 GLbitfield
_mesa_get_readpixels_transfer_ops(const struct gl_context * ctx,mesa_format texFormat,GLenum format,GLenum type,GLboolean uses_blit)84 _mesa_get_readpixels_transfer_ops(const struct gl_context *ctx,
85 mesa_format texFormat,
86 GLenum format, GLenum type,
87 GLboolean uses_blit)
88 {
89 GLbitfield transferOps = ctx->_ImageTransferState;
90 GLenum srcBaseFormat = _mesa_get_format_base_format(texFormat);
91 GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
92
93 if (format == GL_DEPTH_COMPONENT ||
94 format == GL_DEPTH_STENCIL ||
95 format == GL_STENCIL_INDEX) {
96 return 0;
97 }
98
99 /* Pixel transfer ops (scale, bias, table lookup) do not apply
100 * to integer formats.
101 */
102 if (_mesa_is_enum_format_integer(format)) {
103 return 0;
104 }
105
106 if (uses_blit) {
107 /* For blit-based ReadPixels packing, the clamping is done automatically
108 * unless the type is float. */
109 if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
110 (type == GL_FLOAT || type == GL_HALF_FLOAT ||
111 type == GL_UNSIGNED_INT_10F_11F_11F_REV)) {
112 transferOps |= IMAGE_CLAMP_BIT;
113 }
114 }
115 else {
116 /* For CPU-based ReadPixels packing, the clamping must always be done
117 * for non-float types, */
118 if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) ||
119 (type != GL_FLOAT && type != GL_HALF_FLOAT &&
120 type != GL_UNSIGNED_INT_10F_11F_11F_REV)) {
121 transferOps |= IMAGE_CLAMP_BIT;
122 }
123
124 /* For SNORM formats we only clamp if `type` is signed and clamp is `true` */
125 if (!_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
126 _mesa_get_format_datatype(texFormat) == GL_SIGNED_NORMALIZED &&
127 (type == GL_BYTE || type == GL_SHORT || type == GL_INT)) {
128 transferOps &= ~IMAGE_CLAMP_BIT;
129 }
130 }
131
132 /* If the format is unsigned normalized, we can ignore clamping
133 * because the values are already in the range [0,1] so it won't
134 * have any effect anyway.
135 */
136 if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED &&
137 !_mesa_need_rgb_to_luminance_conversion(srcBaseFormat, dstBaseFormat)) {
138 transferOps &= ~IMAGE_CLAMP_BIT;
139 }
140
141 return transferOps;
142 }
143
144
145 /**
146 * Return true if memcpy cannot be used for ReadPixels.
147 *
148 * If uses_blit is true, the function returns true if a simple 3D engine blit
149 * cannot be used for ReadPixels packing.
150 *
151 * NOTE: This doesn't take swizzling and format conversions between
152 * the readbuffer and the pixel pack buffer into account.
153 */
154 GLboolean
_mesa_readpixels_needs_slow_path(const struct gl_context * ctx,GLenum format,GLenum type,GLboolean uses_blit)155 _mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format,
156 GLenum type, GLboolean uses_blit)
157 {
158 struct gl_renderbuffer *rb =
159 _mesa_get_read_renderbuffer_for_format(ctx, format);
160 GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
161
162 assert(rb);
163
164 /* There are different rules depending on the base format. */
165 switch (format) {
166 case GL_DEPTH_STENCIL:
167 return !_mesa_has_depthstencil_combined(ctx->ReadBuffer) ||
168 ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f ||
169 ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
170 ctx->Pixel.MapStencilFlag;
171
172 case GL_DEPTH_COMPONENT:
173 return ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
174
175 case GL_STENCIL_INDEX:
176 return ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
177 ctx->Pixel.MapStencilFlag;
178
179 default:
180 /* Color formats. */
181 if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat,
182 dstBaseFormat)) {
183 return GL_TRUE;
184 }
185
186 /* And finally, see if there are any transfer ops. */
187 return _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, type,
188 uses_blit) != 0;
189 }
190 return GL_FALSE;
191 }
192
193
194 static GLboolean
readpixels_can_use_memcpy(const struct gl_context * ctx,GLenum format,GLenum type,const struct gl_pixelstore_attrib * packing)195 readpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum type,
196 const struct gl_pixelstore_attrib *packing)
197 {
198 struct gl_renderbuffer *rb =
199 _mesa_get_read_renderbuffer_for_format(ctx, format);
200
201 assert(rb);
202
203 if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_FALSE)) {
204 return GL_FALSE;
205 }
206
207 /* The base internal format and the base Mesa format must match. */
208 if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) {
209 return GL_FALSE;
210 }
211
212 /* The Mesa format must match the input format and type. */
213 if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
214 packing->SwapBytes, NULL)) {
215 return GL_FALSE;
216 }
217
218 return GL_TRUE;
219 }
220
221
222 static GLboolean
readpixels_memcpy(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)223 readpixels_memcpy(struct gl_context *ctx,
224 GLint x, GLint y,
225 GLsizei width, GLsizei height,
226 GLenum format, GLenum type,
227 GLvoid *pixels,
228 const struct gl_pixelstore_attrib *packing)
229 {
230 struct gl_renderbuffer *rb =
231 _mesa_get_read_renderbuffer_for_format(ctx, format);
232 GLubyte *dst, *map;
233 int dstStride, stride, j, texelBytes, bytesPerRow;
234
235 /* Fail if memcpy cannot be used. */
236 if (!readpixels_can_use_memcpy(ctx, format, type, packing)) {
237 return GL_FALSE;
238 }
239
240 dstStride = _mesa_image_row_stride(packing, width, format, type);
241 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
242 format, type, 0, 0);
243
244 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
245 &map, &stride, ctx->ReadBuffer->FlipY);
246 if (!map) {
247 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
248 return GL_TRUE; /* don't bother trying the slow path */
249 }
250
251 texelBytes = _mesa_get_format_bytes(rb->Format);
252 bytesPerRow = texelBytes * width;
253
254 /* memcpy*/
255 if (dstStride == stride && dstStride == bytesPerRow) {
256 memcpy(dst, map, bytesPerRow * height);
257 } else {
258 for (j = 0; j < height; j++) {
259 memcpy(dst, map, bytesPerRow);
260 dst += dstStride;
261 map += stride;
262 }
263 }
264
265 ctx->Driver.UnmapRenderbuffer(ctx, rb);
266 return GL_TRUE;
267 }
268
269
270 /**
271 * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT,
272 * GL_UNSIGNED_INT.
273 */
274 static GLboolean
read_uint_depth_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)275 read_uint_depth_pixels( struct gl_context *ctx,
276 GLint x, GLint y,
277 GLsizei width, GLsizei height,
278 GLenum type, GLvoid *pixels,
279 const struct gl_pixelstore_attrib *packing )
280 {
281 struct gl_framebuffer *fb = ctx->ReadBuffer;
282 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
283 GLubyte *map, *dst;
284 int stride, dstStride, j;
285
286 if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F)
287 return GL_FALSE;
288
289 if (packing->SwapBytes)
290 return GL_FALSE;
291
292 if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
293 return GL_FALSE;
294
295 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
296 &map, &stride, fb->FlipY);
297
298 if (!map) {
299 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
300 return GL_TRUE; /* don't bother trying the slow path */
301 }
302
303 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
304 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
305 GL_DEPTH_COMPONENT, type, 0, 0);
306
307 for (j = 0; j < height; j++) {
308 _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
309
310 map += stride;
311 dst += dstStride;
312 }
313 ctx->Driver.UnmapRenderbuffer(ctx, rb);
314
315 return GL_TRUE;
316 }
317
318 /**
319 * Read pixels for format=GL_DEPTH_COMPONENT.
320 */
321 static void
read_depth_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)322 read_depth_pixels( struct gl_context *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 struct gl_framebuffer *fb = ctx->ReadBuffer;
329 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
330 GLint j;
331 GLubyte *dst, *map;
332 int dstStride, stride;
333 GLfloat *depthValues;
334
335 if (!rb)
336 return;
337
338 /* clipping should have been done already */
339 assert(x >= 0);
340 assert(y >= 0);
341 assert(x + width <= (GLint) rb->Width);
342 assert(y + height <= (GLint) rb->Height);
343
344 if (type == GL_UNSIGNED_INT &&
345 read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) {
346 return;
347 }
348
349 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
350 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
351 GL_DEPTH_COMPONENT, type, 0, 0);
352
353 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
354 &map, &stride, fb->FlipY);
355 if (!map) {
356 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
357 return;
358 }
359
360 depthValues = malloc(width * sizeof(GLfloat));
361
362 if (depthValues) {
363 /* General case (slower) */
364 for (j = 0; j < height; j++, y++) {
365 _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
366 _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);
367
368 dst += dstStride;
369 map += stride;
370 }
371 }
372 else {
373 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
374 }
375
376 free(depthValues);
377
378 ctx->Driver.UnmapRenderbuffer(ctx, rb);
379 }
380
381
382 /**
383 * Read pixels for format=GL_STENCIL_INDEX.
384 */
385 static void
read_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)386 read_stencil_pixels( struct gl_context *ctx,
387 GLint x, GLint y,
388 GLsizei width, GLsizei height,
389 GLenum type, GLvoid *pixels,
390 const struct gl_pixelstore_attrib *packing )
391 {
392 struct gl_framebuffer *fb = ctx->ReadBuffer;
393 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
394 GLint j;
395 GLubyte *map, *stencil;
396 GLint stride;
397
398 if (!rb)
399 return;
400
401 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
402 &map, &stride, fb->FlipY);
403 if (!map) {
404 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
405 return;
406 }
407
408 stencil = malloc(width * sizeof(GLubyte));
409
410 if (stencil) {
411 /* process image row by row */
412 for (j = 0; j < height; j++) {
413 GLvoid *dest;
414
415 _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
416 dest = _mesa_image_address2d(packing, pixels, width, height,
417 GL_STENCIL_INDEX, type, j, 0);
418
419 _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
420
421 map += stride;
422 }
423 }
424 else {
425 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
426 }
427
428 free(stencil);
429
430 ctx->Driver.UnmapRenderbuffer(ctx, rb);
431 }
432
433 /*
434 * Read R, G, B, A, RGB, L, or LA pixels.
435 */
436 static void
read_rgba_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)437 read_rgba_pixels( struct gl_context *ctx,
438 GLint x, GLint y,
439 GLsizei width, GLsizei height,
440 GLenum format, GLenum type, GLvoid *pixels,
441 const struct gl_pixelstore_attrib *packing )
442 {
443 GLbitfield transferOps;
444 bool dst_is_integer, convert_rgb_to_lum, needs_rebase;
445 int dst_stride, src_stride, rb_stride;
446 uint32_t dst_format, src_format;
447 GLubyte *dst, *map;
448 mesa_format rb_format;
449 bool needs_rgba;
450 void *rgba, *src;
451 bool src_is_uint = false;
452 uint8_t rebase_swizzle[4];
453 struct gl_framebuffer *fb = ctx->ReadBuffer;
454 struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
455 GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
456
457 if (!rb)
458 return;
459
460 transferOps = _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format,
461 type, GL_FALSE);
462 /* Describe the dst format */
463 dst_is_integer = _mesa_is_enum_format_integer(format);
464 dst_stride = _mesa_image_row_stride(packing, width, format, type);
465 dst_format = _mesa_format_from_format_and_type(format, type);
466 convert_rgb_to_lum =
467 _mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, dstBaseFormat);
468 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
469 format, type, 0, 0);
470
471 /* Map the source render buffer */
472 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
473 &map, &rb_stride, fb->FlipY);
474 if (!map) {
475 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
476 return;
477 }
478 rb_format = _mesa_get_srgb_format_linear(rb->Format);
479
480 /*
481 * Depending on the base formats involved in the conversion we might need to
482 * rebase some values, so for these formats we compute a rebase swizzle.
483 */
484 if (rb->_BaseFormat == GL_LUMINANCE || rb->_BaseFormat == GL_INTENSITY) {
485 needs_rebase = true;
486 rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
487 rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
488 rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
489 rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
490 } else if (rb->_BaseFormat == GL_LUMINANCE_ALPHA) {
491 needs_rebase = true;
492 rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
493 rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
494 rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
495 rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_W;
496 } else if (_mesa_get_format_base_format(rb_format) != rb->_BaseFormat) {
497 needs_rebase =
498 _mesa_compute_rgba2base2rgba_component_mapping(rb->_BaseFormat,
499 rebase_swizzle);
500 } else {
501 needs_rebase = false;
502 }
503
504 /* Since _mesa_format_convert does not handle transferOps we need to handle
505 * them before we call the function. This requires to convert to RGBA float
506 * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
507 * integer transferOps do not apply.
508 *
509 * Converting to luminance also requires converting to RGBA first, so we can
510 * then compute luminance values as L=R+G+B. Notice that this is different
511 * from GetTexImage, where we compute L=R.
512 */
513 assert(!transferOps || (transferOps && !dst_is_integer));
514
515 needs_rgba = transferOps || convert_rgb_to_lum;
516 rgba = NULL;
517 if (needs_rgba) {
518 uint32_t rgba_format;
519 int rgba_stride;
520 bool need_convert;
521
522 /* Convert to RGBA float or int/uint depending on the type of the src */
523 if (dst_is_integer) {
524 src_is_uint = _mesa_is_format_unsigned(rb_format);
525 if (src_is_uint) {
526 rgba_format = RGBA32_UINT;
527 rgba_stride = width * 4 * sizeof(GLuint);
528 } else {
529 rgba_format = RGBA32_INT;
530 rgba_stride = width * 4 * sizeof(GLint);
531 }
532 } else {
533 rgba_format = RGBA32_FLOAT;
534 rgba_stride = width * 4 * sizeof(GLfloat);
535 }
536
537 /* If we are lucky and the dst format matches the RGBA format we need to
538 * convert to, then we can convert directly into the dst buffer and avoid
539 * the final conversion/copy from the rgba buffer to the dst buffer.
540 */
541 if (dst_format == rgba_format &&
542 dst_stride == rgba_stride) {
543 need_convert = false;
544 rgba = dst;
545 } else {
546 need_convert = true;
547 rgba = malloc(height * rgba_stride);
548 if (!rgba) {
549 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
550 goto done_unmap;
551 }
552 }
553
554 /* Convert to RGBA now */
555 _mesa_format_convert(rgba, rgba_format, rgba_stride,
556 map, rb_format, rb_stride,
557 width, height,
558 needs_rebase ? rebase_swizzle : NULL);
559
560 /* Handle transfer ops if necessary */
561 if (transferOps)
562 _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);
563
564 /* If we had to rebase, we have already taken care of that */
565 needs_rebase = false;
566
567 /* If we were lucky and our RGBA conversion matches the dst format, then
568 * we are done.
569 */
570 if (!need_convert)
571 goto done_swap;
572
573 /* Otherwise, we need to convert from RGBA to dst next */
574 src = rgba;
575 src_format = rgba_format;
576 src_stride = rgba_stride;
577 } else {
578 /* No RGBA conversion needed, convert directly to dst */
579 src = map;
580 src_format = rb_format;
581 src_stride = rb_stride;
582 }
583
584 /* Do the conversion.
585 *
586 * If the dst format is Luminance, we need to do the conversion by computing
587 * L=R+G+B values.
588 */
589 if (!convert_rgb_to_lum) {
590 _mesa_format_convert(dst, dst_format, dst_stride,
591 src, src_format, src_stride,
592 width, height,
593 needs_rebase ? rebase_swizzle : NULL);
594 } else if (!dst_is_integer) {
595 /* Compute float Luminance values from RGBA float */
596 int luminance_stride, luminance_bytes;
597 void *luminance;
598 uint32_t luminance_format;
599
600 luminance_stride = width * sizeof(GLfloat);
601 if (format == GL_LUMINANCE_ALPHA)
602 luminance_stride *= 2;
603 luminance_bytes = height * luminance_stride;
604 luminance = malloc(luminance_bytes);
605 if (!luminance) {
606 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
607 free(rgba);
608 goto done_unmap;
609 }
610 _mesa_pack_luminance_from_rgba_float(width * height, src,
611 luminance, format, transferOps);
612
613 /* Convert from Luminance float to dst (this will hadle type conversion
614 * from float to the type of dst if necessary)
615 */
616 luminance_format = _mesa_format_from_format_and_type(format, GL_FLOAT);
617 _mesa_format_convert(dst, dst_format, dst_stride,
618 luminance, luminance_format, luminance_stride,
619 width, height, NULL);
620 free(luminance);
621 } else {
622 _mesa_pack_luminance_from_rgba_integer(width * height, src, !src_is_uint,
623 dst, format, type);
624 }
625
626 free(rgba);
627
628 done_swap:
629 /* Handle byte swapping if required */
630 if (packing->SwapBytes) {
631 _mesa_swap_bytes_2d_image(format, type, packing,
632 width, height, dst, dst);
633 }
634
635 done_unmap:
636 ctx->Driver.UnmapRenderbuffer(ctx, rb);
637 }
638
639 /**
640 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
641 * data (possibly swapping 8/24 vs 24/8 as we go).
642 */
643 static GLboolean
fast_read_depth_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLubyte * dst,int dstStride)644 fast_read_depth_stencil_pixels(struct gl_context *ctx,
645 GLint x, GLint y,
646 GLsizei width, GLsizei height,
647 GLubyte *dst, int dstStride)
648 {
649 struct gl_framebuffer *fb = ctx->ReadBuffer;
650 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
651 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
652 GLubyte *map;
653 int stride, i;
654
655 if (rb != stencilRb)
656 return GL_FALSE;
657
658 if (rb->Format != MESA_FORMAT_S8_UINT_Z24_UNORM &&
659 rb->Format != MESA_FORMAT_Z24_UNORM_S8_UINT)
660 return GL_FALSE;
661
662 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
663 &map, &stride, fb->FlipY);
664 if (!map) {
665 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
666 return GL_TRUE; /* don't bother trying the slow path */
667 }
668
669 for (i = 0; i < height; i++) {
670 _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
671 map, (GLuint *)dst);
672 map += stride;
673 dst += dstStride;
674 }
675
676 ctx->Driver.UnmapRenderbuffer(ctx, rb);
677
678 return GL_TRUE;
679 }
680
681
682 /**
683 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
684 * copy the integer data directly instead of converting depth to float and
685 * re-packing.
686 */
687 static GLboolean
fast_read_depth_stencil_pixels_separate(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,uint32_t * dst,int dstStride)688 fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
689 GLint x, GLint y,
690 GLsizei width, GLsizei height,
691 uint32_t *dst, int dstStride)
692 {
693 struct gl_framebuffer *fb = ctx->ReadBuffer;
694 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
695 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
696 GLubyte *depthMap, *stencilMap, *stencilVals;
697 int depthStride, stencilStride, i, j;
698
699 if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
700 return GL_FALSE;
701
702 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
703 GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
704 if (!depthMap) {
705 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
706 return GL_TRUE; /* don't bother trying the slow path */
707 }
708
709 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
710 GL_MAP_READ_BIT, &stencilMap, &stencilStride, fb->FlipY);
711 if (!stencilMap) {
712 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
713 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
714 return GL_TRUE; /* don't bother trying the slow path */
715 }
716
717 stencilVals = malloc(width * sizeof(GLubyte));
718
719 if (stencilVals) {
720 for (j = 0; j < height; j++) {
721 _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
722 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
723 stencilMap, stencilVals);
724
725 for (i = 0; i < width; i++) {
726 dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
727 }
728
729 depthMap += depthStride;
730 stencilMap += stencilStride;
731 dst += dstStride / 4;
732 }
733 }
734 else {
735 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
736 }
737
738 free(stencilVals);
739
740 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
741 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
742
743 return GL_TRUE;
744 }
745
746 static void
slow_read_depth_stencil_pixels_separate(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,const struct gl_pixelstore_attrib * packing,GLubyte * dst,int dstStride)747 slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
748 GLint x, GLint y,
749 GLsizei width, GLsizei height,
750 GLenum type,
751 const struct gl_pixelstore_attrib *packing,
752 GLubyte *dst, int dstStride)
753 {
754 struct gl_framebuffer *fb = ctx->ReadBuffer;
755 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
756 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
757 GLubyte *depthMap, *stencilMap;
758 int depthStride, stencilStride, j;
759 GLubyte *stencilVals;
760 GLfloat *depthVals;
761
762
763 /* The depth and stencil buffers might be separate, or a single buffer.
764 * If one buffer, only map it once.
765 */
766 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
767 GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
768 if (!depthMap) {
769 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
770 return;
771 }
772
773 if (stencilRb != depthRb) {
774 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
775 GL_MAP_READ_BIT, &stencilMap,
776 &stencilStride, fb->FlipY);
777 if (!stencilMap) {
778 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
779 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
780 return;
781 }
782 }
783 else {
784 stencilMap = depthMap;
785 stencilStride = depthStride;
786 }
787
788 stencilVals = malloc(width * sizeof(GLubyte));
789 depthVals = malloc(width * sizeof(GLfloat));
790
791 if (stencilVals && depthVals) {
792 for (j = 0; j < height; j++) {
793 _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
794 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
795 stencilMap, stencilVals);
796
797 _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
798 depthVals, stencilVals, packing);
799
800 depthMap += depthStride;
801 stencilMap += stencilStride;
802 dst += dstStride;
803 }
804 }
805 else {
806 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
807 }
808
809 free(stencilVals);
810 free(depthVals);
811
812 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
813 if (stencilRb != depthRb) {
814 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
815 }
816 }
817
818
819 /**
820 * Read combined depth/stencil values.
821 * We'll have already done error checking to be sure the expected
822 * depth and stencil buffers really exist.
823 */
824 static void
read_depth_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)825 read_depth_stencil_pixels(struct gl_context *ctx,
826 GLint x, GLint y,
827 GLsizei width, GLsizei height,
828 GLenum type, GLvoid *pixels,
829 const struct gl_pixelstore_attrib *packing )
830 {
831 const GLboolean scaleOrBias
832 = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
833 const GLboolean stencilTransfer = ctx->Pixel.IndexShift
834 || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
835 GLubyte *dst;
836 int dstStride;
837
838 dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
839 width, height,
840 GL_DEPTH_STENCIL_EXT,
841 type, 0, 0);
842 dstStride = _mesa_image_row_stride(packing, width,
843 GL_DEPTH_STENCIL_EXT, type);
844
845 /* Fast 24/8 reads. */
846 if (type == GL_UNSIGNED_INT_24_8 &&
847 !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
848 if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
849 dst, dstStride))
850 return;
851
852 if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
853 (uint32_t *)dst, dstStride))
854 return;
855 }
856
857 slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
858 type, packing,
859 dst, dstStride);
860 }
861
862
863
864 /**
865 * Software fallback routine for ctx->Driver.ReadPixels().
866 * By time we get here, all error checking will have been done.
867 */
868 void
_mesa_readpixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * packing,GLvoid * pixels)869 _mesa_readpixels(struct gl_context *ctx,
870 GLint x, GLint y, GLsizei width, GLsizei height,
871 GLenum format, GLenum type,
872 const struct gl_pixelstore_attrib *packing,
873 GLvoid *pixels)
874 {
875 if (ctx->NewState)
876 _mesa_update_state(ctx);
877
878 pixels = _mesa_map_pbo_dest(ctx, packing, pixels);
879
880 if (pixels) {
881 /* Try memcpy first. */
882 if (readpixels_memcpy(ctx, x, y, width, height, format, type,
883 pixels, packing)) {
884 _mesa_unmap_pbo_dest(ctx, packing);
885 return;
886 }
887
888 /* Otherwise take the slow path. */
889 switch (format) {
890 case GL_STENCIL_INDEX:
891 read_stencil_pixels(ctx, x, y, width, height, type, pixels,
892 packing);
893 break;
894 case GL_DEPTH_COMPONENT:
895 read_depth_pixels(ctx, x, y, width, height, type, pixels,
896 packing);
897 break;
898 case GL_DEPTH_STENCIL_EXT:
899 read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
900 packing);
901 break;
902 default:
903 /* all other formats should be color formats */
904 read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
905 packing);
906 }
907
908 _mesa_unmap_pbo_dest(ctx, packing);
909 }
910 }
911
912
913 static GLenum
read_pixels_es3_error_check(struct gl_context * ctx,GLenum format,GLenum type,const struct gl_renderbuffer * rb)914 read_pixels_es3_error_check(struct gl_context *ctx, GLenum format, GLenum type,
915 const struct gl_renderbuffer *rb)
916 {
917 const GLenum internalFormat = rb->InternalFormat;
918 const GLenum data_type = _mesa_get_format_datatype(rb->Format);
919 GLboolean is_unsigned_int = GL_FALSE;
920 GLboolean is_signed_int = GL_FALSE;
921 GLboolean is_float_depth = _mesa_has_depth_float_channel(internalFormat);
922
923 is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat);
924 if (!is_unsigned_int) {
925 is_signed_int = _mesa_is_enum_format_signed_int(internalFormat);
926 }
927
928 switch (format) {
929 case GL_RGBA:
930 if (type == GL_FLOAT && data_type == GL_FLOAT)
931 return GL_NO_ERROR; /* EXT_color_buffer_float */
932 if (type == GL_UNSIGNED_BYTE && data_type == GL_UNSIGNED_NORMALIZED)
933 return GL_NO_ERROR;
934 if (internalFormat == GL_RGB10_A2 &&
935 type == GL_UNSIGNED_INT_2_10_10_10_REV)
936 return GL_NO_ERROR;
937 if (internalFormat == GL_RGB10_A2UI && type == GL_UNSIGNED_BYTE)
938 return GL_NO_ERROR;
939 if (type == GL_UNSIGNED_SHORT) {
940 switch (internalFormat) {
941 case GL_R16:
942 case GL_RG16:
943 case GL_RGB16:
944 case GL_RGBA16:
945 if (_mesa_has_EXT_texture_norm16(ctx))
946 return GL_NO_ERROR;
947 }
948 }
949 if (type == GL_SHORT) {
950 switch (internalFormat) {
951 case GL_R16_SNORM:
952 case GL_RG16_SNORM:
953 case GL_RGBA16_SNORM:
954 if (_mesa_has_EXT_texture_norm16(ctx) &&
955 _mesa_has_EXT_render_snorm(ctx))
956 return GL_NO_ERROR;
957 }
958 }
959 if (type == GL_BYTE) {
960 switch (internalFormat) {
961 case GL_R8_SNORM:
962 case GL_RG8_SNORM:
963 case GL_RGBA8_SNORM:
964 if (_mesa_has_EXT_render_snorm(ctx))
965 return GL_NO_ERROR;
966 }
967 }
968 if (type == GL_UNSIGNED_BYTE) {
969 switch (internalFormat) {
970 case GL_R8_SNORM:
971 case GL_RG8_SNORM:
972 case GL_RGBA8_SNORM:
973 if (_mesa_has_EXT_render_snorm(ctx))
974 return GL_NO_ERROR;
975 }
976 }
977 break;
978 case GL_BGRA:
979 /* GL_EXT_read_format_bgra */
980 if (type == GL_UNSIGNED_BYTE ||
981 type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
982 type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
983 return GL_NO_ERROR;
984 break;
985 case GL_RGBA_INTEGER:
986 if ((is_signed_int && type == GL_INT) ||
987 (is_unsigned_int && type == GL_UNSIGNED_INT))
988 return GL_NO_ERROR;
989 break;
990 case GL_DEPTH_STENCIL:
991 switch (type) {
992 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
993 if (is_float_depth)
994 return GL_NO_ERROR;
995 break;
996 case GL_UNSIGNED_INT_24_8:
997 if (!is_float_depth)
998 return GL_NO_ERROR;
999 break;
1000 default:
1001 return GL_INVALID_ENUM;
1002 }
1003 break;
1004 case GL_DEPTH_COMPONENT:
1005 switch (type) {
1006 case GL_FLOAT:
1007 if (is_float_depth)
1008 return GL_NO_ERROR;
1009 break;
1010 case GL_UNSIGNED_SHORT:
1011 case GL_UNSIGNED_INT:
1012 case GL_UNSIGNED_INT_24_8:
1013 if (!is_float_depth)
1014 return GL_NO_ERROR;
1015 break;
1016 default:
1017 return GL_INVALID_ENUM;
1018 }
1019 break;
1020 case GL_STENCIL_INDEX:
1021 switch (type) {
1022 case GL_UNSIGNED_BYTE:
1023 return GL_NO_ERROR;
1024 default:
1025 return GL_INVALID_ENUM;
1026 }
1027 break;
1028 }
1029
1030 return GL_INVALID_OPERATION;
1031 }
1032
1033
1034 static ALWAYS_INLINE void
read_pixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLvoid * pixels,bool no_error)1035 read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
1036 GLenum type, GLsizei bufSize, GLvoid *pixels, bool no_error)
1037 {
1038 GLenum err = GL_NO_ERROR;
1039 struct gl_renderbuffer *rb;
1040 struct gl_pixelstore_attrib clippedPacking;
1041
1042 GET_CURRENT_CONTEXT(ctx);
1043
1044 FLUSH_VERTICES(ctx, 0, 0);
1045
1046 if (MESA_VERBOSE & VERBOSE_API)
1047 _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
1048 width, height,
1049 _mesa_enum_to_string(format),
1050 _mesa_enum_to_string(type),
1051 pixels);
1052
1053 if (!no_error && (width < 0 || height < 0)) {
1054 _mesa_error( ctx, GL_INVALID_VALUE,
1055 "glReadPixels(width=%d height=%d)", width, height );
1056 return;
1057 }
1058
1059 _mesa_update_pixel(ctx);
1060
1061 if (ctx->NewState)
1062 _mesa_update_state(ctx);
1063
1064 if (!no_error && ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1065 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1066 "glReadPixels(incomplete framebuffer)" );
1067 return;
1068 }
1069
1070 rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
1071 if (!no_error) {
1072 if (rb == NULL) {
1073 _mesa_error(ctx, GL_INVALID_OPERATION,
1074 "glReadPixels(read buffer)");
1075 return;
1076 }
1077
1078 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
1079 * combinations of format and type that can be used.
1080 *
1081 * Technically, only two combinations are actually allowed:
1082 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
1083 * preferred combination. This code doesn't know what that preferred
1084 * combination is, and Mesa can handle anything valid. Just work instead.
1085 */
1086 if (_mesa_is_gles(ctx)) {
1087 if (ctx->API == API_OPENGLES2 &&
1088 _mesa_is_color_format(format) &&
1089 _mesa_get_color_read_format(ctx, NULL, "glReadPixels") == format &&
1090 _mesa_get_color_read_type(ctx, NULL, "glReadPixels") == type) {
1091 err = GL_NO_ERROR;
1092 } else if (ctx->Version < 30) {
1093 err = _mesa_es_error_check_format_and_type(ctx, format, type, 2);
1094 if (err == GL_NO_ERROR) {
1095 if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
1096 err = GL_INVALID_OPERATION;
1097 }
1098 }
1099 } else {
1100 err = read_pixels_es3_error_check(ctx, format, type, rb);
1101 }
1102
1103 if (err != GL_NO_ERROR) {
1104 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
1105 _mesa_enum_to_string(format),
1106 _mesa_enum_to_string(type));
1107 return;
1108 }
1109 }
1110
1111 err = _mesa_error_check_format_and_type(ctx, format, type);
1112 if (err != GL_NO_ERROR) {
1113 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
1114 _mesa_enum_to_string(format),
1115 _mesa_enum_to_string(type));
1116 return;
1117 }
1118
1119 if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
1120 ctx->ReadBuffer->Visual.samples > 0) {
1121 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
1122 return;
1123 }
1124
1125 if (!_mesa_source_buffer_exists(ctx, format)) {
1126 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
1127 return;
1128 }
1129
1130 /* Check that the destination format and source buffer are both
1131 * integer-valued or both non-integer-valued.
1132 */
1133 if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
1134 const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
1135 const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
1136 const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
1137 if (dstInteger != srcInteger) {
1138 _mesa_error(ctx, GL_INVALID_OPERATION,
1139 "glReadPixels(integer / non-integer format mismatch");
1140 return;
1141 }
1142 }
1143 }
1144
1145 /* Do all needed clipping here, so that we can forget about it later */
1146 clippedPacking = ctx->Pack;
1147 if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking))
1148 return; /* nothing to do */
1149
1150 if (!no_error) {
1151 if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
1152 format, type, bufSize, pixels)) {
1153 if (ctx->Pack.BufferObj) {
1154 _mesa_error(ctx, GL_INVALID_OPERATION,
1155 "glReadPixels(out of bounds PBO access)");
1156 } else {
1157 _mesa_error(ctx, GL_INVALID_OPERATION,
1158 "glReadnPixelsARB(out of bounds access:"
1159 " bufSize (%d) is too small)", bufSize);
1160 }
1161 return;
1162 }
1163
1164 if (ctx->Pack.BufferObj &&
1165 _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
1166 /* buffer is mapped - that's an error */
1167 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
1168 return;
1169 }
1170 }
1171
1172 ctx->Driver.ReadPixels(ctx, x, y, width, height,
1173 format, type, &clippedPacking, pixels);
1174 }
1175
1176 void GLAPIENTRY
_mesa_ReadnPixelsARB_no_error(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLvoid * pixels)1177 _mesa_ReadnPixelsARB_no_error(GLint x, GLint y, GLsizei width, GLsizei height,
1178 GLenum format, GLenum type, GLsizei bufSize,
1179 GLvoid *pixels)
1180 {
1181 read_pixels(x, y, width, height, format, type, bufSize, pixels, true);
1182 }
1183
1184 void GLAPIENTRY
_mesa_ReadnPixelsARB(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLvoid * pixels)1185 _mesa_ReadnPixelsARB(GLint x, GLint y, GLsizei width, GLsizei height,
1186 GLenum format, GLenum type, GLsizei bufSize,
1187 GLvoid *pixels)
1188 {
1189 read_pixels(x, y, width, height, format, type, bufSize, pixels, false);
1190 }
1191
1192 void GLAPIENTRY
_mesa_ReadPixels_no_error(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)1193 _mesa_ReadPixels_no_error(GLint x, GLint y, GLsizei width, GLsizei height,
1194 GLenum format, GLenum type, GLvoid *pixels)
1195 {
1196 _mesa_ReadnPixelsARB_no_error(x, y, width, height, format, type, INT_MAX,
1197 pixels);
1198 }
1199
1200 void GLAPIENTRY
_mesa_ReadPixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)1201 _mesa_ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1202 GLenum format, GLenum type, GLvoid *pixels)
1203 {
1204 _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
1205 }
1206