~ubuntu-branches/ubuntu/precise/mesa-lts-quantal/precise-updates

« back to all changes in this revision

Viewing changes to src/mesa/main/readpix.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 20:58:34 UTC
  • Revision ID: package-import@ubuntu.com-20121130205834-gazuvne3fpwlf012
Tags: upstream-9.0
ImportĀ upstreamĀ versionĀ 9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Mesa 3-D graphics library
 
3
 * Version:  7.1
 
4
 *
 
5
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
 
6
 *
 
7
 * Permission is hereby granted, free of charge, to any person obtaining a
 
8
 * copy of this software and associated documentation files (the "Software"),
 
9
 * to deal in the Software without restriction, including without limitation
 
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
11
 * and/or sell copies of the Software, and to permit persons to whom the
 
12
 * Software is furnished to do so, subject to the following conditions:
 
13
 *
 
14
 * The above copyright notice and this permission notice shall be included
 
15
 * in all copies or substantial portions of the Software.
 
16
 *
 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
20
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
21
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 */
 
24
 
 
25
#include "glheader.h"
 
26
#include "imports.h"
 
27
#include "bufferobj.h"
 
28
#include "context.h"
 
29
#include "enums.h"
 
30
#include "readpix.h"
 
31
#include "framebuffer.h"
 
32
#include "formats.h"
 
33
#include "format_unpack.h"
 
34
#include "image.h"
 
35
#include "mtypes.h"
 
36
#include "pack.h"
 
37
#include "pbo.h"
 
38
#include "state.h"
 
39
#include "glformats.h"
 
40
#include "fbobject.h"
 
41
#include "teximage.h"
 
42
 
 
43
/* Inexplicably, GL_HALF_FLOAT_OES has a different value than GL_HALF_FLOAT.
 
44
 */
 
45
#ifndef GL_HALF_FLOAT_OES
 
46
#define GL_HALF_FLOAT_OES 0x8D61
 
47
#endif
 
48
 
 
49
/**
 
50
 * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the
 
51
 * mapping.
 
52
 */
 
53
static GLboolean
 
54
fast_read_depth_pixels( struct gl_context *ctx,
 
55
                        GLint x, GLint y,
 
56
                        GLsizei width, GLsizei height,
 
57
                        GLenum type, GLvoid *pixels,
 
58
                        const struct gl_pixelstore_attrib *packing )
 
59
{
 
60
   struct gl_framebuffer *fb = ctx->ReadBuffer;
 
61
   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
 
62
   GLubyte *map, *dst;
 
63
   int stride, dstStride, j;
 
64
 
 
65
   if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0)
 
66
      return GL_FALSE;
 
67
 
 
68
   if (packing->SwapBytes)
 
69
      return GL_FALSE;
 
70
 
 
71
   if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
 
72
      return GL_FALSE;
 
73
 
 
74
   if (!((type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16) ||
 
75
         type == GL_UNSIGNED_INT))
 
76
      return GL_FALSE;
 
77
 
 
78
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
 
79
                               &map, &stride);
 
80
 
 
81
   if (!map) {
 
82
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
83
      return GL_TRUE;  /* don't bother trying the slow path */
 
84
   }
 
85
 
 
86
   dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
 
87
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
 
88
                                           GL_DEPTH_COMPONENT, type, 0, 0);
 
89
 
 
90
   for (j = 0; j < height; j++) {
 
91
      if (type == GL_UNSIGNED_INT) {
 
92
         _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
 
93
      } else {
 
94
         ASSERT(type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16);
 
95
         memcpy(dst, map, width * 2);
 
96
      }
 
97
 
 
98
      map += stride;
 
99
      dst += dstStride;
 
100
   }
 
101
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
 
102
 
 
103
   return GL_TRUE;
 
104
}
 
105
 
 
106
/**
 
107
 * Read pixels for format=GL_DEPTH_COMPONENT.
 
108
 */
 
109
static void
 
110
read_depth_pixels( struct gl_context *ctx,
 
111
                   GLint x, GLint y,
 
112
                   GLsizei width, GLsizei height,
 
113
                   GLenum type, GLvoid *pixels,
 
114
                   const struct gl_pixelstore_attrib *packing )
 
