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