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