115
{
 
116
   struct gl_framebuffer *fb = ctx->ReadBuffer;
 
117
   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
 
118
   GLint j;
 
119
   GLubyte *dst, *map;
 
120
   int dstStride, stride;
 
121
   GLfloat *depthValues;
 
122
 
 
123
   if (!rb)
 
124
      return;
 
125
 
 
126
   /* clipping should have been done already */
 
127
   ASSERT(x >= 0);
 
128
   ASSERT(y >= 0);
 
129
   ASSERT(x + width <= (GLint) rb->Width);
 
130
   ASSERT(y + height <= (GLint) rb->Height);
 
131
 
 
132
   if (fast_read_depth_pixels(ctx, x, y, width, height, type, pixels, packing))
 
133
      return;
 
134
 
 
135
   dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
 
136
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
 
137
                                           GL_DEPTH_COMPONENT, type, 0, 0);
 
138
 
 
139
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
 
140
                               &map, &stride);
 
141
   if (!map) {
 
142
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
143
      return;
 
144
   }
 
145
 
 
146
   depthValues = (GLfloat *) malloc(width * sizeof(GLfloat));
 
147
 
 
148
   if (depthValues) {
 
149
      /* General case (slower) */
 
150
      for (j = 0; j < height; j++, y++) {
 
151
         _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
 
152
         _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);
 
153
 
 
154
         dst += dstStride;
 
155
         map += stride;
 
156
      }
 
157
   }
 
158
   else {
 
159
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
160
   }
 
161
 
 
162
   free(depthValues);
 
163
 
 
164
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
 
165
}
 
166
 
 
167
 
 
168
/**
 
169
 * Read pixels for format=GL_STENCIL_INDEX.
 
170
 */
 
171
static void
 
172
read_stencil_pixels( struct gl_context *ctx,
 
173
                     GLint x, GLint y,
 
174
                     GLsizei width, GLsizei height,
 
175
                     GLenum type, GLvoid *pixels,
 
176
                     const struct gl_pixelstore_attrib *packing )
 
177
{
 
178
   struct gl_framebuffer *fb = ctx->ReadBuffer;
 
179
   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
 
180
   GLint j;
 
181
   GLubyte *map, *stencil;
 
182
   GLint stride;
 
183
 
 
184
   if (!rb)
 
185
      return;
 
186
 
 
187
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
 
188
                               &map, &stride);
 
189
   if (!map) {
 
190
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
191
      return;
 
192
   }
 
193
 
 
194
   stencil = (GLubyte *) malloc(width * sizeof(GLubyte));
 
195
 
 
196
   if (stencil) {
 
197
      /* process image row by row */
 
198
      for (j = 0; j < height; j++) {
 
199
         GLvoid *dest;
 
200
 
 
201
         _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
 
202
         dest = _mesa_image_address2d(packing, pixels, width, height,
 
203
                                      GL_STENCIL_INDEX, type, j, 0);
 
204
 
 
205
         _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
 
206
 
 
207
         map += stride;
 
208
      }
 
209
   }
 
210
   else {
 
211
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
212
   }
 
213
 
 
214
   free(stencil);
 
215
 
 
216
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
 
217
}
 
218
 
 
219
 
 
220
/**
 
221
 * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle.
 
222
 * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)
 
223
 */
 
224
static GLboolean
 
225
fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
 
226
                              GLint x, GLint y,
 
227
                              GLsizei width, GLsizei height,
 
228
                              GLenum format, GLenum type,
 
229
                              GLvoid *pixels,
 
230
                              const struct gl_pixelstore_attrib *packing,
 
231
                              GLbitfield transferOps )
 
