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
);