swrast: Directly map the stencil buffer in read_stencil_pixels.
[mesa.git] / src / mesa / swrast / s_readpix.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.0.3
4 *
5 * Copyright (C) 1999-2007 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
26 #include "main/glheader.h"
27 #include "main/colormac.h"
28 #include "main/feedback.h"
29 #include "main/formats.h"
30 #include "main/format_unpack.h"
31 #include "main/image.h"
32 #include "main/imports.h"
33 #include "main/macros.h"
34 #include "main/pack.h"
35 #include "main/pbo.h"
36 #include "main/state.h"
37
38 #include "s_context.h"
39 #include "s_depth.h"
40 #include "s_span.h"
41 #include "s_stencil.h"
42
43 /**
44 * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the
45 * mapping.
46 */
47 static GLboolean
48 fast_read_depth_pixels( struct gl_context *ctx,
49 GLint x, GLint y,
50 GLsizei width, GLsizei height,
51 GLenum type, GLvoid *pixels,
52 const struct gl_pixelstore_attrib *packing )
53 {
54 struct gl_framebuffer *fb = ctx->ReadBuffer;
55 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
56 GLubyte *map, *dst;
57 int stride, dstStride, j;
58
59 if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0)
60 return GL_FALSE;
61
62 if (packing->SwapBytes)
63 return GL_FALSE;
64
65 if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_INT)
66 return GL_FALSE;
67
68 if (!((type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16) ||
69 type == GL_UNSIGNED_INT))
70 return GL_FALSE;
71
72 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
73 &map, &stride);
74
75 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
76 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
77 GL_DEPTH_COMPONENT, type, 0, 0);
78
79 for (j = 0; j < height; j++) {
80 if (type == GL_UNSIGNED_INT) {
81 _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
82 } else {
83 ASSERT(type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16);
84 memcpy(dst, map, width * 2);
85 }
86
87 map += stride;
88 dst += dstStride;
89 }
90 ctx->Driver.UnmapRenderbuffer(ctx, rb);
91
92 return GL_TRUE;
93 }
94
95 /**
96 * Read pixels for format=GL_DEPTH_COMPONENT.
97 */
98 static void
99 read_depth_pixels( struct gl_context *ctx,
100 GLint x, GLint y,
101 GLsizei width, GLsizei height,
102 GLenum type, GLvoid *pixels,
103 const struct gl_pixelstore_attrib *packing )
104 {
105 struct gl_framebuffer *fb = ctx->ReadBuffer;
106 struct gl_renderbuffer *rb = fb->_DepthBuffer;
107 GLint j;
108
109 if (!rb)
110 return;
111
112 /* clipping should have been done already */
113 ASSERT(x >= 0);
114 ASSERT(y >= 0);
115 ASSERT(x + width <= (GLint) rb->Width);
116 ASSERT(y + height <= (GLint) rb->Height);
117 /* width should never be > MAX_WIDTH since we did clipping earlier */
118 ASSERT(width <= MAX_WIDTH);
119
120 if (fast_read_depth_pixels(ctx, x, y, width, height, type, pixels, packing))
121 return;
122
123 /* General case (slower) */
124 for (j = 0; j < height; j++, y++) {
125 GLfloat depthValues[MAX_WIDTH];
126 GLvoid *dest = _mesa_image_address2d(packing, pixels, width, height,
127 GL_DEPTH_COMPONENT, type, j, 0);
128 _swrast_read_depth_span_float(ctx, rb, width, x, y, depthValues);
129 _mesa_pack_depth_span(ctx, width, dest, type, depthValues, packing);
130 }
131 }
132
133
134 /**
135 * Read pixels for format=GL_STENCIL_INDEX.
136 */
137 static void
138 read_stencil_pixels( struct gl_context *ctx,
139 GLint x, GLint y,
140 GLsizei width, GLsizei height,
141 GLenum type, GLvoid *pixels,
142 const struct gl_pixelstore_attrib *packing )
143 {
144 struct gl_framebuffer *fb = ctx->ReadBuffer;
145 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
146 GLint j;
147 GLubyte *map;
148 GLint stride;
149
150 if (!rb)
151 return;
152
153 /* width should never be > MAX_WIDTH since we did clipping earlier */
154 ASSERT(width <= MAX_WIDTH);
155
156 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
157 &map, &stride);
158
159 /* process image row by row */
160 for (j = 0; j < height; j++) {
161 GLvoid *dest;
162 GLstencil stencil[MAX_WIDTH];
163
164 _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
165 dest = _mesa_image_address2d(packing, pixels, width, height,
166 GL_STENCIL_INDEX, type, j, 0);
167
168 _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
169
170 map += stride;
171 }
172
173 ctx->Driver.UnmapRenderbuffer(ctx, rb);
174 }
175
176
177
178 /**
179 * Optimized glReadPixels for particular pixel formats when pixel
180 * scaling, biasing, mapping, etc. are disabled.
181 * \return GL_TRUE if success, GL_FALSE if unable to do the readpixels
182 */
183 static GLboolean
184 fast_read_rgba_pixels( struct gl_context *ctx,
185 GLint x, GLint y,
186 GLsizei width, GLsizei height,
187 GLenum format, GLenum type,
188 GLvoid *pixels,
189 const struct gl_pixelstore_attrib *packing,
190 GLbitfield transferOps)
191 {
192 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
193
194 if (!rb)
195 return GL_FALSE;
196
197 ASSERT(rb->_BaseFormat == GL_RGBA ||
198 rb->_BaseFormat == GL_RGB ||
199 rb->_BaseFormat == GL_RG ||
200 rb->_BaseFormat == GL_RED ||
201 rb->_BaseFormat == GL_LUMINANCE ||
202 rb->_BaseFormat == GL_INTENSITY ||
203 rb->_BaseFormat == GL_LUMINANCE_ALPHA ||
204 rb->_BaseFormat == GL_ALPHA);
205
206 /* clipping should have already been done */
207 ASSERT(x + width <= (GLint) rb->Width);
208 ASSERT(y + height <= (GLint) rb->Height);
209
210 /* check for things we can't handle here */
211 if (transferOps ||
212 packing->SwapBytes ||
213 packing->LsbFirst) {
214 return GL_FALSE;
215 }
216
217 if (format == GL_RGBA && rb->DataType == type) {
218 const GLint dstStride = _mesa_image_row_stride(packing, width,
219 format, type);
220 GLubyte *dest
221 = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
222 format, type, 0, 0);
223 GLint row;
224 ASSERT(rb->GetRow);
225 for (row = 0; row < height; row++) {
226 rb->GetRow(ctx, rb, width, x, y + row, dest);
227 dest += dstStride;
228 }
229 return GL_TRUE;
230 }
231
232 if (format == GL_RGB &&
233 rb->DataType == GL_UNSIGNED_BYTE &&
234 type == GL_UNSIGNED_BYTE) {
235 const GLint dstStride = _mesa_image_row_stride(packing, width,
236 format, type);
237 GLubyte *dest
238 = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
239 format, type, 0, 0);
240 GLint row;
241 ASSERT(rb->GetRow);
242 for (row = 0; row < height; row++) {
243 GLubyte tempRow[MAX_WIDTH][4];
244 GLint col;
245 rb->GetRow(ctx, rb, width, x, y + row, tempRow);
246 /* convert RGBA to RGB */
247 for (col = 0; col < width; col++) {
248 dest[col * 3 + 0] = tempRow[col][0];
249 dest[col * 3 + 1] = tempRow[col][1];
250 dest[col * 3 + 2] = tempRow[col][2];
251 }
252 dest += dstStride;
253 }
254 return GL_TRUE;
255 }
256
257 /* not handled */
258 return GL_FALSE;
259 }
260
261
262 /**
263 * When we're using a low-precision color buffer (like 16-bit 5/6/5)
264 * we have to adjust our color values a bit to pass conformance.
265 * The problem is when a 5 or 6-bit color value is converted to an 8-bit
266 * value and then a floating point value, the floating point values don't
267 * increment uniformly as the 5 or 6-bit value is incremented.
268 *
269 * This function adjusts floating point values to compensate.
270 */
271 static void
272 adjust_colors(const struct gl_framebuffer *fb, GLuint n, GLfloat rgba[][4])
273 {
274 const GLuint rShift = 8 - fb->Visual.redBits;
275 const GLuint gShift = 8 - fb->Visual.greenBits;
276 const GLuint bShift = 8 - fb->Visual.blueBits;
277 GLfloat rScale = 1.0F / (GLfloat) ((1 << fb->Visual.redBits ) - 1);
278 GLfloat gScale = 1.0F / (GLfloat) ((1 << fb->Visual.greenBits) - 1);
279 GLfloat bScale = 1.0F / (GLfloat) ((1 << fb->Visual.blueBits ) - 1);
280 GLuint i;
281
282 if (fb->Visual.redBits == 0)
283 rScale = 0;
284 if (fb->Visual.greenBits == 0)
285 gScale = 0;
286 if (fb->Visual.blueBits == 0)
287 bScale = 0;
288
289 for (i = 0; i < n; i++) {
290 GLint r, g, b;
291 /* convert float back to ubyte */
292 CLAMPED_FLOAT_TO_UBYTE(r, rgba[i][RCOMP]);
293 CLAMPED_FLOAT_TO_UBYTE(g, rgba[i][GCOMP]);
294 CLAMPED_FLOAT_TO_UBYTE(b, rgba[i][BCOMP]);
295 /* using only the N most significant bits of the ubyte value, convert to
296 * float in [0,1].
297 */
298 rgba[i][RCOMP] = (GLfloat) (r >> rShift) * rScale;
299 rgba[i][GCOMP] = (GLfloat) (g >> gShift) * gScale;
300 rgba[i][BCOMP] = (GLfloat) (b >> bShift) * bScale;
301 }
302 }
303
304
305
306 /*
307 * Read R, G, B, A, RGB, L, or LA pixels.
308 */
309 static void
310 read_rgba_pixels( struct gl_context *ctx,
311 GLint x, GLint y,
312 GLsizei width, GLsizei height,
313 GLenum format, GLenum type, GLvoid *pixels,
314 const struct gl_pixelstore_attrib *packing )
315 {
316 SWcontext *swrast = SWRAST_CONTEXT(ctx);
317 GLbitfield transferOps = ctx->_ImageTransferState;
318 struct gl_framebuffer *fb = ctx->ReadBuffer;
319 struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
320
321 if (!rb)
322 return;
323
324 if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) &&
325 !_mesa_is_integer_format(format)) {
326 transferOps |= IMAGE_CLAMP_BIT;
327 }
328
329 /* Try the optimized path first. */
330 if (fast_read_rgba_pixels(ctx, x, y, width, height,
331 format, type, pixels, packing, transferOps)) {
332 return; /* done! */
333 }
334
335 /* width should never be > MAX_WIDTH since we did clipping earlier */
336 ASSERT(width <= MAX_WIDTH);
337
338 {
339 const GLint dstStride
340 = _mesa_image_row_stride(packing, width, format, type);
341 GLfloat (*rgba)[4] = swrast->SpanArrays->attribs[FRAG_ATTRIB_COL0];
342 GLint row;
343 GLubyte *dst
344 = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
345 format, type, 0, 0);
346
347 for (row = 0; row < height; row++, y++) {
348
349 /* Get float rgba pixels */
350 _swrast_read_rgba_span(ctx, rb, width, x, y, GL_FLOAT, rgba);
351
352 /* apply fudge factor for shallow color buffers */
353 if ((fb->Visual.redBits < 8 && fb->Visual.redBits != 0) ||
354 (fb->Visual.greenBits < 8 && fb->Visual.greenBits != 0) ||
355 (fb->Visual.blueBits < 8 && fb->Visual.blueBits != 0)) {
356 adjust_colors(fb, width, rgba);
357 }
358
359 /* pack the row of RGBA pixels into user's buffer */
360 _mesa_pack_rgba_span_float(ctx, width, rgba, format, type, dst,
361 packing, transferOps);
362
363 dst += dstStride;
364 }
365 }
366 }
367
368
369 /**
370 * Read combined depth/stencil values.
371 * We'll have already done error checking to be sure the expected
372 * depth and stencil buffers really exist.
373 */
374 static void
375 read_depth_stencil_pixels(struct gl_context *ctx,
376 GLint x, GLint y,
377 GLsizei width, GLsizei height,
378 GLenum type, GLvoid *pixels,
379 const struct gl_pixelstore_attrib *packing )
380 {
381 const GLboolean scaleOrBias
382 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
383 const GLboolean stencilTransfer = ctx->Pixel.IndexShift
384 || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
385 struct gl_renderbuffer *depthRb, *stencilRb;
386
387 depthRb = ctx->ReadBuffer->_DepthBuffer;
388 stencilRb = ctx->ReadBuffer->_StencilBuffer;
389
390 if (!depthRb || !stencilRb)
391 return;
392
393 depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
394 stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
395
396 if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
397 depthRb->Format == MESA_FORMAT_Z24_S8 &&
398 type == GL_UNSIGNED_INT_24_8 &&
399 depthRb == stencilRb &&
400 depthRb->GetRow && /* May be null if depthRb is a wrapper around
401 * separate depth and stencil buffers. */
402 !scaleOrBias &&
403 !stencilTransfer) {
404 /* This is the ideal case.
405 * Reading GL_DEPTH_STENCIL pixels from combined depth/stencil buffer.
406 * Plus, no pixel transfer ops to worry about!
407 */
408 GLint i;
409 GLint dstStride = _mesa_image_row_stride(packing, width,
410 GL_DEPTH_STENCIL_EXT, type);
411 GLubyte *dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
412 width, height,
413 GL_DEPTH_STENCIL_EXT,
414 type, 0, 0);
415 for (i = 0; i < height; i++) {
416 depthRb->GetRow(ctx, depthRb, width, x, y + i, dst);
417 dst += dstStride;
418 }
419 }
420 else {
421 /* Reading GL_DEPTH_STENCIL pixels from separate depth/stencil buffers,
422 * or we need pixel transfer.
423 */
424 GLint i;
425 depthRb = ctx->ReadBuffer->_DepthBuffer;
426 stencilRb = ctx->ReadBuffer->_StencilBuffer;
427
428 for (i = 0; i < height; i++) {
429 GLstencil stencilVals[MAX_WIDTH];
430
431 GLuint *depthStencilDst = (GLuint *)
432 _mesa_image_address2d(packing, pixels, width, height,
433 GL_DEPTH_STENCIL_EXT, type, i, 0);
434
435 _swrast_read_stencil_span(ctx, stencilRb, width,
436 x, y + i, stencilVals);
437
438 if (!scaleOrBias && !stencilTransfer
439 && ctx->ReadBuffer->Visual.depthBits == 24) {
440 /* ideal case */
441 GLuint zVals[MAX_WIDTH]; /* 24-bit values! */
442 GLint j;
443 ASSERT(depthRb->DataType == GL_UNSIGNED_INT);
444 /* note, we've already been clipped */
445 depthRb->GetRow(ctx, depthRb, width, x, y + i, zVals);
446 for (j = 0; j < width; j++) {
447 depthStencilDst[j] = (zVals[j] << 8) | (stencilVals[j] & 0xff);
448 }
449 }
450 else {
451 /* general case */
452 GLfloat depthVals[MAX_WIDTH];
453 _swrast_read_depth_span_float(ctx, depthRb, width, x, y + i,
454 depthVals);
455 _mesa_pack_depth_stencil_span(ctx, width, type, depthStencilDst,
456 depthVals, stencilVals, packing);
457 }
458 }
459 }
460 }
461
462
463
464 /**
465 * Software fallback routine for ctx->Driver.ReadPixels().
466 * By time we get here, all error checking will have been done.
467 */
468 void
469 _swrast_ReadPixels( struct gl_context *ctx,
470 GLint x, GLint y, GLsizei width, GLsizei height,
471 GLenum format, GLenum type,
472 const struct gl_pixelstore_attrib *packing,
473 GLvoid *pixels )
474 {
475 SWcontext *swrast = SWRAST_CONTEXT(ctx);
476 struct gl_pixelstore_attrib clippedPacking = *packing;
477
478 if (ctx->NewState)
479 _mesa_update_state(ctx);
480
481 /* Need to do swrast_render_start() before clipping or anything else
482 * since this is where a driver may grab the hw lock and get an updated
483 * window size.
484 */
485 swrast_render_start(ctx);
486
487 if (swrast->NewState)
488 _swrast_validate_derived( ctx );
489
490 /* Do all needed clipping here, so that we can forget about it later */
491 if (_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
492
493 pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels);
494
495 if (pixels) {
496 switch (format) {
497 case GL_STENCIL_INDEX:
498 read_stencil_pixels(ctx, x, y, width, height, type, pixels,
499 &clippedPacking);
500 break;
501 case GL_DEPTH_COMPONENT:
502 read_depth_pixels(ctx, x, y, width, height, type, pixels,
503 &clippedPacking);
504 break;
505 case GL_DEPTH_STENCIL_EXT:
506 read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
507 &clippedPacking);
508 break;
509 default:
510 /* all other formats should be color formats */
511 read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
512 &clippedPacking);
513 }
514
515 _mesa_unmap_pbo_dest(ctx, &clippedPacking);
516 }
517 }
518
519 swrast_render_finish(ctx);
520 }