232
{
 
233
   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
 
234
   GLubyte *dst, *map;
 
235
   int dstStride, stride, j, texelBytes;
 
236
   GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE;
 
237
 
 
238
   /* XXX we could check for other swizzle/special cases here as needed */
 
239
   if (rb->Format == MESA_FORMAT_RGBA8888_REV &&
 
240
       format == GL_BGRA &&
 
241
       type == GL_UNSIGNED_INT_8_8_8_8_REV &&
 
242
       !ctx->Pack.SwapBytes) {
 
243
      swizzle_rb = GL_TRUE;
 
244
   }
 
245
   else if (rb->Format == MESA_FORMAT_XRGB8888 &&
 
246
       format == GL_BGRA &&
 
247
       type == GL_UNSIGNED_INT_8_8_8_8_REV &&
 
248
       !ctx->Pack.SwapBytes) {
 
249
      copy_xrgb = GL_TRUE;
 
250
   }
 
251
   else if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
 
252
                                                  ctx->Pack.SwapBytes))
 
253
      return GL_FALSE;
 
254
 
 
255
   /* If the format is unsigned normalized then we can ignore clamping
 
256
    * because the values are already in the range [0,1] so it won't
 
257
    * have any effect anyway.
 
258
    */
 
259
   if (_mesa_get_format_datatype(rb->Format) == GL_UNSIGNED_NORMALIZED)
 
260
      transferOps &= ~IMAGE_CLAMP_BIT;
 
261
 
 
262
   if (transferOps)
 
263
      return GL_FALSE;
 
264
 
 
265
   dstStride = _mesa_image_row_stride(packing, width, format, type);
 
266
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
 
267
                                           format, type, 0, 0);
 
268
 
 
269
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
 
270
                               &map, &stride);
 
271
   if (!map) {
 
272
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
273
      return GL_TRUE;  /* don't bother trying the slow path */
 
274
   }
 
275
 
 
276
   texelBytes = _mesa_get_format_bytes(rb->Format);
 
277
 
 
278
   if (swizzle_rb) {
 
279
      /* swap R/B */
 
280
      for (j = 0; j < height; j++) {
 
281
         int i;
 
282
         for (i = 0; i < width; i++) {
 
283
            GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
 
284
            GLuint pixel = map4[i];
 
285
            dst4[i] = (pixel & 0xff00ff00)
 
286
                   | ((pixel & 0x00ff0000) >> 16)
 
287
                   | ((pixel & 0x000000ff) << 16);
 
288
         }
 
289
         dst += dstStride;
 
290
         map += stride;
 
291
      }
 
292
   } else if (copy_xrgb) {
 
293
      /* convert xrgb -> argb */
 
294
      for (j = 0; j < height; j++) {
 
295
         GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
 
296
         int i;
 
297
         for (i = 0; i < width; i++) {
 
298
            dst4[i] = map4[i] | 0xff000000;  /* set A=0xff */
 
299
         }
 
300
         dst += dstStride;
 
301
         map += stride;
 
302
      }
 
303
   } else {
 
304
      /* just memcpy */
 
305
      for (j = 0; j < height; j++) {
 
306
         memcpy(dst, map, width * texelBytes);
 
307
         dst += dstStride;
 
308
         map += stride;
 
309
      }
 
310
   }
 
311
 
 
312
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
 
313
 
 
314
   return GL_TRUE;
 
315
}
 
316
 
 
317
static void
 
318
slow_read_rgba_pixels( struct gl_context *ctx,
 
319
                       GLint x, GLint y,
 
320
                       GLsizei width, GLsizei height,
 
321
                       GLenum format, GLenum type,
 
322
                       GLvoid *pixels,
 
323
                       const struct gl_pixelstore_attrib *packing,
 
324
                       GLbitfield transferOps )
 
325
{
 
326
   struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
 
327
   const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format);
 
328
   void *rgba;
 
329
   GLubyte *dst, *map;
 
330
   int dstStride, stride, j;
 
331
   GLboolean dst_is_integer = _mesa_is_enum_format_integer(format);
 
332
   GLboolean dst_is_uint = _mesa_is_format_unsigned(rbFormat);
 
333
 
 
334
   dstStride = _mesa_image_row_stride(packing, width, format, type);
 
335
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
 
336
                                           format, type, 0, 0);
 
337
 
 
338
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
 
339
                               &map, &stride);
 
340
   if (!map) {
 
341
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
342
      return;
 
343
   }
 
