1 /* $Id: drawpix.c,v 1.42 2000/10/29 19:02:23 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 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.
54 * Given the dest position, size and skipPixels and skipRows values
55 * for a glDrawPixels command, perform clipping of the image bounds
56 * so the result lies withing the context's buffer bounds.
57 * Return: GL_TRUE if image is ready for drawing
58 * GL_FALSE if image was completely clipped away (draw nothing)
61 _mesa_clip_pixelrect(const GLcontext
*ctx
,
62 GLint
*destX
, GLint
*destY
,
63 GLsizei
*width
, GLsizei
*height
,
64 GLint
*skipPixels
, GLint
*skipRows
)
66 const GLframebuffer
*buffer
= ctx
->DrawBuffer
;
69 if (*destX
< buffer
->Xmin
) {
70 *skipPixels
+= (buffer
->Xmin
- *destX
);
71 *width
-= (buffer
->Xmin
- *destX
);
72 *destX
= buffer
->Xmin
;
75 if (*destX
+ *width
> buffer
->Xmax
)
76 *width
-= (*destX
+ *width
- buffer
->Xmax
);
82 if (*destY
< buffer
->Ymin
) {
83 *skipRows
+= (buffer
->Ymin
- *destY
);
84 *height
-= (buffer
->Ymin
- *destY
);
85 *destY
= buffer
->Ymin
;
88 if (*destY
+ *height
> buffer
->Ymax
)
89 *height
-= (*destY
+ *height
- buffer
->Ymax
);
100 * Try to do a fast and simple RGB(a) glDrawPixels.
101 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
104 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
105 GLsizei width
, GLsizei height
,
106 GLenum format
, GLenum type
, const GLvoid
*pixels
)
108 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
109 GLchan rgb
[MAX_WIDTH
][3];
110 GLchan rgba
[MAX_WIDTH
][4];
112 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx
, "glDrawPixels",
116 if (!ctx
->Current
.RasterPosValid
) {
117 return GL_TRUE
; /* no-op */
120 if ((ctx
->RasterMask
&(~(SCISSOR_BIT
|WINCLIP_BIT
)))==0
121 && ctx
->Texture
.ReallyEnabled
== 0
122 && unpack
->Alignment
== 1
123 && !unpack
->SwapBytes
124 && !unpack
->LsbFirst
) {
128 GLint drawWidth
= width
; /* actual width drawn */
129 GLint drawHeight
= height
; /* actual height drawn */
130 GLint skipPixels
= unpack
->SkipPixels
;
131 GLint skipRows
= unpack
->SkipRows
;
133 GLdepth zSpan
[MAX_WIDTH
]; /* only used when zooming */
136 if (unpack
->RowLength
> 0)
137 rowLength
= unpack
->RowLength
;
141 /* If we're not using pixel zoom then do all clipping calculations
142 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions
143 * handle the clipping.
145 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
146 /* horizontal clipping */
147 if (destX
< ctx
->DrawBuffer
->Xmin
) {
148 skipPixels
+= (ctx
->DrawBuffer
->Xmin
- destX
);
149 drawWidth
-= (ctx
->DrawBuffer
->Xmin
- destX
);
150 destX
= ctx
->DrawBuffer
->Xmin
;
152 if (destX
+ drawWidth
> ctx
->DrawBuffer
->Xmax
)
153 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->Xmax
);
157 /* vertical clipping */
158 if (destY
< ctx
->DrawBuffer
->Ymin
) {
159 skipRows
+= (ctx
->DrawBuffer
->Ymin
- destY
);
160 drawHeight
-= (ctx
->DrawBuffer
->Ymin
- destY
);
161 destY
= ctx
->DrawBuffer
->Ymin
;
163 if (destY
+ drawHeight
> ctx
->DrawBuffer
->Ymax
)
164 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->Ymax
);
168 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
169 /* upside-down image */
170 /* horizontal clipping */
171 if (destX
< ctx
->DrawBuffer
->Xmin
) {
172 skipPixels
+= (ctx
->DrawBuffer
->Xmin
- destX
);
173 drawWidth
-= (ctx
->DrawBuffer
->Xmin
- destX
);
174 destX
= ctx
->DrawBuffer
->Xmin
;
176 if (destX
+ drawWidth
> ctx
->DrawBuffer
->Xmax
)
177 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->Xmax
);
181 /* vertical clipping */
182 if (destY
> ctx
->DrawBuffer
->Ymax
) {
183 skipRows
+= (destY
- ctx
->DrawBuffer
->Ymax
);
184 drawHeight
-= (destY
- ctx
->DrawBuffer
->Ymax
);
185 destY
= ctx
->DrawBuffer
->Ymax
;
187 if (destY
- drawHeight
< ctx
->DrawBuffer
->Ymin
)
188 drawHeight
-= (ctx
->DrawBuffer
->Ymin
- (destY
- drawHeight
));
193 /* setup array of fragment Z value to pass to zoom function */
194 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->Visual
.DepthMaxF
);
196 ASSERT(drawWidth
< MAX_WIDTH
);
197 for (i
=0; i
<drawWidth
; i
++)
200 /* save Y value of first row */
201 zoomY0
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
207 * The window region at (destX, destY) of size (drawWidth, drawHeight)
208 * will be written to.
209 * We'll take pixel data from buffer pointed to by "pixels" but we'll
210 * skip "skipRows" rows and skip "skipPixels" pixels/row.
213 if (format
== GL_RGBA
&& type
== CHAN_TYPE
214 && ctx
->ImageTransferState
==0) {
215 if (ctx
->Visual
.RGBAflag
) {
216 GLchan
*src
= (GLchan
*) pixels
217 + (skipRows
* rowLength
+ skipPixels
) * 4;
218 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
221 for (row
=0; row
<drawHeight
; row
++) {
222 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
224 src
+= rowLength
* 4;
228 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
231 for (row
=0; row
<drawHeight
; row
++) {
233 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
235 src
+= rowLength
* 4;
241 for (row
=0; row
<drawHeight
; row
++) {
242 gl_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
243 zSpan
, 0, (void *) src
, zoomY0
);
244 src
+= rowLength
* 4;
251 else if (format
== GL_RGB
&& type
== CHAN_TYPE
252 && ctx
->ImageTransferState
== 0) {
253 if (ctx
->Visual
.RGBAflag
) {
254 GLchan
*src
= (GLchan
*) pixels
255 + (skipRows
* rowLength
+ skipPixels
) * 3;
256 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
258 for (row
=0; row
<drawHeight
; row
++) {
259 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
261 src
+= rowLength
* 3;
265 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
268 for (row
=0; row
<drawHeight
; row
++) {
270 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
272 src
+= rowLength
* 3;
278 for (row
=0; row
<drawHeight
; row
++) {
279 gl_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
280 zSpan
, 0, (void *) src
, zoomY0
);
281 src
+= rowLength
* 3;
288 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
289 && ctx
->ImageTransferState
==0) {
290 if (ctx
->Visual
.RGBAflag
) {
291 GLchan
*src
= (GLchan
*) pixels
292 + (skipRows
* rowLength
+ skipPixels
);
293 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
296 ASSERT(drawWidth
< MAX_WIDTH
);
297 for (row
=0; row
<drawHeight
; row
++) {
299 for (i
=0;i
<drawWidth
;i
++) {
304 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
310 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
313 ASSERT(drawWidth
< MAX_WIDTH
);
314 for (row
=0; row
<drawHeight
; row
++) {
316 for (i
=0;i
<drawWidth
;i
++) {
322 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
330 ASSERT(drawWidth
< MAX_WIDTH
);
331 for (row
=0; row
<drawHeight
; row
++) {
333 for (i
=0;i
<drawWidth
;i
++) {
338 gl_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
339 zSpan
, 0, (void *) rgb
, zoomY0
);
347 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
348 && ctx
->ImageTransferState
== 0) {
349 if (ctx
->Visual
.RGBAflag
) {
350 GLchan
*src
= (GLchan
*) pixels
351 + (skipRows
* rowLength
+ skipPixels
)*2;
352 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
355 ASSERT(drawWidth
< MAX_WIDTH
);
356 for (row
=0; row
<drawHeight
; row
++) {
359 for (i
=0;i
<drawWidth
;i
++) {
365 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
366 (void *) rgba
, NULL
);
371 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
374 ASSERT(drawWidth
< MAX_WIDTH
);
375 for (row
=0; row
<drawHeight
; row
++) {
378 for (i
=0;i
<drawWidth
;i
++) {
385 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
386 (void *) rgba
, NULL
);
393 ASSERT(drawWidth
< MAX_WIDTH
);
394 for (row
=0; row
<drawHeight
; row
++) {
397 for (i
=0;i
<drawWidth
;i
++) {
403 gl_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
404 zSpan
, 0, (void *) rgba
, zoomY0
);
412 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
413 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
414 if (ctx
->Visual
.RGBAflag
) {
415 /* convert CI data to RGBA */
416 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
419 for (row
=0; row
<drawHeight
; row
++) {
420 ASSERT(drawWidth
< MAX_WIDTH
);
421 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
422 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
423 (const GLchan (*)[4]) rgba
,
430 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
433 for (row
=0; row
<drawHeight
; row
++) {
434 ASSERT(drawWidth
< MAX_WIDTH
);
435 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
437 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
438 (const GLchan (*)[4]) rgba
,
447 for (row
=0; row
<drawHeight
; row
++) {
448 ASSERT(drawWidth
< MAX_WIDTH
);
449 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
450 gl_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
451 zSpan
, 0, (void *) rgba
, zoomY0
);
458 else if (ctx
->ImageTransferState
==0) {
459 /* write CI data to CI frame buffer */
461 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
463 for (row
=0; row
<drawHeight
; row
++) {
464 (*ctx
->Driver
.WriteCI8Span
)(ctx
, drawWidth
, destX
, destY
,
478 /* can't handle this pixel format and/or data type here */
483 /* can't do a simple draw, have to use slow path */
490 * Do glDrawPixels of index pixels.
493 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
494 GLsizei width
, GLsizei height
,
495 GLenum type
, const GLvoid
*pixels
)
497 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
498 const GLint desty
= y
;
499 GLint row
, drawWidth
;
500 GLdepth zspan
[MAX_WIDTH
];
502 drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
504 /* Fragment depth values */
505 if (ctx
->Depth
.Test
|| ctx
->Fog
.Enabled
) {
506 GLdepth zval
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->Visual
.DepthMaxF
);
508 for (i
= 0; i
< drawWidth
; i
++) {
516 for (row
= 0; row
< height
; row
++, y
++) {
517 GLuint indexes
[MAX_WIDTH
];
518 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
519 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
520 _mesa_unpack_index_span(ctx
, drawWidth
, GL_UNSIGNED_INT
, indexes
,
521 type
, source
, &ctx
->Unpack
,
522 ctx
->ImageTransferState
);
524 gl_write_zoomed_index_span(ctx
, drawWidth
, x
, y
, zspan
, 0, indexes
, desty
);
527 gl_write_index_span(ctx
, drawWidth
, x
, y
, zspan
, 0, indexes
, GL_BITMAP
);
535 * Do glDrawPixels of stencil image. The image datatype may either
536 * be GLubyte or GLbitmap.
539 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
540 GLsizei width
, GLsizei height
,
541 GLenum type
, const GLvoid
*pixels
)
543 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
544 const GLint desty
= y
;
545 GLint row
, drawWidth
;
547 if (type
!= GL_BYTE
&&
548 type
!= GL_UNSIGNED_BYTE
&&
550 type
!= GL_UNSIGNED_SHORT
&&
552 type
!= GL_UNSIGNED_INT
&&
555 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(stencil type)");
559 drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
561 for (row
= 0; row
< height
; row
++, y
++) {
562 GLstencil values
[MAX_WIDTH
];
563 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
564 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
565 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
566 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
567 _mesa_unpack_index_span(ctx
, drawWidth
, destType
, values
,
568 type
, source
, &ctx
->Unpack
,
569 ctx
->ImageTransferState
);
570 if (ctx
->ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
571 _mesa_shift_and_offset_stencil( ctx
, drawWidth
, values
);
573 if (ctx
->Pixel
.MapStencilFlag
) {
574 _mesa_map_stencil( ctx
, drawWidth
, values
);
578 gl_write_zoomed_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
,
582 _mesa_write_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
, values
);
590 * Do a glDrawPixels of depth values.
593 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
594 GLsizei width
, GLsizei height
,
595 GLenum type
, const GLvoid
*pixels
)
597 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
598 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
599 const GLint desty
= y
;
600 GLchan rgba
[MAX_WIDTH
][4];
601 GLuint ispan
[MAX_WIDTH
];
602 GLint drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
605 && type
!= GL_UNSIGNED_BYTE
607 && type
!= GL_UNSIGNED_SHORT
609 && type
!= GL_UNSIGNED_INT
610 && type
!= GL_FLOAT
) {
611 gl_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(type)");
615 /* Colors or indexes */
616 if (ctx
->Visual
.RGBAflag
) {
617 GLint r
= FLOAT_TO_CHAN(ctx
->Current
.RasterColor
[0]);
618 GLint g
= FLOAT_TO_CHAN(ctx
->Current
.RasterColor
[1]);
619 GLint b
= FLOAT_TO_CHAN(ctx
->Current
.RasterColor
[2]);
620 GLint a
= FLOAT_TO_CHAN(ctx
->Current
.RasterColor
[3]);
622 for (i
= 0; i
< drawWidth
; i
++) {
631 for (i
= 0; i
< drawWidth
; i
++) {
632 ispan
[i
] = ctx
->Current
.RasterIndex
;
636 if (type
==GL_UNSIGNED_SHORT
&& sizeof(GLdepth
)==sizeof(GLushort
)
637 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.RGBAflag
) {
638 /* Special case: directly write 16-bit depth values */
640 for (row
= 0; row
< height
; row
++, y
++) {
641 GLdepth zspan
[MAX_WIDTH
];
642 const GLushort
*zptr
= _mesa_image_address(&ctx
->Unpack
,
643 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
645 for (i
= 0; i
< width
; i
++)
647 gl_write_rgba_span( ctx
, width
, x
, y
, zspan
, 0, rgba
, GL_BITMAP
);
650 else if (type
==GL_UNSIGNED_INT
&& ctx
->Visual
.DepthBits
== 32
651 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.RGBAflag
) {
652 /* Special case: directly write 32-bit depth values */
654 for (row
= 0; row
< height
; row
++, y
++) {
655 const GLuint
*zptr
= _mesa_image_address(&ctx
->Unpack
,
656 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
657 gl_write_rgba_span( ctx
, width
, x
, y
, zptr
, 0, rgba
, GL_BITMAP
);
663 for (row
= 0; row
< height
; row
++, y
++) {
664 GLdepth zspan
[MAX_WIDTH
];
665 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
,
666 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
667 _mesa_unpack_depth_span( ctx
, drawWidth
, zspan
, type
, src
,
668 &ctx
->Unpack
, ctx
->ImageTransferState
);
669 if (ctx
->Visual
.RGBAflag
) {
671 gl_write_zoomed_rgba_span(ctx
, width
, x
, y
, zspan
, 0,
672 (const GLchan (*)[4]) rgba
, desty
);
675 gl_write_rgba_span(ctx
, width
, x
, y
, zspan
, 0, rgba
, GL_BITMAP
);
680 gl_write_zoomed_index_span(ctx
, width
, x
, y
, zspan
, 0,
684 gl_write_index_span(ctx
, width
, x
, y
, zspan
, 0,
695 * Do glDrawPixels of RGBA pixels.
698 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
699 GLsizei width
, GLsizei height
,
700 GLenum format
, GLenum type
, const GLvoid
*pixels
)
702 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
703 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
704 const GLint desty
= y
;
705 GLdepth zspan
[MAX_WIDTH
];
707 GLfloat
*convImage
= NULL
;
708 GLuint transferOps
= ctx
->ImageTransferState
;
710 if (!_mesa_is_legal_format_and_type(format
, type
)) {
711 gl_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(format or type)");
715 /* Try an optimized glDrawPixels first */
716 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
))
719 /* Fragment depth values */
720 if (ctx
->Depth
.Test
|| ctx
->Fog
.Enabled
) {
721 /* fill in array of z values */
722 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->Visual
.DepthMaxF
);
724 for (i
=0;i
<width
;i
++) {
730 if (ctx
->RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
731 && x
+ width
<= ctx
->DrawBuffer
->Width
732 && y
+ height
<= ctx
->DrawBuffer
->Height
) {
736 quickDraw
= GL_FALSE
;
739 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
740 /* Convolution has to be handled specially. We'll create an
741 * intermediate image, applying all pixel transfer operations
742 * up to convolution. Then we'll convolve the image. Then
743 * we'll proceed with the rest of the transfer operations and
744 * rasterize the image.
747 GLfloat
*dest
, *tmpImage
;
749 tmpImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
751 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
754 convImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
757 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
761 /* Unpack the image and apply transfer ops up to convolution */
763 for (row
= 0; row
< height
; row
++) {
764 const GLvoid
*source
= _mesa_image_address(unpack
,
765 pixels
, width
, height
, format
, type
, 0, row
, 0);
766 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, (void *) dest
,
767 format
, type
, source
, unpack
,
768 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
774 if (ctx
->Pixel
.Convolution2DEnabled
) {
775 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
778 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
779 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
783 /* continue transfer ops and draw the convolved image */
784 unpack
= &_mesa_native_packing
;
788 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
795 GLchan rgba
[MAX_WIDTH
][4];
797 if (width
> MAX_WIDTH
)
799 for (row
= 0; row
< height
; row
++, y
++) {
800 const GLvoid
*source
= _mesa_image_address(unpack
,
801 pixels
, width
, height
, format
, type
, 0, row
, 0);
802 _mesa_unpack_chan_color_span(ctx
, width
, GL_RGBA
, (void*) rgba
,
803 format
, type
, source
, unpack
,
805 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
806 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
809 if (ctx
->Texture
.ReallyEnabled
&& ctx
->Pixel
.PixelTextureEnabled
) {
810 GLfloat s
[MAX_WIDTH
], t
[MAX_WIDTH
], r
[MAX_WIDTH
], q
[MAX_WIDTH
];
811 GLchan primary_rgba
[MAX_WIDTH
][4];
813 /* XXX not sure how multitexture is supposed to work here */
815 MEMCPY(primary_rgba
, rgba
, 4 * width
* sizeof(GLchan
));
817 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
818 if (ctx
->Texture
.Unit
[unit
].ReallyEnabled
) {
819 _mesa_pixeltexgen(ctx
, width
, (const GLchan (*)[4]) rgba
,
821 gl_texture_pixels(ctx
, unit
, width
, s
, t
, r
, NULL
,
828 (*ctx
->Driver
.WriteRGBASpan
)( ctx
, width
, x
, y
,
829 (CONST
GLchan (*)[]) rgba
, NULL
);
832 gl_write_zoomed_rgba_span( ctx
, width
, x
, y
, zspan
, 0,
833 (CONST
GLchan (*)[]) rgba
, desty
);
836 gl_write_rgba_span( ctx
, (GLuint
) width
, x
, y
, zspan
, 0,
850 * Execute glDrawPixels
853 _mesa_DrawPixels( GLsizei width
, GLsizei height
,
854 GLenum format
, GLenum type
, const GLvoid
*pixels
)
856 GET_CURRENT_CONTEXT(ctx
);
857 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawPixels");
859 if (ctx
->RenderMode
==GL_RENDER
) {
861 if (!pixels
|| !ctx
->Current
.RasterPosValid
) {
866 gl_update_state(ctx
);
869 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
870 _mesa_update_image_transfer_state(ctx
);
872 x
= (GLint
) (ctx
->Current
.RasterPos
[0] + 0.5F
);
873 y
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
875 ctx
->OcclusionResult
= GL_TRUE
;
877 /* see if device driver can do the drawpix */
878 if (ctx
->Driver
.DrawPixels
879 && (*ctx
->Driver
.DrawPixels
)(ctx
, x
, y
, width
, height
, format
, type
,
880 &ctx
->Unpack
, pixels
)) {
886 case GL_STENCIL_INDEX
:
887 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
889 case GL_DEPTH_COMPONENT
:
890 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
893 if (ctx
->Visual
.RGBAflag
)
894 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, pixels
);
896 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, pixels
);
903 case GL_LUMINANCE_ALPHA
:
909 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
);
912 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(format)" );
916 else if (ctx
->RenderMode
==GL_FEEDBACK
) {
917 if (ctx
->Current
.RasterPosValid
) {
919 GLfloat texcoord
[4], invq
;
920 color
[0] = CHAN_TO_FLOAT(ctx
->Current
.Color
[0]);
921 color
[1] = CHAN_TO_FLOAT(ctx
->Current
.Color
[1]);
922 color
[2] = CHAN_TO_FLOAT(ctx
->Current
.Color
[2]);
923 color
[3] = CHAN_TO_FLOAT(ctx
->Current
.Color
[3]);
924 invq
= 1.0F
/ ctx
->Current
.Texcoord
[0][3];
925 texcoord
[0] = ctx
->Current
.Texcoord
[0][0] * invq
;
926 texcoord
[1] = ctx
->Current
.Texcoord
[0][1] * invq
;
927 texcoord
[2] = ctx
->Current
.Texcoord
[0][2] * invq
;
928 texcoord
[3] = ctx
->Current
.Texcoord
[0][3];
929 FEEDBACK_TOKEN( ctx
, (GLfloat
) (GLint
) GL_DRAW_PIXEL_TOKEN
);
930 gl_feedback_vertex( ctx
,
931 ctx
->Current
.RasterPos
,
932 color
, ctx
->Current
.Index
, texcoord
);
935 else if (ctx
->RenderMode
==GL_SELECT
) {
936 if (ctx
->Current
.RasterPosValid
) {
937 gl_update_hitflag( ctx
, ctx
->Current
.RasterPos
[2] );