Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5563 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 1999-2007 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 | |||
26 | #include "main/glheader.h" |
||
27 | #include "main/bufferobj.h" |
||
28 | #include "main/colormac.h" |
||
29 | #include "main/condrender.h" |
||
30 | #include "main/context.h" |
||
31 | #include "main/format_pack.h" |
||
32 | #include "main/image.h" |
||
33 | #include "main/imports.h" |
||
34 | #include "main/macros.h" |
||
35 | #include "main/pack.h" |
||
36 | #include "main/pbo.h" |
||
37 | #include "main/pixeltransfer.h" |
||
38 | #include "main/state.h" |
||
39 | |||
40 | #include "s_context.h" |
||
41 | #include "s_span.h" |
||
42 | #include "s_stencil.h" |
||
43 | #include "s_zoom.h" |
||
44 | |||
45 | |||
46 | /** |
||
47 | * Handle a common case of drawing GL_RGB/GL_UNSIGNED_BYTE into a |
||
48 | * MESA_FORMAT_XRGB888 or MESA_FORMAT_ARGB888 renderbuffer. |
||
49 | */ |
||
50 | static void |
||
51 | fast_draw_rgb_ubyte_pixels(struct gl_context *ctx, |
||
52 | struct gl_renderbuffer *rb, |
||
53 | GLint x, GLint y, |
||
54 | GLsizei width, GLsizei height, |
||
55 | const struct gl_pixelstore_attrib *unpack, |
||
56 | const GLvoid *pixels) |
||
57 | { |
||
58 | const GLubyte *src = (const GLubyte *) |
||
59 | _mesa_image_address2d(unpack, pixels, width, |
||
60 | height, GL_RGB, GL_UNSIGNED_BYTE, 0, 0); |
||
61 | const GLint srcRowStride = _mesa_image_row_stride(unpack, width, |
||
62 | GL_RGB, GL_UNSIGNED_BYTE); |
||
63 | GLint i, j; |
||
64 | GLubyte *dst; |
||
65 | GLint dstRowStride; |
||
66 | |||
67 | ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, |
||
68 | GL_MAP_WRITE_BIT, &dst, &dstRowStride); |
||
69 | |||
70 | if (!dst) { |
||
71 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); |
||
72 | return; |
||
73 | } |
||
74 | |||
75 | if (ctx->Pixel.ZoomY == -1.0f) { |
||
76 | dst = dst + (height - 1) * dstRowStride; |
||
77 | dstRowStride = -dstRowStride; |
||
78 | } |
||
79 | |||
80 | for (i = 0; i < height; i++) { |
||
81 | GLuint *dst4 = (GLuint *) dst; |
||
82 | for (j = 0; j < width; j++) { |
||
83 | dst4[j] = PACK_COLOR_8888(0xff, src[j*3+0], src[j*3+1], src[j*3+2]); |
||
84 | } |
||
85 | dst += dstRowStride; |
||
86 | src += srcRowStride; |
||
87 | } |
||
88 | |||
89 | ctx->Driver.UnmapRenderbuffer(ctx, rb); |
||
90 | } |
||
91 | |||
92 | |||
93 | /** |
||
94 | * Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a |
||
95 | * MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer. |
||
96 | */ |
||
97 | static void |
||
98 | fast_draw_rgba_ubyte_pixels(struct gl_context *ctx, |
||
99 | struct gl_renderbuffer *rb, |
||
100 | GLint x, GLint y, |
||
101 | GLsizei width, GLsizei height, |
||
102 | const struct gl_pixelstore_attrib *unpack, |
||
103 | const GLvoid *pixels) |
||
104 | { |
||
105 | const GLubyte *src = (const GLubyte *) |
||
106 | _mesa_image_address2d(unpack, pixels, width, |
||
107 | height, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); |
||
108 | const GLint srcRowStride = |
||
109 | _mesa_image_row_stride(unpack, width, GL_RGBA, GL_UNSIGNED_BYTE); |
||
110 | GLint i, j; |
||
111 | GLubyte *dst; |
||
112 | GLint dstRowStride; |
||
113 | |||
114 | ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, |
||
115 | GL_MAP_WRITE_BIT, &dst, &dstRowStride); |
||
116 | |||
117 | if (!dst) { |
||
118 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); |
||
119 | return; |
||
120 | } |
||
121 | |||
122 | if (ctx->Pixel.ZoomY == -1.0f) { |
||
123 | dst = dst + (height - 1) * dstRowStride; |
||
124 | dstRowStride = -dstRowStride; |
||
125 | } |
||
126 | |||
127 | for (i = 0; i < height; i++) { |
||
128 | GLuint *dst4 = (GLuint *) dst; |
||
129 | for (j = 0; j < width; j++) { |
||
130 | dst4[j] = PACK_COLOR_8888(src[j*4+3], src[j*4+0], |
||
131 | src[j*4+1], src[j*4+2]); |
||
132 | } |
||
133 | dst += dstRowStride; |
||
134 | src += srcRowStride; |
||
135 | } |
||
136 | |||
137 | ctx->Driver.UnmapRenderbuffer(ctx, rb); |
||
138 | } |
||
139 | |||
140 | |||
141 | /** |
||
142 | * Handle a common case of drawing a format/type combination that |
||
143 | * exactly matches the renderbuffer format. |
||
144 | */ |
||
145 | static void |
||
146 | fast_draw_generic_pixels(struct gl_context *ctx, |
||
147 | struct gl_renderbuffer *rb, |
||
148 | GLint x, GLint y, |
||
149 | GLsizei width, GLsizei height, |
||
150 | GLenum format, GLenum type, |
||
151 | const struct gl_pixelstore_attrib *unpack, |
||
152 | const GLvoid *pixels) |
||
153 | { |
||
154 | const GLubyte *src = (const GLubyte *) |
||
155 | _mesa_image_address2d(unpack, pixels, width, |
||
156 | height, format, type, 0, 0); |
||
157 | const GLint srcRowStride = |
||
158 | _mesa_image_row_stride(unpack, width, format, type); |
||
159 | const GLint rowLength = width * _mesa_get_format_bytes(rb->Format); |
||
160 | GLint i; |
||
161 | GLubyte *dst; |
||
162 | GLint dstRowStride; |
||
163 | |||
164 | ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, |
||
165 | GL_MAP_WRITE_BIT, &dst, &dstRowStride); |
||
166 | |||
167 | if (!dst) { |
||
168 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); |
||
169 | return; |
||
170 | } |
||
171 | |||
172 | if (ctx->Pixel.ZoomY == -1.0f) { |
||
173 | dst = dst + (height - 1) * dstRowStride; |
||
174 | dstRowStride = -dstRowStride; |
||
175 | } |
||
176 | |||
177 | for (i = 0; i < height; i++) { |
||
178 | memcpy(dst, src, rowLength); |
||
179 | dst += dstRowStride; |
||
180 | src += srcRowStride; |
||
181 | } |
||
182 | |||
183 | ctx->Driver.UnmapRenderbuffer(ctx, rb); |
||
184 | } |
||
185 | |||
186 | |||
187 | /** |
||
188 | * Try to do a fast and simple RGB(a) glDrawPixels. |
||
189 | * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead |
||
190 | */ |
||
191 | static GLboolean |
||
192 | fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y, |
||
193 | GLsizei width, GLsizei height, |
||
194 | GLenum format, GLenum type, |
||
195 | const struct gl_pixelstore_attrib *userUnpack, |
||
196 | const GLvoid *pixels) |
||
197 | { |
||
198 | struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; |
||
199 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
200 | struct gl_pixelstore_attrib unpack; |
||
201 | |||
202 | if (!rb) |
||
203 | return GL_TRUE; /* no-op */ |
||
204 | |||
205 | if (ctx->DrawBuffer->_NumColorDrawBuffers > 1 || |
||
206 | (swrast->_RasterMask & ~CLIP_BIT) || |
||
207 | ctx->Texture._EnabledCoordUnits || |
||
208 | userUnpack->SwapBytes || |
||
209 | ctx->Pixel.ZoomX != 1.0f || |
||
210 | fabsf(ctx->Pixel.ZoomY) != 1.0f || |
||
211 | ctx->_ImageTransferState) { |
||
212 | /* can't handle any of those conditions */ |
||
213 | return GL_FALSE; |
||
214 | } |
||
215 | |||
216 | unpack = *userUnpack; |
||
217 | |||
218 | /* clipping */ |
||
219 | if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &unpack)) { |
||
220 | /* image was completely clipped: no-op, all done */ |
||
221 | return GL_TRUE; |
||
222 | } |
||
223 | |||
224 | if (format == GL_RGB && |
||
225 | type == GL_UNSIGNED_BYTE && |
||
226 | (rb->Format == MESA_FORMAT_XRGB8888 || |
||
227 | rb->Format == MESA_FORMAT_ARGB8888)) { |
||
228 | fast_draw_rgb_ubyte_pixels(ctx, rb, x, y, width, height, |
||
229 | &unpack, pixels); |
||
230 | return GL_TRUE; |
||
231 | } |
||
232 | |||
233 | if (format == GL_RGBA && |
||
234 | type == GL_UNSIGNED_BYTE && |
||
235 | (rb->Format == MESA_FORMAT_XRGB8888 || |
||
236 | rb->Format == MESA_FORMAT_ARGB8888)) { |
||
237 | fast_draw_rgba_ubyte_pixels(ctx, rb, x, y, width, height, |
||
238 | &unpack, pixels); |
||
239 | return GL_TRUE; |
||
240 | } |
||
241 | |||
242 | if (_mesa_format_matches_format_and_type(rb->Format, format, type, |
||
243 | ctx->Unpack.SwapBytes)) { |
||
244 | fast_draw_generic_pixels(ctx, rb, x, y, width, height, |
||
245 | format, type, &unpack, pixels); |
||
246 | return GL_TRUE; |
||
247 | } |
||
248 | |||
249 | /* can't handle this pixel format and/or data type */ |
||
250 | return GL_FALSE; |
||
251 | } |
||
252 | |||
253 | |||
254 | |||
255 | /* |
||
256 | * Draw stencil image. |
||
257 | */ |
||
258 | static void |
||
259 | draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y, |
||
260 | GLsizei width, GLsizei height, |
||
261 | GLenum type, |
||
262 | const struct gl_pixelstore_attrib *unpack, |
||
263 | const GLvoid *pixels ) |
||
264 | { |
||
265 | const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; |
||
266 | const GLenum destType = GL_UNSIGNED_BYTE; |
||
267 | GLint row; |
||
268 | GLubyte *values; |
||
269 | |||
270 | values = malloc(width * sizeof(GLubyte)); |
||
271 | if (!values) { |
||
272 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); |
||
273 | return; |
||
274 | } |
||
275 | |||
276 | for (row = 0; row < height; row++) { |
||
277 | const GLvoid *source = _mesa_image_address2d(unpack, pixels, |
||
278 | width, height, |
||
279 | GL_STENCIL_INDEX, type, |
||
280 | row, 0); |
||
281 | _mesa_unpack_stencil_span(ctx, width, destType, values, |
||
282 | type, source, unpack, |
||
283 | ctx->_ImageTransferState); |
||
284 | if (zoom) { |
||
285 | _swrast_write_zoomed_stencil_span(ctx, x, y, width, |
||
286 | x, y, values); |
||
287 | } |
||
288 | else { |
||
289 | _swrast_write_stencil_span(ctx, width, x, y, values); |
||
290 | } |
||
291 | |||
292 | y++; |
||
293 | } |
||
294 | |||
295 | free(values); |
||
296 | } |
||
297 | |||
298 | |||
299 | /* |
||
300 | * Draw depth image. |
||
301 | */ |
||
302 | static void |
||
303 | draw_depth_pixels( struct gl_context *ctx, GLint x, GLint y, |
||
304 | GLsizei width, GLsizei height, |
||
305 | GLenum type, |
||
306 | const struct gl_pixelstore_attrib *unpack, |
||
307 | const GLvoid *pixels ) |
||
308 | { |
||
309 | const GLboolean scaleOrBias |
||
310 | = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; |
||
311 | const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; |
||
312 | SWspan span; |
||
313 | |||
314 | INIT_SPAN(span, GL_BITMAP); |
||
315 | span.arrayMask = SPAN_Z; |
||
316 | _swrast_span_default_attribs(ctx, &span); |
||
317 | |||
318 | if (type == GL_UNSIGNED_SHORT |
||
319 | && ctx->DrawBuffer->Visual.depthBits == 16 |
||
320 | && !scaleOrBias |
||
321 | && !zoom |
||
322 | && width <= SWRAST_MAX_WIDTH |
||
323 | && !unpack->SwapBytes) { |
||
324 | /* Special case: directly write 16-bit depth values */ |
||
325 | GLint row; |
||
326 | for (row = 0; row < height; row++) { |
||
327 | const GLushort *zSrc = (const GLushort *) |
||
328 | _mesa_image_address2d(unpack, pixels, width, height, |
||
329 | GL_DEPTH_COMPONENT, type, row, 0); |
||
330 | GLint i; |
||
331 | for (i = 0; i < width; i++) |
||
332 | span.array->z[i] = zSrc[i]; |
||
333 | span.x = x; |
||
334 | span.y = y + row; |
||
335 | span.end = width; |
||
336 | _swrast_write_rgba_span(ctx, &span); |
||
337 | } |
||
338 | } |
||
339 | else if (type == GL_UNSIGNED_INT |
||
340 | && !scaleOrBias |
||
341 | && !zoom |
||
342 | && width <= SWRAST_MAX_WIDTH |
||
343 | && !unpack->SwapBytes) { |
||
344 | /* Special case: shift 32-bit values down to Visual.depthBits */ |
||
345 | const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits; |
||
346 | GLint row; |
||
347 | for (row = 0; row < height; row++) { |
||
348 | const GLuint *zSrc = (const GLuint *) |
||
349 | _mesa_image_address2d(unpack, pixels, width, height, |
||
350 | GL_DEPTH_COMPONENT, type, row, 0); |
||
351 | if (shift == 0) { |
||
352 | memcpy(span.array->z, zSrc, width * sizeof(GLuint)); |
||
353 | } |
||
354 | else { |
||
355 | GLint col; |
||
356 | for (col = 0; col < width; col++) |
||
357 | span.array->z[col] = zSrc[col] >> shift; |
||
358 | } |
||
359 | span.x = x; |
||
360 | span.y = y + row; |
||
361 | span.end = width; |
||
362 | _swrast_write_rgba_span(ctx, &span); |
||
363 | } |
||
364 | } |
||
365 | else { |
||
366 | /* General case */ |
||
367 | const GLuint depthMax = ctx->DrawBuffer->_DepthMax; |
||
368 | GLint skipPixels = 0; |
||
369 | |||
370 | /* in case width > SWRAST_MAX_WIDTH do the copy in chunks */ |
||
371 | while (skipPixels < width) { |
||
372 | const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH); |
||
373 | GLint row; |
||
374 | ASSERT(span.end <= SWRAST_MAX_WIDTH); |
||
375 | for (row = 0; row < height; row++) { |
||
376 | const GLvoid *zSrc = _mesa_image_address2d(unpack, |
||
377 | pixels, width, height, |
||
378 | GL_DEPTH_COMPONENT, type, |
||
379 | row, skipPixels); |
||
380 | |||
381 | /* Set these for each row since the _swrast_write_* function may |
||
382 | * change them while clipping. |
||
383 | */ |
||
384 | span.x = x + skipPixels; |
||
385 | span.y = y + row; |
||
386 | span.end = spanWidth; |
||
387 | |||
388 | _mesa_unpack_depth_span(ctx, spanWidth, |
||
389 | GL_UNSIGNED_INT, span.array->z, depthMax, |
||
390 | type, zSrc, unpack); |
||
391 | if (zoom) { |
||
392 | _swrast_write_zoomed_depth_span(ctx, x, y, &span); |
||
393 | } |
||
394 | else { |
||
395 | _swrast_write_rgba_span(ctx, &span); |
||
396 | } |
||
397 | } |
||
398 | skipPixels += spanWidth; |
||
399 | } |
||
400 | } |
||
401 | } |
||
402 | |||
403 | |||
404 | |||
405 | /** |
||
406 | * Draw RGBA image. |
||
407 | */ |
||
408 | static void |
||
409 | draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y, |
||
410 | GLsizei width, GLsizei height, |
||
411 | GLenum format, GLenum type, |
||
412 | const struct gl_pixelstore_attrib *unpack, |
||
413 | const GLvoid *pixels ) |
||
414 | { |
||
415 | const GLint imgX = x, imgY = y; |
||
416 | const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; |
||
417 | GLfloat *convImage = NULL; |
||
418 | GLbitfield transferOps = ctx->_ImageTransferState; |
||
419 | SWspan span; |
||
420 | |||
421 | /* Try an optimized glDrawPixels first */ |
||
422 | if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type, |
||
423 | unpack, pixels)) { |
||
424 | return; |
||
425 | } |
||
426 | |||
427 | swrast_render_start(ctx); |
||
428 | |||
429 | INIT_SPAN(span, GL_BITMAP); |
||
430 | _swrast_span_default_attribs(ctx, &span); |
||
431 | span.arrayMask = SPAN_RGBA; |
||
432 | span.arrayAttribs = VARYING_BIT_COL0; /* we're fill in COL0 attrib values */ |
||
433 | |||
434 | if (ctx->DrawBuffer->_NumColorDrawBuffers > 0) { |
||
435 | GLenum datatype = _mesa_get_format_datatype( |
||
436 | ctx->DrawBuffer->_ColorDrawBuffers[0]->Format); |
||
437 | if (datatype != GL_FLOAT && |
||
438 | ctx->Color.ClampFragmentColor != GL_FALSE) { |
||
439 | /* need to clamp colors before applying fragment ops */ |
||
440 | transferOps |= IMAGE_CLAMP_BIT; |
||
441 | } |
||
442 | } |
||
443 | |||
444 | /* |
||
445 | * General solution |
||
446 | */ |
||
447 | { |
||
448 | const GLbitfield interpMask = span.interpMask; |
||
449 | const GLbitfield arrayMask = span.arrayMask; |
||
450 | const GLint srcStride |
||
451 | = _mesa_image_row_stride(unpack, width, format, type); |
||
452 | GLint skipPixels = 0; |
||
453 | /* use span array for temp color storage */ |
||
454 | GLfloat *rgba = (GLfloat *) span.array->attribs[VARYING_SLOT_COL0]; |
||
455 | |||
456 | /* if the span is wider than SWRAST_MAX_WIDTH we have to do it in chunks */ |
||
457 | while (skipPixels < width) { |
||
458 | const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH); |
||
459 | const GLubyte *source |
||
460 | = (const GLubyte *) _mesa_image_address2d(unpack, pixels, |
||
461 | width, height, format, |
||
462 | type, 0, skipPixels); |
||
463 | GLint row; |
||
464 | |||
465 | for (row = 0; row < height; row++) { |
||
466 | /* get image row as float/RGBA */ |
||
467 | _mesa_unpack_color_span_float(ctx, spanWidth, GL_RGBA, rgba, |
||
468 | format, type, source, unpack, |
||
469 | transferOps); |
||
470 | /* Set these for each row since the _swrast_write_* functions |
||
471 | * may change them while clipping/rendering. |
||
472 | */ |
||
473 | span.array->ChanType = GL_FLOAT; |
||
474 | span.x = x + skipPixels; |
||
475 | span.y = y + row; |
||
476 | span.end = spanWidth; |
||
477 | span.arrayMask = arrayMask; |
||
478 | span.interpMask = interpMask; |
||
479 | if (zoom) { |
||
480 | _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba); |
||
481 | } |
||
482 | else { |
||
483 | _swrast_write_rgba_span(ctx, &span); |
||
484 | } |
||
485 | |||
486 | source += srcStride; |
||
487 | } /* for row */ |
||
488 | |||
489 | skipPixels += spanWidth; |
||
490 | } /* while skipPixels < width */ |
||
491 | |||
492 | /* XXX this is ugly/temporary, to undo above change */ |
||
493 | span.array->ChanType = CHAN_TYPE; |
||
494 | } |
||
495 | |||
496 | free(convImage); |
||
497 | |||
498 | swrast_render_finish(ctx); |
||
499 | } |
||
500 | |||
501 | |||
502 | /** |
||
503 | * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_S8_Z24 |
||
504 | * renderbuffer. No masking, zooming, scaling, etc. |
||
505 | */ |
||
506 | static void |
||
507 | fast_draw_depth_stencil(struct gl_context *ctx, GLint x, GLint y, |
||
508 | GLsizei width, GLsizei height, |
||
509 | const struct gl_pixelstore_attrib *unpack, |
||
510 | const GLvoid *pixels) |
||
511 | { |
||
512 | const GLenum format = GL_DEPTH_STENCIL_EXT; |
||
513 | const GLenum type = GL_UNSIGNED_INT_24_8; |
||
514 | struct gl_renderbuffer *rb = |
||
515 | ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; |
||
516 | struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); |
||
517 | GLubyte *src, *dst; |
||
518 | GLint srcRowStride, dstRowStride; |
||
519 | GLint i; |
||
520 | |||
521 | src = _mesa_image_address2d(unpack, pixels, width, height, |
||
522 | format, type, 0, 0); |
||
523 | srcRowStride = _mesa_image_row_stride(unpack, width, format, type); |
||
524 | |||
525 | dst = _swrast_pixel_address(rb, x, y); |
||
526 | dstRowStride = srb->RowStride; |
||
527 | |||
528 | for (i = 0; i < height; i++) { |
||
529 | _mesa_pack_uint_24_8_depth_stencil_row(rb->Format, width, |
||
530 | (const GLuint *) src, dst); |
||
531 | dst += dstRowStride; |
||
532 | src += srcRowStride; |
||
533 | } |
||
534 | } |
||
535 | |||
536 | |||
537 | |||
538 | /** |
||
539 | * This is a bit different from drawing GL_DEPTH_COMPONENT pixels. |
||
540 | * The only per-pixel operations that apply are depth scale/bias, |
||
541 | * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK, |
||
542 | * and pixel zoom. |
||
543 | * Also, only the depth buffer and stencil buffers are touched, not the |
||
544 | * color buffer(s). |
||
545 | */ |
||
546 | static void |
||
547 | draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, |
||
548 | GLsizei width, GLsizei height, GLenum type, |
||
549 | const struct gl_pixelstore_attrib *unpack, |
||
550 | const GLvoid *pixels) |
||
551 | { |
||
552 | const GLint imgX = x, imgY = y; |
||
553 | const GLboolean scaleOrBias |
||
554 | = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; |
||
555 | const GLuint stencilMask = ctx->Stencil.WriteMask[0]; |
||
556 | const GLenum stencilType = GL_UNSIGNED_BYTE; |
||
557 | const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; |
||
558 | struct gl_renderbuffer *depthRb, *stencilRb; |
||
559 | struct gl_pixelstore_attrib clippedUnpack = *unpack; |
||
560 | |||
561 | if (!zoom) { |
||
562 | if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, |
||
563 | &clippedUnpack)) { |
||
564 | /* totally clipped */ |
||
565 | return; |
||
566 | } |
||
567 | } |
||
568 | |||
569 | depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; |
||
570 | stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; |
||
571 | ASSERT(depthRb); |
||
572 | ASSERT(stencilRb); |
||
573 | |||
574 | if (depthRb == stencilRb && |
||
575 | (depthRb->Format == MESA_FORMAT_Z24_S8 || |
||
576 | depthRb->Format == MESA_FORMAT_S8_Z24) && |
||
577 | type == GL_UNSIGNED_INT_24_8 && |
||
578 | !scaleOrBias && |
||
579 | !zoom && |
||
580 | ctx->Depth.Mask && |
||
581 | (stencilMask & 0xff) == 0xff) { |
||
582 | fast_draw_depth_stencil(ctx, x, y, width, height, |
||
583 | &clippedUnpack, pixels); |
||
584 | } |
||
585 | else { |
||
586 | /* sub-optimal cases: |
||
587 | * Separate depth/stencil buffers, or pixel transfer ops required. |
||
588 | */ |
||
589 | /* XXX need to handle very wide images (skippixels) */ |
||
590 | GLuint *zValues; /* 32-bit Z values */ |
||
591 | GLint i; |
||
592 | |||
593 | zValues = malloc(width * sizeof(GLuint)); |
||
594 | if (!zValues) { |
||
595 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); |
||
596 | return; |
||
597 | } |
||
598 | |||
599 | for (i = 0; i < height; i++) { |
||
600 | const GLuint *depthStencilSrc = (const GLuint *) |
||
601 | _mesa_image_address2d(&clippedUnpack, pixels, width, height, |
||
602 | GL_DEPTH_STENCIL_EXT, type, i, 0); |
||
603 | |||
604 | if (ctx->Depth.Mask) { |
||
605 | _mesa_unpack_depth_span(ctx, width, |
||
606 | GL_UNSIGNED_INT, /* dest type */ |
||
607 | zValues, /* dest addr */ |
||
608 | 0xffffffff, /* depth max */ |
||
609 | type, /* src type */ |
||
610 | depthStencilSrc, /* src addr */ |
||
611 | &clippedUnpack); |
||
612 | if (zoom) { |
||
613 | _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x, |
||
614 | y + i, zValues); |
||
615 | } |
||
616 | else { |
||
617 | GLubyte *dst = _swrast_pixel_address(depthRb, x, y + i); |
||
618 | _mesa_pack_uint_z_row(depthRb->Format, width, zValues, dst); |
||
619 | } |
||
620 | } |
||
621 | |||
622 | if (stencilMask != 0x0) { |
||
623 | GLubyte *stencilValues = (GLubyte *) zValues; /* re-use buffer */ |
||
624 | /* get stencil values, with shift/offset/mapping */ |
||
625 | _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues, |
||
626 | type, depthStencilSrc, &clippedUnpack, |
||
627 | ctx->_ImageTransferState); |
||
628 | if (zoom) |
||
629 | _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width, |
||
630 | x, y + i, stencilValues); |
||
631 | else |
||
632 | _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues); |
||
633 | } |
||
634 | } |
||
635 | |||
636 | free(zValues); |
||
637 | } |
||
638 | } |
||
639 | |||
640 | |||
641 | /** |
||
642 | * Execute software-based glDrawPixels. |
||
643 | * By time we get here, all error checking will have been done. |
||
644 | */ |
||
645 | void |
||
646 | _swrast_DrawPixels( struct gl_context *ctx, |
||
647 | GLint x, GLint y, |
||
648 | GLsizei width, GLsizei height, |
||
649 | GLenum format, GLenum type, |
||
650 | const struct gl_pixelstore_attrib *unpack, |
||
651 | const GLvoid *pixels ) |
||
652 | { |
||
653 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
654 | GLboolean save_vp_override = ctx->VertexProgram._Overriden; |
||
655 | |||
656 | if (!_mesa_check_conditional_render(ctx)) |
||
657 | return; /* don't draw */ |
||
658 | |||
659 | /* We are creating fragments directly, without going through vertex |
||
660 | * programs. |
||
661 | * |
||
662 | * This override flag tells the fragment processing code that its input |
||
663 | * comes from a non-standard source, and it may therefore not rely on |
||
664 | * optimizations that assume e.g. constant color if there is no color |
||
665 | * vertex array. |
||
666 | */ |
||
667 | _mesa_set_vp_override(ctx, GL_TRUE); |
||
668 | |||
669 | if (ctx->NewState) |
||
670 | _mesa_update_state(ctx); |
||
671 | |||
672 | if (swrast->NewState) |
||
673 | _swrast_validate_derived( ctx ); |
||
674 | |||
675 | pixels = _mesa_map_pbo_source(ctx, unpack, pixels); |
||
676 | if (!pixels) { |
||
677 | _mesa_set_vp_override(ctx, save_vp_override); |
||
678 | return; |
||
679 | } |
||
680 | |||
681 | /* |
||
682 | * By time we get here, all error checking should have been done. |
||
683 | */ |
||
684 | switch (format) { |
||
685 | case GL_STENCIL_INDEX: |
||
686 | swrast_render_start(ctx); |
||
687 | draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels ); |
||
688 | swrast_render_finish(ctx); |
||
689 | break; |
||
690 | case GL_DEPTH_COMPONENT: |
||
691 | swrast_render_start(ctx); |
||
692 | draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels ); |
||
693 | swrast_render_finish(ctx); |
||
694 | break; |
||
695 | case GL_DEPTH_STENCIL_EXT: |
||
696 | swrast_render_start(ctx); |
||
697 | draw_depth_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels); |
||
698 | swrast_render_finish(ctx); |
||
699 | break; |
||
700 | default: |
||
701 | /* all other formats should be color formats */ |
||
702 | draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels); |
||
703 | } |
||
704 | |||
705 | _mesa_set_vp_override(ctx, save_vp_override); |
||
706 | |||
707 | _mesa_unmap_pbo_source(ctx, unpack); |
||
708 | }>>>>>>=>>>>=>>>=>>>>>>> |