2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
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"
37 #include "main/pixeltransfer.h"
38 #include "main/state.h"
40 #include "s_context.h"
42 #include "s_stencil.h"
47 * Handle a common case of drawing GL_RGB/GL_UNSIGNED_BYTE into a
48 * MESA_FORMAT_XRGB888 or MESA_FORMAT_ARGB888 renderbuffer.
51 fast_draw_rgb_ubyte_pixels(struct gl_context *ctx,
52 struct gl_renderbuffer *rb,
54 GLsizei width, GLsizei height,
55 const struct gl_pixelstore_attrib *unpack,
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);
67 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
68 GL_MAP_WRITE_BIT, &dst, &dstRowStride);
71 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
75 if (ctx->Pixel.ZoomY == -1.0f) {
76 dst = dst + (height - 1) * dstRowStride;
77 dstRowStride = -dstRowStride;
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]);
89 ctx->Driver.UnmapRenderbuffer(ctx, rb);
94 * Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a
95 * MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer.
98 fast_draw_rgba_ubyte_pixels(struct gl_context *ctx,
99 struct gl_renderbuffer *rb,
101 GLsizei width, GLsizei height,
102 const struct gl_pixelstore_attrib *unpack,
103 const GLvoid *pixels)
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);
114 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
115 GL_MAP_WRITE_BIT, &dst, &dstRowStride);
118 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
122 if (ctx->Pixel.ZoomY == -1.0f) {
123 dst = dst + (height - 1) * dstRowStride;
124 dstRowStride = -dstRowStride;
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]);
137 ctx->Driver.UnmapRenderbuffer(ctx, rb);
142 * Handle a common case of drawing a format/type combination that
143 * exactly matches the renderbuffer format.
146 fast_draw_generic_pixels(struct gl_context *ctx,
147 struct gl_renderbuffer *rb,
149 GLsizei width, GLsizei height,
150 GLenum format, GLenum type,
151 const struct gl_pixelstore_attrib *unpack,
152 const GLvoid *pixels)
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);
164 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
165 GL_MAP_WRITE_BIT, &dst, &dstRowStride);
168 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
172 if (ctx->Pixel.ZoomY == -1.0f) {
173 dst = dst + (height - 1) * dstRowStride;
174 dstRowStride = -dstRowStride;
177 for (i = 0; i < height; i++) {
178 memcpy(dst, src, rowLength);
183 ctx->Driver.UnmapRenderbuffer(ctx, rb);
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
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)
198 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
199 SWcontext *swrast = SWRAST_CONTEXT(ctx);
200 struct gl_pixelstore_attrib unpack;
203 return GL_TRUE; /* no-op */
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 */
216 unpack = *userUnpack;
219 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &unpack)) {
220 /* image was completely clipped: no-op, all done */
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,
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,
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);
249 /* can't handle this pixel format and/or data type */
256 * Draw stencil image.
259 draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y,
260 GLsizei width, GLsizei height,
262 const struct gl_pixelstore_attrib *unpack,
263 const GLvoid *pixels )
265 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
266 const GLenum destType = GL_UNSIGNED_BYTE;
270 values = (GLubyte *) malloc(width * sizeof(GLubyte));
272 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
276 for (row = 0; row < height; row++) {
277 const GLvoid *source = _mesa_image_address2d(unpack, pixels,
279 GL_STENCIL_INDEX, type,
281 _mesa_unpack_stencil_span(ctx, width, destType, values,
282 type, source, unpack,
283 ctx->_ImageTransferState);
285 _swrast_write_zoomed_stencil_span(ctx, x, y, width,
289 _swrast_write_stencil_span(ctx, width, x, y, values);
303 draw_depth_pixels( struct gl_context *ctx, GLint x, GLint y,
304 GLsizei width, GLsizei height,
306 const struct gl_pixelstore_attrib *unpack,
307 const GLvoid *pixels )
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;
314 INIT_SPAN(span, GL_BITMAP);
315 span.arrayMask = SPAN_Z;
316 _swrast_span_default_attribs(ctx, &span);
318 if (type == GL_UNSIGNED_SHORT
319 && ctx->DrawBuffer->Visual.depthBits == 16
322 && width <= SWRAST_MAX_WIDTH
323 && !unpack->SwapBytes) {
324 /* Special case: directly write 16-bit depth values */
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);
331 for (i = 0; i < width; i++)
332 span.array->z[i] = zSrc[i];
336 _swrast_write_rgba_span(ctx, &span);
339 else if (type == GL_UNSIGNED_INT
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;
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);
352 memcpy(span.array->z, zSrc, width * sizeof(GLuint));
356 for (col = 0; col < width; col++)
357 span.array->z[col] = zSrc[col] >> shift;
362 _swrast_write_rgba_span(ctx, &span);
367 const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
368 GLint skipPixels = 0;
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);
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,
381 /* Set these for each row since the _swrast_write_* function may
382 * change them while clipping.
384 span.x = x + skipPixels;
386 span.end = spanWidth;
388 _mesa_unpack_depth_span(ctx, spanWidth,
389 GL_UNSIGNED_INT, span.array->z, depthMax,
392 _swrast_write_zoomed_depth_span(ctx, x, y, &span);
395 _swrast_write_rgba_span(ctx, &span);
398 skipPixels += spanWidth;
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 )
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;
421 /* Try an optimized glDrawPixels first */
422 if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type,
427 swrast_render_start(ctx);
429 INIT_SPAN(span, GL_BITMAP);
430 _swrast_span_default_attribs(ctx, &span);
431 span.arrayMask = SPAN_RGBA;
432 span.arrayAttribs = FRAG_BIT_COL0; /* we're fill in COL0 attrib values */
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;
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[FRAG_ATTRIB_COL0];
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);
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,
470 /* Set these for each row since the _swrast_write_* functions
471 * may change them while clipping/rendering.
473 span.array->ChanType = GL_FLOAT;
474 span.x = x + skipPixels;
476 span.end = spanWidth;
477 span.arrayMask = arrayMask;
478 span.interpMask = interpMask;
480 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
483 _swrast_write_rgba_span(ctx, &span);
489 skipPixels += spanWidth;
490 } /* while skipPixels < width */
492 /* XXX this is ugly/temporary, to undo above change */
493 span.array->ChanType = CHAN_TYPE;
500 swrast_render_finish(ctx);
505 * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_S8_Z24
506 * renderbuffer. No masking, zooming, scaling, etc.
509 fast_draw_depth_stencil(struct gl_context *ctx, GLint x, GLint y,
510 GLsizei width, GLsizei height,
511 const struct gl_pixelstore_attrib *unpack,
512 const GLvoid *pixels)
514 const GLenum format = GL_DEPTH_STENCIL_EXT;
515 const GLenum type = GL_UNSIGNED_INT_24_8;
516 struct gl_renderbuffer *rb =
517 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
518 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
520 GLint srcRowStride, dstRowStride;
523 src = _mesa_image_address2d(unpack, pixels, width, height,
525 srcRowStride = _mesa_image_row_stride(unpack, width, format, type);
527 dst = _swrast_pixel_address(rb, x, y);
528 dstRowStride = srb->RowStride;
530 for (i = 0; i < height; i++) {
531 _mesa_pack_uint_24_8_depth_stencil_row(rb->Format, width,
532 (const GLuint *) src, dst);
541 * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
542 * The only per-pixel operations that apply are depth scale/bias,
543 * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
545 * Also, only the depth buffer and stencil buffers are touched, not the
549 draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
550 GLsizei width, GLsizei height, GLenum type,
551 const struct gl_pixelstore_attrib *unpack,
552 const GLvoid *pixels)
554 const GLint imgX = x, imgY = y;
555 const GLboolean scaleOrBias
556 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
557 const GLuint stencilMask = ctx->Stencil.WriteMask[0];
558 const GLenum stencilType = GL_UNSIGNED_BYTE;
559 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
560 struct gl_renderbuffer *depthRb, *stencilRb;
561 struct gl_pixelstore_attrib clippedUnpack = *unpack;
564 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
566 /* totally clipped */
571 depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
572 stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
576 if (depthRb == stencilRb &&
577 (depthRb->Format == MESA_FORMAT_Z24_S8 ||
578 depthRb->Format == MESA_FORMAT_S8_Z24) &&
579 type == GL_UNSIGNED_INT_24_8 &&
583 (stencilMask & 0xff) == 0xff) {
584 fast_draw_depth_stencil(ctx, x, y, width, height,
585 &clippedUnpack, pixels);
588 /* sub-optimal cases:
589 * Separate depth/stencil buffers, or pixel transfer ops required.
591 /* XXX need to handle very wide images (skippixels) */
592 GLuint *zValues; /* 32-bit Z values */
595 zValues = (GLuint *) malloc(width * sizeof(GLuint));
597 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
601 for (i = 0; i < height; i++) {
602 const GLuint *depthStencilSrc = (const GLuint *)
603 _mesa_image_address2d(&clippedUnpack, pixels, width, height,
604 GL_DEPTH_STENCIL_EXT, type, i, 0);
606 if (ctx->Depth.Mask) {
607 _mesa_unpack_depth_span(ctx, width,
608 GL_UNSIGNED_INT, /* dest type */
609 zValues, /* dest addr */
610 0xffffffff, /* depth max */
612 depthStencilSrc, /* src addr */
615 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
619 GLubyte *dst = _swrast_pixel_address(depthRb, x, y + i);
620 _mesa_pack_uint_z_row(depthRb->Format, width, zValues, dst);
624 if (stencilMask != 0x0) {
625 GLubyte *stencilValues = (GLubyte *) zValues; /* re-use buffer */
626 /* get stencil values, with shift/offset/mapping */
627 _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues,
628 type, depthStencilSrc, &clippedUnpack,
629 ctx->_ImageTransferState);
631 _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width,
632 x, y + i, stencilValues);
634 _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues);
644 * Execute software-based glDrawPixels.
645 * By time we get here, all error checking will have been done.
648 _swrast_DrawPixels( struct gl_context *ctx,
650 GLsizei width, GLsizei height,
651 GLenum format, GLenum type,
652 const struct gl_pixelstore_attrib *unpack,
653 const GLvoid *pixels )
655 SWcontext *swrast = SWRAST_CONTEXT(ctx);
656 GLboolean save_vp_override = ctx->VertexProgram._Overriden;
658 if (!_mesa_check_conditional_render(ctx))
659 return; /* don't draw */
661 /* We are creating fragments directly, without going through vertex
664 * This override flag tells the fragment processing code that its input
665 * comes from a non-standard source, and it may therefore not rely on
666 * optimizations that assume e.g. constant color if there is no color
669 _mesa_set_vp_override(ctx, GL_TRUE);
672 _mesa_update_state(ctx);
674 if (swrast->NewState)
675 _swrast_validate_derived( ctx );
677 pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
679 _mesa_set_vp_override(ctx, save_vp_override);
684 * By time we get here, all error checking should have been done.
687 case GL_STENCIL_INDEX:
688 swrast_render_start(ctx);
689 draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
690 swrast_render_finish(ctx);
692 case GL_DEPTH_COMPONENT:
693 swrast_render_start(ctx);
694 draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
695 swrast_render_finish(ctx);
697 case GL_DEPTH_STENCIL_EXT:
698 swrast_render_start(ctx);
699 draw_depth_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
700 swrast_render_finish(ctx);
703 /* all other formats should be color formats */
704 draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
707 _mesa_set_vp_override(ctx, save_vp_override);
709 _mesa_unmap_pbo_source(ctx, unpack);