344
 
 
345
   rgba = malloc(width * MAX_PIXEL_BYTES);
 
346
   if (!rgba)
 
347
      goto done;
 
348
 
 
349
   for (j = 0; j < height; j++) {
 
350
      if (dst_is_integer) {
 
351
         _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba);
 
352
         _mesa_rebase_rgba_uint(width, (GLuint (*)[4]) rgba,
 
353
                                rb->_BaseFormat);
 
354
         if (dst_is_uint) {
 
355
            _mesa_pack_rgba_span_from_uints(ctx, width, (GLuint (*)[4]) rgba, format,
 
356
                                            type, dst);
 
357
         } else {
 
358
            _mesa_pack_rgba_span_from_ints(ctx, width, (GLint (*)[4]) rgba, format,
 
359
                                           type, dst);
 
360
         }
 
361
      } else {
 
362
         _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba);
 
363
         _mesa_rebase_rgba_float(width, (GLfloat (*)[4]) rgba,
 
364
                                 rb->_BaseFormat);
 
365
         _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
 
366
                                    type, dst, packing, transferOps);
 
367
      }
 
368
      dst += dstStride;
 
369
      map += stride;
 
370
   }
 
371
 
 
372
   free(rgba);
 
373
 
 
374
done:
 
375
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
 
376
}
 
377
 
 
378
/*
 
379
 * Read R, G, B, A, RGB, L, or LA pixels.
 
380
 */
 
381
static void
 
382
read_rgba_pixels( struct gl_context *ctx,
 
383
                  GLint x, GLint y,
 
384
                  GLsizei width, GLsizei height,
 
385
                  GLenum format, GLenum type, GLvoid *pixels,
 
386
                  const struct gl_pixelstore_attrib *packing )
 
387
{
 
388
   GLbitfield transferOps = ctx->_ImageTransferState;
 
389
   struct gl_framebuffer *fb = ctx->ReadBuffer;
 
390
   struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
 
391
 
 
392
   if (!rb)
 
393
      return;
 
394
 
 
395
   if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) &&
 
396
       !_mesa_is_enum_format_integer(format)) {
 
397
      transferOps |= IMAGE_CLAMP_BIT;
 
398
   }
 
399
 
 
400
   /* Try the optimized paths first. */
 
401
   if (fast_read_rgba_pixels_memcpy(ctx, x, y, width, height,
 
402
                                    format, type, pixels, packing,
 
403
                                    transferOps)) {
 
404
      return;
 
405
   }
 
406
 
 
407
   slow_read_rgba_pixels(ctx, x, y, width, height,
 
408
                         format, type, pixels, packing, transferOps);
 
409
}
 
410
 
 
411
/**
 
412
 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
 
413
 * data (possibly swapping 8/24 vs 24/8 as we go).
 
414
 */
 
415
static GLboolean
 
416
fast_read_depth_stencil_pixels(struct gl_context *ctx,
 
417
                               GLint x, GLint y,
 
418
                               GLsizei width, GLsizei height,
 
419
                               GLubyte *dst, int dstStride)
 
420
{
 
421
   struct gl_framebuffer *fb = ctx->ReadBuffer;
 
422
   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
 
423
   struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
 
424
   GLubyte *map;
 
425
   int stride, i;
 
426
 
 
427
   if (rb != stencilRb)
 
428
      return GL_FALSE;
 
429
 
 
430
   if (rb->Format != MESA_FORMAT_Z24_S8 &&
 
431
       rb->Format != MESA_FORMAT_S8_Z24)
 
432
      return GL_FALSE;
 
433
 
 
434
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
 
435
                               &map, &stride);
 
436
   if (!map) {
 
437
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
438
      return GL_TRUE;  /* don't bother trying the slow path */
 
439
   }
 
440
 
 
441
   for (i = 0; i < height; i++) {
 
442
      _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
 
443
                                               map, (GLuint *)dst);
 
444
      map += stride;
 
445
      dst += dstStride;
 
446
   }
 
447
 
 
448
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
 
449
 
 
450
   return GL_TRUE;
 
451
}
 
