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