1 /* $Id: s_drawpix.c,v 1.11 2001/03/03 20:33:30 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 #include "s_context.h"
39 #include "s_drawpix.h"
40 #include "s_pixeltex.h"
42 #include "s_stencil.h"
43 #include "s_texture.h"
49 * Given the dest position, size and skipPixels and skipRows values
50 * for a glDrawPixels command, perform clipping of the image bounds
51 * so the result lies withing the context's buffer bounds.
52 * Return: GL_TRUE if image is ready for drawing
53 * GL_FALSE if image was completely clipped away (draw nothing)
56 _mesa_clip_pixelrect(const GLcontext
*ctx
,
57 GLint
*destX
, GLint
*destY
,
58 GLsizei
*width
, GLsizei
*height
,
59 GLint
*skipPixels
, GLint
*skipRows
)
61 const GLframebuffer
*buffer
= ctx
->DrawBuffer
;
64 if (*destX
< buffer
->_Xmin
) {
65 *skipPixels
+= (buffer
->_Xmin
- *destX
);
66 *width
-= (buffer
->_Xmin
- *destX
);
67 *destX
= buffer
->_Xmin
;
70 if (*destX
+ *width
> buffer
->_Xmax
)
71 *width
-= (*destX
+ *width
- buffer
->_Xmax
);
77 if (*destY
< buffer
->_Ymin
) {
78 *skipRows
+= (buffer
->_Ymin
- *destY
);
79 *height
-= (buffer
->_Ymin
- *destY
);
80 *destY
= buffer
->_Ymin
;
83 if (*destY
+ *height
> buffer
->_Ymax
)
84 *height
-= (*destY
+ *height
- buffer
->_Ymax
);
95 * Try to do a fast and simple RGB(a) glDrawPixels.
96 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
99 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
100 GLsizei width
, GLsizei height
,
101 GLenum format
, GLenum type
, const GLvoid
*pixels
)
103 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
104 GLchan rgb
[MAX_WIDTH
][3];
105 GLchan rgba
[MAX_WIDTH
][4];
107 if (!ctx
->Current
.RasterPosValid
) {
108 return GL_TRUE
; /* no-op */
111 if ((SWRAST_CONTEXT(ctx
)->_RasterMask
&(~(SCISSOR_BIT
|WINCLIP_BIT
)))==0
112 && ctx
->Texture
._ReallyEnabled
== 0
113 && unpack
->Alignment
== 1
114 && !unpack
->SwapBytes
115 && !unpack
->LsbFirst
) {
119 GLint drawWidth
= width
; /* actual width drawn */
120 GLint drawHeight
= height
; /* actual height drawn */
121 GLint skipPixels
= unpack
->SkipPixels
;
122 GLint skipRows
= unpack
->SkipRows
;
124 GLdepth zSpan
[MAX_WIDTH
]; /* only used when zooming */
127 if (unpack
->RowLength
> 0)
128 rowLength
= unpack
->RowLength
;
132 /* If we're not using pixel zoom then do all clipping calculations
133 * now. Otherwise, we'll let the _mesa_write_zoomed_*_span() functions
134 * handle the clipping.
136 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
137 /* horizontal clipping */
138 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
139 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
140 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
141 destX
= ctx
->DrawBuffer
->_Xmin
;
143 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
144 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
148 /* vertical clipping */
149 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
150 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
151 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
152 destY
= ctx
->DrawBuffer
->_Ymin
;
154 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
155 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
159 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
160 /* upside-down image */
161 /* horizontal clipping */
162 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
163 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
164 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
165 destX
= ctx
->DrawBuffer
->_Xmin
;
167 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
168 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
172 /* vertical clipping */
173 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
174 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
175 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
176 destY
= ctx
->DrawBuffer
->_Ymax
;
178 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
179 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
184 /* setup array of fragment Z value to pass to zoom function */
185 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMaxF
);
187 ASSERT(drawWidth
< MAX_WIDTH
);
188 for (i
=0; i
<drawWidth
; i
++)
191 /* save Y value of first row */
192 zoomY0
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
198 * The window region at (destX, destY) of size (drawWidth, drawHeight)
199 * will be written to.
200 * We'll take pixel data from buffer pointed to by "pixels" but we'll
201 * skip "skipRows" rows and skip "skipPixels" pixels/row.
204 if (format
== GL_RGBA
&& type
== CHAN_TYPE
205 && ctx
->_ImageTransferState
==0) {
206 if (ctx
->Visual
.rgbMode
) {
207 GLchan
*src
= (GLchan
*) pixels
208 + (skipRows
* rowLength
+ skipPixels
) * 4;
209 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
212 for (row
=0; row
<drawHeight
; row
++) {
213 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
215 src
+= rowLength
* 4;
219 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
222 for (row
=0; row
<drawHeight
; row
++) {
224 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
226 src
+= rowLength
* 4;
232 for (row
=0; row
<drawHeight
; row
++) {
233 _mesa_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
234 zSpan
, 0, (void *) src
, zoomY0
);
235 src
+= rowLength
* 4;
242 else if (format
== GL_RGB
&& type
== CHAN_TYPE
243 && ctx
->_ImageTransferState
== 0) {
244 if (ctx
->Visual
.rgbMode
) {
245 GLchan
*src
= (GLchan
*) pixels
246 + (skipRows
* rowLength
+ skipPixels
) * 3;
247 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
249 for (row
=0; row
<drawHeight
; row
++) {
250 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
252 src
+= rowLength
* 3;
256 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
259 for (row
=0; row
<drawHeight
; row
++) {
261 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
263 src
+= rowLength
* 3;
269 for (row
=0; row
<drawHeight
; row
++) {
270 _mesa_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
271 zSpan
, 0, (void *) src
, zoomY0
);
272 src
+= rowLength
* 3;
279 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
280 && ctx
->_ImageTransferState
==0) {
281 if (ctx
->Visual
.rgbMode
) {
282 GLchan
*src
= (GLchan
*) pixels
283 + (skipRows
* rowLength
+ skipPixels
);
284 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
287 ASSERT(drawWidth
< MAX_WIDTH
);
288 for (row
=0; row
<drawHeight
; row
++) {
290 for (i
=0;i
<drawWidth
;i
++) {
295 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
301 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
304 ASSERT(drawWidth
< MAX_WIDTH
);
305 for (row
=0; row
<drawHeight
; row
++) {
307 for (i
=0;i
<drawWidth
;i
++) {
313 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
321 ASSERT(drawWidth
< MAX_WIDTH
);
322 for (row
=0; row
<drawHeight
; row
++) {
324 for (i
=0;i
<drawWidth
;i
++) {
329 _mesa_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
330 zSpan
, 0, (void *) rgb
, zoomY0
);
338 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
339 && ctx
->_ImageTransferState
== 0) {
340 if (ctx
->Visual
.rgbMode
) {
341 GLchan
*src
= (GLchan
*) pixels
342 + (skipRows
* rowLength
+ skipPixels
)*2;
343 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
346 ASSERT(drawWidth
< MAX_WIDTH
);
347 for (row
=0; row
<drawHeight
; row
++) {
350 for (i
=0;i
<drawWidth
;i
++) {
356 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
357 (void *) rgba
, NULL
);
362 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
365 ASSERT(drawWidth
< MAX_WIDTH
);
366 for (row
=0; row
<drawHeight
; row
++) {
369 for (i
=0;i
<drawWidth
;i
++) {
376 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
377 (void *) rgba
, NULL
);
384 ASSERT(drawWidth
< MAX_WIDTH
);
385 for (row
=0; row
<drawHeight
; row
++) {
388 for (i
=0;i
<drawWidth
;i
++) {
394 _mesa_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
395 zSpan
, 0, (void *) rgba
, zoomY0
);
403 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
404 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
405 if (ctx
->Visual
.rgbMode
) {
406 /* convert CI data to RGBA */
407 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
410 for (row
=0; row
<drawHeight
; row
++) {
411 ASSERT(drawWidth
< MAX_WIDTH
);
412 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
413 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
414 (const GLchan (*)[4]) rgba
,
421 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
424 for (row
=0; row
<drawHeight
; row
++) {
425 ASSERT(drawWidth
< MAX_WIDTH
);
426 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
428 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
429 (const GLchan (*)[4]) rgba
,
438 for (row
=0; row
<drawHeight
; row
++) {
439 ASSERT(drawWidth
< MAX_WIDTH
);
440 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
441 _mesa_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
442 zSpan
, 0, (void *) rgba
, zoomY0
);
449 else if (ctx
->_ImageTransferState
==0) {
450 /* write CI data to CI frame buffer */
452 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
454 for (row
=0; row
<drawHeight
; row
++) {
455 (*ctx
->Driver
.WriteCI8Span
)(ctx
, drawWidth
, destX
, destY
,
469 /* can't handle this pixel format and/or data type here */
474 /* can't do a simple draw, have to use slow path */
481 * Do glDrawPixels of index pixels.
484 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
485 GLsizei width
, GLsizei height
,
486 GLenum type
, const GLvoid
*pixels
)
488 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
489 const GLint desty
= y
;
490 GLint row
, drawWidth
;
491 GLdepth zspan
[MAX_WIDTH
];
493 drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
495 /* Fragment depth values */
496 if (ctx
->Depth
.Test
|| ctx
->Fog
.Enabled
) {
497 GLdepth zval
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMaxF
);
499 for (i
= 0; i
< drawWidth
; i
++) {
507 for (row
= 0; row
< height
; row
++, y
++) {
508 GLuint indexes
[MAX_WIDTH
];
509 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
510 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
511 _mesa_unpack_index_span(ctx
, drawWidth
, GL_UNSIGNED_INT
, indexes
,
512 type
, source
, &ctx
->Unpack
,
513 ctx
->_ImageTransferState
);
515 _mesa_write_zoomed_index_span(ctx
, drawWidth
, x
, y
, zspan
, 0, indexes
, desty
);
518 _mesa_write_index_span(ctx
, drawWidth
, x
, y
, zspan
, 0, indexes
, GL_BITMAP
);
526 * Do glDrawPixels of stencil image. The image datatype may either
527 * be GLubyte or GLbitmap.
530 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
531 GLsizei width
, GLsizei height
,
532 GLenum type
, const GLvoid
*pixels
)
534 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
535 const GLint desty
= y
;
536 GLint row
, drawWidth
;
538 if (type
!= GL_BYTE
&&
539 type
!= GL_UNSIGNED_BYTE
&&
541 type
!= GL_UNSIGNED_SHORT
&&
543 type
!= GL_UNSIGNED_INT
&&
546 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(stencil type)");
550 drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
552 for (row
= 0; row
< height
; row
++, y
++) {
553 GLstencil values
[MAX_WIDTH
];
554 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
555 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
556 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
557 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
558 _mesa_unpack_index_span(ctx
, drawWidth
, destType
, values
,
559 type
, source
, &ctx
->Unpack
,
560 ctx
->_ImageTransferState
);
561 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
562 _mesa_shift_and_offset_stencil( ctx
, drawWidth
, values
);
564 if (ctx
->Pixel
.MapStencilFlag
) {
565 _mesa_map_stencil( ctx
, drawWidth
, values
);
569 _mesa_write_zoomed_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
,
573 _mesa_write_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
, values
);
581 * Do a glDrawPixels of depth values.
584 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
585 GLsizei width
, GLsizei height
,
586 GLenum type
, const GLvoid
*pixels
)
588 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
589 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
590 const GLint desty
= y
;
591 GLchan rgba
[MAX_WIDTH
][4];
592 GLuint ispan
[MAX_WIDTH
];
593 GLint drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
596 && type
!= GL_UNSIGNED_BYTE
598 && type
!= GL_UNSIGNED_SHORT
600 && type
!= GL_UNSIGNED_INT
601 && type
!= GL_FLOAT
) {
602 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(type)");
606 /* Colors or indexes */
607 if (ctx
->Visual
.rgbMode
) {
610 UNCLAMPED_FLOAT_TO_CHAN(r
, ctx
->Current
.RasterColor
[0]);
611 UNCLAMPED_FLOAT_TO_CHAN(g
, ctx
->Current
.RasterColor
[1]);
612 UNCLAMPED_FLOAT_TO_CHAN(b
, ctx
->Current
.RasterColor
[2]);
613 UNCLAMPED_FLOAT_TO_CHAN(a
, ctx
->Current
.RasterColor
[3]);
614 for (i
= 0; i
< drawWidth
; i
++) {
623 for (i
= 0; i
< drawWidth
; i
++) {
624 ispan
[i
] = ctx
->Current
.RasterIndex
;
628 if (type
==GL_UNSIGNED_SHORT
&& sizeof(GLdepth
)==sizeof(GLushort
)
629 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
) {
630 /* Special case: directly write 16-bit depth values */
632 for (row
= 0; row
< height
; row
++, y
++) {
633 GLdepth zspan
[MAX_WIDTH
];
634 const GLushort
*zptr
= _mesa_image_address(&ctx
->Unpack
,
635 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
637 for (i
= 0; i
< width
; i
++)
639 _mesa_write_rgba_span( ctx
, width
, x
, y
, zspan
, 0, rgba
, GL_BITMAP
);
642 else if (type
==GL_UNSIGNED_INT
&& ctx
->Visual
.depthBits
== 32
643 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
) {
644 /* Special case: directly write 32-bit depth values */
646 for (row
= 0; row
< height
; row
++, y
++) {
647 const GLuint
*zptr
= _mesa_image_address(&ctx
->Unpack
,
648 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
649 _mesa_write_rgba_span( ctx
, width
, x
, y
, zptr
, 0, rgba
, GL_BITMAP
);
655 for (row
= 0; row
< height
; row
++, y
++) {
656 GLfloat fspan
[MAX_WIDTH
];
657 GLdepth zspan
[MAX_WIDTH
];
658 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
,
659 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
660 _mesa_unpack_depth_span( ctx
, drawWidth
, fspan
, type
, src
,
662 /* clamp depth values to [0,1] and convert from floats to integers */
664 const GLfloat zs
= ctx
->DepthMaxF
;
666 for (i
= 0; i
< drawWidth
; i
++) {
667 zspan
[i
] = (GLdepth
) (fspan
[i
] * zs
);
671 if (ctx
->Visual
.rgbMode
) {
673 _mesa_write_zoomed_rgba_span(ctx
, width
, x
, y
, zspan
, 0,
674 (const GLchan (*)[4]) rgba
, desty
);
677 _mesa_write_rgba_span(ctx
, width
, x
, y
, zspan
, 0, rgba
, GL_BITMAP
);
682 _mesa_write_zoomed_index_span(ctx
, width
, x
, y
, zspan
, 0,
686 _mesa_write_index_span(ctx
, width
, x
, y
, zspan
, 0,
697 * Do glDrawPixels of RGBA pixels.
700 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
701 GLsizei width
, GLsizei height
,
702 GLenum format
, GLenum type
, const GLvoid
*pixels
)
704 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
705 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
706 const GLint desty
= y
;
707 GLdepth zspan
[MAX_WIDTH
];
709 GLfloat
*convImage
= NULL
;
710 GLuint transferOps
= ctx
->_ImageTransferState
;
712 if (!_mesa_is_legal_format_and_type(format
, type
)) {
713 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(format or type)");
717 /* Try an optimized glDrawPixels first */
718 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
))
721 /* Fragment depth values */
722 if (ctx
->Depth
.Test
|| ctx
->Fog
.Enabled
) {
723 /* fill in array of z values */
724 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMaxF
);
726 for (i
=0;i
<width
;i
++) {
732 if (SWRAST_CONTEXT(ctx
)->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
733 && x
+ width
<= ctx
->DrawBuffer
->Width
734 && y
+ height
<= ctx
->DrawBuffer
->Height
) {
738 quickDraw
= GL_FALSE
;
741 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
742 /* Convolution has to be handled specially. We'll create an
743 * intermediate image, applying all pixel transfer operations
744 * up to convolution. Then we'll convolve the image. Then
745 * we'll proceed with the rest of the transfer operations and
746 * rasterize the image.
749 GLfloat
*dest
, *tmpImage
;
751 tmpImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
753 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
756 convImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
759 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
763 /* Unpack the image and apply transfer ops up to convolution */
765 for (row
= 0; row
< height
; row
++) {
766 const GLvoid
*source
= _mesa_image_address(unpack
,
767 pixels
, width
, height
, format
, type
, 0, row
, 0);
768 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, (void *) dest
,
769 format
, type
, source
, unpack
,
770 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
776 if (ctx
->Pixel
.Convolution2DEnabled
) {
777 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
780 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
781 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
785 /* continue transfer ops and draw the convolved image */
786 unpack
= &_mesa_native_packing
;
790 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
797 GLchan rgba
[MAX_WIDTH
][4];
799 if (width
> MAX_WIDTH
)
801 for (row
= 0; row
< height
; row
++, y
++) {
802 const GLvoid
*source
= _mesa_image_address(unpack
,
803 pixels
, width
, height
, format
, type
, 0, row
, 0);
804 _mesa_unpack_chan_color_span(ctx
, width
, GL_RGBA
, (void*) rgba
,
805 format
, type
, source
, unpack
,
807 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
808 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
811 if (ctx
->Texture
._ReallyEnabled
&& ctx
->Pixel
.PixelTextureEnabled
) {
812 GLfloat s
[MAX_WIDTH
], t
[MAX_WIDTH
], r
[MAX_WIDTH
], q
[MAX_WIDTH
];
813 GLchan primary_rgba
[MAX_WIDTH
][4];
815 /* XXX not sure how multitexture is supposed to work here */
817 MEMCPY(primary_rgba
, rgba
, 4 * width
* sizeof(GLchan
));
819 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
820 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
821 _mesa_pixeltexgen(ctx
, width
, (const GLchan (*)[4]) rgba
,
823 _swrast_texture_fragments(ctx
, unit
, width
, s
, t
, r
, NULL
,
824 (CONST
GLchan (*)[4]) primary_rgba
,
831 (*ctx
->Driver
.WriteRGBASpan
)( ctx
, width
, x
, y
,
832 (CONST
GLchan (*)[]) rgba
, NULL
);
835 _mesa_write_zoomed_rgba_span( ctx
, width
, x
, y
, zspan
, 0,
836 (CONST
GLchan (*)[]) rgba
, desty
);
839 _mesa_write_rgba_span( ctx
, (GLuint
) width
, x
, y
, zspan
, 0,
853 * Execute glDrawPixels
856 _swrast_DrawPixels( GLcontext
*ctx
,
858 GLsizei width
, GLsizei height
,
859 GLenum format
, GLenum type
,
860 const struct gl_pixelstore_attrib
*unpack
,
861 const GLvoid
*pixels
)
865 if (SWRAST_CONTEXT(ctx
)->NewState
)
866 _swrast_validate_derived( ctx
);
869 case GL_STENCIL_INDEX
:
870 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
872 case GL_DEPTH_COMPONENT
:
873 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
876 if (ctx
->Visual
.rgbMode
)
877 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, pixels
);
879 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, pixels
);
886 case GL_LUMINANCE_ALPHA
:
892 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
);
895 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(format)" );