452
 
 
453
 
 
454
/**
 
455
 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
 
456
 * copy the integer data directly instead of converting depth to float and
 
457
 * re-packing.
 
458
 */
 
459
static GLboolean
 
460
fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
 
461
                                        GLint x, GLint y,
 
462
                                        GLsizei width, GLsizei height,
 
463
                                        uint32_t *dst, int dstStride)
 
464
{
 
465
   struct gl_framebuffer *fb = ctx->ReadBuffer;
 
466
   struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
 
467
   struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
 
468
   GLubyte *depthMap, *stencilMap, *stencilVals;
 
469
   int depthStride, stencilStride, i, j;
 
470
 
 
471
   if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
 
472
      return GL_FALSE;
 
473
 
 
474
   ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
 
475
                               GL_MAP_READ_BIT, &depthMap, &depthStride);
 
476
   if (!depthMap) {
 
477
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
478
      return GL_TRUE;  /* don't bother trying the slow path */
 
479
   }
 
480
 
 
481
   ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
 
482
                               GL_MAP_READ_BIT, &stencilMap, &stencilStride);
 
483
   if (!stencilMap) {
 
484
      ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
 
485
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
486
      return GL_TRUE;  /* don't bother trying the slow path */
 
487
   }
 
488
 
 
489
   stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte));
 
490
 
 
491
   if (stencilVals) {
 
492
      for (j = 0; j < height; j++) {
 
493
         _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
 
494
         _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
 
495
                                        stencilMap, stencilVals);
 
496
 
 
497
         for (i = 0; i < width; i++) {
 
498
            dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
 
499
         }
 
500
 
 
501
         depthMap += depthStride;
 
502
         stencilMap += stencilStride;
 
503
         dst += dstStride / 4;
 
504
      }
 
505
   }
 
506
   else {
 
507
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
508
   }
 
509
 
 
510
   free(stencilVals);
 
511
 
 
512
   ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
 
513
   ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
 
514
 
 
515
   return GL_TRUE;
 
516
}
 
517
 
 
518
static void
 
519
slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
 
520
                                        GLint x, GLint y,
 
521
                                        GLsizei width, GLsizei height,
 
522
                                        GLenum type,
 
523
                                        const struct gl_pixelstore_attrib *packing,
 
524
                                        GLubyte *dst, int dstStride)
 
525
{
 
526
   struct gl_framebuffer *fb = ctx->ReadBuffer;
 
527
   struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
 
528
   struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
 
529
   GLubyte *depthMap, *stencilMap;
 
530
   int depthStride, stencilStride, j;
 
531
   GLubyte *stencilVals;
 
532
   GLfloat *depthVals;
 
533
 
 
534
 
 
535
   /* The depth and stencil buffers might be separate, or a single buffer.
 
536
    * If one buffer, only map it once.
 
537
    */
 
538
   ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
 
539
                               GL_MAP_READ_BIT, &depthMap, &depthStride);
 
540
   if (!depthMap) {
 
541
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
542
      return;
 
543
   }
 
544
 
 
545
   if (stencilRb != depthRb) {
 
546
      ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
 
547
                                  GL_MAP_READ_BIT, &stencilMap,
 
548
                                  &stencilStride);
 
549
      if (!stencilMap) {
 
550
         ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
 
551
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
552
         return;
 
553
      }
 
554
   }
 
555
   else {
 
556
      stencilMap = depthMap;
 
557
      stencilStride = depthStride;
 
558
   }
 
559
 
 
560
   stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte));
 
561
   depthVals = (GLfloat *) malloc(width * sizeof(GLfloat));
 
562
 
 
563
   if (stencilVals && depthVals) {
 
564
      for (j = 0; j < height; j++) {
 
565
         _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
 
566
         _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
 
567
                                        stencilMap, stencilVals);
 
568
 
 
569
         _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
 
570
                                       depthVals, stencilVals, packing);
 
571
 
 
572
         depthMap += depthStride;
 
573
         stencilMap += stencilStride;
 
574
         dst += dstStride;
 
575
      }
 
576
   }
 
577
   else {
 
578
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
 
579
   }
 
580
 
 
581
   free(stencilVals);
 
