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