582
   free(depthVals);
 
583
 
 
584
   ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
 
585
   if (stencilRb != depthRb) {
 
586
      ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
 
587
   }
 
588
}
 
589
 
 
590
 
 
591
/**
 
592
 * Read combined depth/stencil values.
 
593
 * We'll have already done error checking to be sure the expected
 
594
 * depth and stencil buffers really exist.
 
595
 */
 
596
static void
 
597
read_depth_stencil_pixels(struct gl_context *ctx,
 
598
                          GLint x, GLint y,
 
599
                          GLsizei width, GLsizei height,
 
600
                          GLenum type, GLvoid *pixels,
 
601
                          const struct gl_pixelstore_attrib *packing )
 
602
{
 
603
   const GLboolean scaleOrBias
 
604
      = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
 
605
   const GLboolean stencilTransfer = ctx->Pixel.IndexShift
 
606
      || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
 
607
   GLubyte *dst;
 
608
   int dstStride;
 
609
 
 
610
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
 
611
                                           width, height,
 
612
                                           GL_DEPTH_STENCIL_EXT,
 
613
                                           type, 0, 0);
 
614
   dstStride = _mesa_image_row_stride(packing, width,
 
615
                                      GL_DEPTH_STENCIL_EXT, type);
 
616
 
 
617
   /* Fast 24/8 reads. */
 
618
   if (type == GL_UNSIGNED_INT_24_8 &&
 
619
       !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
 
620
      if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
 
621
                                         dst, dstStride))
 
622
         return;
 
623
 
 
624
      if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
 
625
                                                  (uint32_t *)dst, dstStride))
 
626
         return;
 
627
   }
 
628
 
 
629
   slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
 
630
                                           type, packing,
 
631
                                           dst, dstStride);
 
632
}
 
633
 
 
634
 
 
635
 
 
636
/**
 
637
 * Software fallback routine for ctx->Driver.ReadPixels().
 
638
 * By time we get here, all error checking will have been done.
 
639
 */
 
640
void
 
641
_mesa_readpixels(struct gl_context *ctx,
 
642
                 GLint x, GLint y, GLsizei width, GLsizei height,
 
643
                 GLenum format, GLenum type,
 
644
                 const struct gl_pixelstore_attrib *packing,
 
645
                 GLvoid *pixels)
 
646
{
 
647
   struct gl_pixelstore_attrib clippedPacking = *packing;
 
648
 
 
649
   if (ctx->NewState)
 
650
      _mesa_update_state(ctx);
 
651
 
 
652
   /* Do all needed clipping here, so that we can forget about it later */
 
653
   if (_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
 
654
 
 
655
      pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels);
 
656
 
 
657
      if (pixels) {
 
658
         switch (format) {
 
659
         case GL_STENCIL_INDEX:
 
660
            read_stencil_pixels(ctx, x, y, width, height, type, pixels,
 
661
                                &clippedPacking);
 
662
            break;
 
663
         case GL_DEPTH_COMPONENT:
 
664
            read_depth_pixels(ctx, x, y, width, height, type, pixels,
 
665
                              &clippedPacking);
 
666
            break;
 
667
         case GL_DEPTH_STENCIL_EXT:
 
668
            read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
 
669
                                      &clippedPacking);
 
670
            break;
 
671
         default:
 
672
            /* all other formats should be color formats */
 
673
            read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
 
674
                             &clippedPacking);
 
675
         }
 
676
 
 
677
         _mesa_unmap_pbo_dest(ctx, &clippedPacking);
 
678
      }
 
679
   }
 
680
}
 
681
 
 
682
 
 
683
void GLAPIENTRY
 
684
_mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
 
685
                      GLenum format, GLenum type, GLsizei bufSize,
 
686
                      GLvoid *pixels )
 
687
{
 
688
   GLenum err;
 
689
 
 
690
   GET_CURRENT_CONTEXT(ctx);
 
691
   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
692
 
 
693
   FLUSH_CURRENT(ctx, 0);
 
694
 
 
695
   if (MESA_VERBOSE & VERBOSE_API)
 
696
      _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
 
697
                  width, height,
 
698
                  _mesa_lookup_enum_by_nr(format),
 
699
                  _mesa_lookup_enum_by_nr(type),
 
700
                  pixels);
 
701
 
 
702
   if (width < 0 || height < 0) {
 
703
      _mesa_error( ctx, GL_INVALID_VALUE,
 
704
                   "glReadPixels(width=%d height=%d)", width, height );
 
705
      return;
 
706
   }
 
707
 
 
708
   /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
 
709
    * combinations of format and type that can be used.
 
710
    *
 
711
    * Technically, only two combinations are actually allowed:
 
712
    * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
 
713
    * preferred combination.  This code doesn't know what that preferred
 
714
    * combination is, and Mesa can handle anything valid.  Just work instead.
 
715
    */
 
716
   if (_mesa_is_gles(ctx) && ctx->Version < 30) {
 
717
      err = _mesa_es_error_check_format_and_type(format, type, 2);
 
718
      if (err == GL_NO_ERROR) {
 
719
         if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
 
720
            err = GL_INVALID_OPERATION;
 
721
         } else if (format == GL_DEPTH_COMPONENT
 
722
                    || format == GL_DEPTH_STENCIL) {
 
723
            err = GL_INVALID_ENUM;
 
724
         }
 
725
      }
 
726
 
 
727
      if (err != GL_NO_ERROR) {
 
728
         _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
 
729
                     _mesa_lookup_enum_by_nr(format),
 
730
                     _mesa_lookup_enum_by_nr(type));
 
731
         return;
 
732
      }
 
733
   }
 
734
 
 
735
   if (ctx->NewState)
 
736
      _mesa_update_state(ctx);
 
737
 
 
738
   err = _mesa_error_check_format_and_type(ctx, format, type);
 
739
   if (err != GL_NO_ERROR) {
 
740
      _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
 
741
                  _mesa_lookup_enum_by_nr(format),
 
742
                  _mesa_lookup_enum_by_nr(type));
 
743
      return;
 
744
   }
 
745
 
 
746
   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
 
747
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
 
748
                  "glReadPixels(incomplete framebuffer)" );
 
749
      return;
 
750
   }
 
751
 
 
752
   /* Check that the destination format and source buffer are both
 
753
    * integer-valued or both non-integer-valued.
 
754
    */
 
755
   if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
 
756
      const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
 
757
      const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
 
758
      const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
 
759
      if (dstInteger != srcInteger) {
 
760
         _mesa_error(ctx, GL_INVALID_OPERATION,
 
761
                     "glReadPixels(integer / non-integer format mismatch");
 
762
         return;
 
763
      }
 
764
   }
 
765
 
 
766
   if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
 
767
       ctx->ReadBuffer->Visual.samples > 0) {
 
768
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
 
769
      return;
 
770
   }
 
771
 
 
772
   if (!_mesa_source_buffer_exists(ctx, format)) {
 
773
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
 
774
      return;
 
775
   }
 
776
 
 
777
   if (width == 0 || height == 0)
 
778
      return; /* nothing to do */
 
779
 
 
780
   if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
 
781
                                  format, type, bufSize, pixels)) {
 
782
      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
 
783
         _mesa_error(ctx, GL_INVALID_OPERATION,
 
784
                     "glReadPixels(out of bounds PBO access)");
 
785
      } else {
 
786
         _mesa_error(ctx, GL_INVALID_OPERATION,
 
787
                     "glReadnPixelsARB(out of bounds access:"
 
788
                     " bufSize (%d) is too small)", bufSize);
 
789
      }
 
790
      return;
 
791
   }
 
792
 
 
793
   if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
 
794
       _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
 
795
      /* buffer is mapped - that's an error */
 
796
      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
 
797
      return;
 
798
   }
 
799
 
 
800
   ctx->Driver.ReadPixels(ctx, x, y, width, height,
 
801
                          format, type, &ctx->Pack, pixels);
 
802
}
 
803
 
 
804
void GLAPIENTRY
 
805
_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
 
806
                  GLenum format, GLenum type, GLvoid *pixels )
 
807
{
 
808
   _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
 
809
}