1 /* $Id: s_drawpix.c,v 1.22 2001/06/26 21:15:36 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"
41 #include "s_pixeltex.h"
43 #include "s_stencil.h"
44 #include "s_texture.h"
50 * Given the dest position, size and skipPixels and skipRows values
51 * for a glDrawPixels command, perform clipping of the image bounds
52 * so the result lies withing the context's buffer bounds.
53 * Return: GL_TRUE if image is ready for drawing
54 * GL_FALSE if image was completely clipped away (draw nothing)
57 _mesa_clip_pixelrect(const GLcontext
*ctx
,
58 GLint
*destX
, GLint
*destY
,
59 GLsizei
*width
, GLsizei
*height
,
60 GLint
*skipPixels
, GLint
*skipRows
)
62 const GLframebuffer
*buffer
= ctx
->DrawBuffer
;
65 if (*destX
< buffer
->_Xmin
) {
66 *skipPixels
+= (buffer
->_Xmin
- *destX
);
67 *width
-= (buffer
->_Xmin
- *destX
);
68 *destX
= buffer
->_Xmin
;
71 if (*destX
+ *width
> buffer
->_Xmax
)
72 *width
-= (*destX
+ *width
- buffer
->_Xmax
);
78 if (*destY
< buffer
->_Ymin
) {
79 *skipRows
+= (buffer
->_Ymin
- *destY
);
80 *height
-= (buffer
->_Ymin
- *destY
);
81 *destY
= buffer
->_Ymin
;
84 if (*destY
+ *height
> buffer
->_Ymax
)
85 *height
-= (*destY
+ *height
- buffer
->_Ymax
);
96 * Try to do a fast and simple RGB(a) glDrawPixels.
97 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
100 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
101 GLsizei width
, GLsizei height
,
102 GLenum format
, GLenum type
, const GLvoid
*pixels
)
104 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
105 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
106 GLchan rgb
[MAX_WIDTH
][3];
107 GLchan rgba
[MAX_WIDTH
][4];
109 if (!ctx
->Current
.RasterPosValid
) {
110 return GL_TRUE
; /* no-op */
113 if ((SWRAST_CONTEXT(ctx
)->_RasterMask
&(~(SCISSOR_BIT
|WINCLIP_BIT
)))==0
114 && ctx
->Texture
._ReallyEnabled
== 0
115 && unpack
->Alignment
== 1
116 && !unpack
->SwapBytes
117 && !unpack
->LsbFirst
) {
121 GLint drawWidth
= width
; /* actual width drawn */
122 GLint drawHeight
= height
; /* actual height drawn */
123 GLint skipPixels
= unpack
->SkipPixels
;
124 GLint skipRows
= unpack
->SkipRows
;
126 GLdepth zSpan
[MAX_WIDTH
]; /* only used when zooming */
129 if (unpack
->RowLength
> 0)
130 rowLength
= unpack
->RowLength
;
134 /* If we're not using pixel zoom then do all clipping calculations
135 * now. Otherwise, we'll let the _mesa_write_zoomed_*_span() functions
136 * handle the clipping.
138 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
139 /* horizontal clipping */
140 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
141 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
142 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
143 destX
= ctx
->DrawBuffer
->_Xmin
;
145 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
146 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
150 /* vertical clipping */
151 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
152 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
153 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
154 destY
= ctx
->DrawBuffer
->_Ymin
;
156 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
157 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
161 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
162 /* upside-down image */
163 /* horizontal clipping */
164 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
165 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
166 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
167 destX
= ctx
->DrawBuffer
->_Xmin
;
169 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
170 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
174 /* vertical clipping */
175 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
176 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
177 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
178 destY
= ctx
->DrawBuffer
->_Ymax
;
180 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
181 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
186 /* setup array of fragment Z value to pass to zoom function */
187 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMaxF
);
189 ASSERT(drawWidth
< MAX_WIDTH
);
190 for (i
=0; i
<drawWidth
; i
++)
193 /* save Y value of first row */
194 zoomY0
= IROUND(ctx
->Current
.RasterPos
[1]);
200 * The window region at (destX, destY) of size (drawWidth, drawHeight)
201 * will be written to.
202 * We'll take pixel data from buffer pointed to by "pixels" but we'll
203 * skip "skipRows" rows and skip "skipPixels" pixels/row.
206 if (format
== GL_RGBA
&& type
== CHAN_TYPE
207 && ctx
->_ImageTransferState
==0) {
208 if (ctx
->Visual
.rgbMode
) {
209 GLchan
*src
= (GLchan
*) pixels
210 + (skipRows
* rowLength
+ skipPixels
) * 4;
211 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
214 for (row
=0; row
<drawHeight
; row
++) {
215 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
216 (CONST
GLchan (*)[4]) src
, NULL
);
217 src
+= rowLength
* 4;
221 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
224 for (row
=0; row
<drawHeight
; row
++) {
226 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
227 (CONST
GLchan (*)[4]) src
, NULL
);
228 src
+= rowLength
* 4;
234 for (row
=0; row
<drawHeight
; row
++) {
235 _mesa_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
236 zSpan
, 0, (CONST
GLchan (*)[4]) src
, zoomY0
);
237 src
+= rowLength
* 4;
244 else if (format
== GL_RGB
&& type
== CHAN_TYPE
245 && ctx
->_ImageTransferState
== 0) {
246 if (ctx
->Visual
.rgbMode
) {
247 GLchan
*src
= (GLchan
*) pixels
248 + (skipRows
* rowLength
+ skipPixels
) * 3;
249 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
251 for (row
=0; row
<drawHeight
; row
++) {
252 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
253 (CONST
GLchan (*)[3]) src
, NULL
);
254 src
+= rowLength
* 3;
258 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
261 for (row
=0; row
<drawHeight
; row
++) {
263 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
264 (CONST
GLchan (*)[3]) src
, NULL
);
265 src
+= rowLength
* 3;
271 for (row
=0; row
<drawHeight
; row
++) {
272 _mesa_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
273 zSpan
, 0, (CONST
GLchan (*)[3]) src
, zoomY0
);
274 src
+= rowLength
* 3;
281 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
282 && ctx
->_ImageTransferState
==0) {
283 if (ctx
->Visual
.rgbMode
) {
284 GLchan
*src
= (GLchan
*) pixels
285 + (skipRows
* rowLength
+ skipPixels
);
286 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
289 ASSERT(drawWidth
< MAX_WIDTH
);
290 for (row
=0; row
<drawHeight
; row
++) {
292 for (i
=0;i
<drawWidth
;i
++) {
297 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
298 (CONST
GLchan (*)[3]) rgb
, NULL
);
303 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
306 ASSERT(drawWidth
< MAX_WIDTH
);
307 for (row
=0; row
<drawHeight
; row
++) {
309 for (i
=0;i
<drawWidth
;i
++) {
315 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
316 (CONST
GLchan (*)[3]) rgb
, NULL
);
323 ASSERT(drawWidth
< MAX_WIDTH
);
324 for (row
=0; row
<drawHeight
; row
++) {
326 for (i
=0;i
<drawWidth
;i
++) {
331 _mesa_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
332 zSpan
, 0, (CONST
GLchan (*)[3]) rgb
, zoomY0
);
340 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
341 && ctx
->_ImageTransferState
== 0) {
342 if (ctx
->Visual
.rgbMode
) {
343 GLchan
*src
= (GLchan
*) pixels
344 + (skipRows
* rowLength
+ skipPixels
)*2;
345 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
348 ASSERT(drawWidth
< MAX_WIDTH
);
349 for (row
=0; row
<drawHeight
; row
++) {
352 for (i
=0;i
<drawWidth
;i
++) {
358 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
359 (CONST
GLchan (*)[4]) rgba
, NULL
);
364 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
367 ASSERT(drawWidth
< MAX_WIDTH
);
368 for (row
=0; row
<drawHeight
; row
++) {
371 for (i
=0;i
<drawWidth
;i
++) {
378 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
379 (CONST
GLchan (*)[4]) rgba
, NULL
);
386 ASSERT(drawWidth
< MAX_WIDTH
);
387 for (row
=0; row
<drawHeight
; row
++) {
390 for (i
=0;i
<drawWidth
;i
++) {
396 _mesa_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
397 zSpan
, 0, (CONST
GLchan (*)[4]) rgba
, zoomY0
);
405 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
406 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
407 if (ctx
->Visual
.rgbMode
) {
408 /* convert CI data to RGBA */
409 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
412 for (row
=0; row
<drawHeight
; row
++) {
413 ASSERT(drawWidth
< MAX_WIDTH
);
414 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
415 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
416 (const GLchan (*)[4]) rgba
,
423 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
426 for (row
=0; row
<drawHeight
; row
++) {
427 ASSERT(drawWidth
< MAX_WIDTH
);
428 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
430 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
431 (CONST
GLchan (*)[4]) rgba
,
440 for (row
=0; row
<drawHeight
; row
++) {
441 ASSERT(drawWidth
< MAX_WIDTH
);
442 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
443 _mesa_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
444 zSpan
, 0, (CONST
GLchan (*)[4]) rgba
, zoomY0
);
451 else if (ctx
->_ImageTransferState
==0) {
452 /* write CI data to CI frame buffer */
454 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
456 for (row
=0; row
<drawHeight
; row
++) {
457 (*swrast
->Driver
.WriteCI8Span
)(ctx
, drawWidth
, destX
, destY
,
471 /* can't handle this pixel format and/or data type here */
476 /* can't do a simple draw, have to use slow path */
483 * Do glDrawPixels of index pixels.
486 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
487 GLsizei width
, GLsizei height
,
488 GLenum type
, const GLvoid
*pixels
)
490 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
491 const GLint desty
= y
;
492 GLint row
, drawWidth
;
493 GLdepth zspan
[MAX_WIDTH
];
494 GLfloat fogSpan
[MAX_WIDTH
];
496 drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
498 /* Fragment depth values */
499 if (ctx
->Depth
.Test
|| ctx
->Fog
.Enabled
) {
500 GLdepth zval
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMaxF
);
504 if (ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORDINATE_EXT
)
505 fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterFogCoord
);
507 fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
509 for (i
= 0; i
< drawWidth
; i
++) {
518 for (row
= 0; row
< height
; row
++, y
++) {
519 GLuint indexes
[MAX_WIDTH
];
520 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
521 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
522 _mesa_unpack_index_span(ctx
, drawWidth
, GL_UNSIGNED_INT
, indexes
,
523 type
, source
, &ctx
->Unpack
,
524 ctx
->_ImageTransferState
);
526 _mesa_write_zoomed_index_span(ctx
, drawWidth
, x
, y
, zspan
, fogSpan
,
530 _mesa_write_index_span(ctx
, drawWidth
, x
, y
, zspan
, fogSpan
, indexes
,
539 * Do glDrawPixels of stencil image. The image datatype may either
540 * be GLubyte or GLbitmap.
543 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
544 GLsizei width
, GLsizei height
,
545 GLenum type
, const GLvoid
*pixels
)
547 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
548 const GLint desty
= y
;
549 GLint row
, drawWidth
;
551 if (type
!= GL_BYTE
&&
552 type
!= GL_UNSIGNED_BYTE
&&
554 type
!= GL_UNSIGNED_SHORT
&&
556 type
!= GL_UNSIGNED_INT
&&
559 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(stencil type)");
563 drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
565 for (row
= 0; row
< height
; row
++, y
++) {
566 GLstencil values
[MAX_WIDTH
];
567 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
568 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
569 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
570 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
571 _mesa_unpack_index_span(ctx
, drawWidth
, destType
, values
,
572 type
, source
, &ctx
->Unpack
,
573 ctx
->_ImageTransferState
);
574 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
575 _mesa_shift_and_offset_stencil( ctx
, drawWidth
, values
);
577 if (ctx
->Pixel
.MapStencilFlag
) {
578 _mesa_map_stencil( ctx
, drawWidth
, values
);
582 _mesa_write_zoomed_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
,
586 _mesa_write_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
, values
);
594 * Do a glDrawPixels of depth values.
597 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
598 GLsizei width
, GLsizei height
,
599 GLenum type
, const GLvoid
*pixels
)
601 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
602 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
603 const GLint desty
= y
;
604 GLchan rgba
[MAX_WIDTH
][4];
605 GLuint ispan
[MAX_WIDTH
];
606 GLint drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
609 && type
!= GL_UNSIGNED_BYTE
611 && type
!= GL_UNSIGNED_SHORT
613 && type
!= GL_UNSIGNED_INT
614 && type
!= GL_FLOAT
) {
615 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(type)");
619 /* Colors or indexes */
620 if (ctx
->Visual
.rgbMode
) {
623 UNCLAMPED_FLOAT_TO_CHAN(r
, ctx
->Current
.RasterColor
[0]);
624 UNCLAMPED_FLOAT_TO_CHAN(g
, ctx
->Current
.RasterColor
[1]);
625 UNCLAMPED_FLOAT_TO_CHAN(b
, ctx
->Current
.RasterColor
[2]);
626 UNCLAMPED_FLOAT_TO_CHAN(a
, ctx
->Current
.RasterColor
[3]);
627 for (i
= 0; i
< drawWidth
; i
++) {
636 for (i
= 0; i
< drawWidth
; i
++) {
637 ispan
[i
] = ctx
->Current
.RasterIndex
;
641 if (type
==GL_UNSIGNED_SHORT
&& sizeof(GLdepth
)==sizeof(GLushort
)
642 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
) {
643 /* Special case: directly write 16-bit depth values */
645 for (row
= 0; row
< height
; row
++, y
++) {
646 GLdepth zspan
[MAX_WIDTH
];
647 const GLushort
*zptr
= (const GLushort
*)
648 _mesa_image_address(&ctx
->Unpack
, pixels
, width
, height
,
649 GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
651 for (i
= 0; i
< width
; i
++)
653 _mesa_write_rgba_span(ctx
, width
, x
, y
, zspan
, 0, rgba
,
657 else if (type
==GL_UNSIGNED_INT
&& ctx
->Visual
.depthBits
== 32
658 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
) {
659 /* Special case: directly write 32-bit depth values */
661 for (row
= 0; row
< height
; row
++, y
++) {
662 const GLuint
*zptr
= (const GLuint
*)
663 _mesa_image_address(&ctx
->Unpack
, pixels
, width
, height
,
664 GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
665 _mesa_write_rgba_span(ctx
, width
, x
, y
, zptr
, 0, rgba
,
672 for (row
= 0; row
< height
; row
++, y
++) {
673 GLfloat fspan
[MAX_WIDTH
];
674 GLdepth zspan
[MAX_WIDTH
];
675 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
,
676 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
677 _mesa_unpack_depth_span( ctx
, drawWidth
, fspan
, type
, src
,
679 /* clamp depth values to [0,1] and convert from floats to integers */
681 const GLfloat zs
= ctx
->DepthMaxF
;
683 for (i
= 0; i
< drawWidth
; i
++) {
684 zspan
[i
] = (GLdepth
) (fspan
[i
] * zs
);
688 if (ctx
->Visual
.rgbMode
) {
690 _mesa_write_zoomed_rgba_span(ctx
, width
, x
, y
, zspan
, 0,
691 (const GLchan (*)[4]) rgba
, desty
);
694 _mesa_write_rgba_span(ctx
, width
, x
, y
, zspan
, 0,
695 rgba
, NULL
, GL_BITMAP
);
700 _mesa_write_zoomed_index_span(ctx
, width
, x
, y
, zspan
, 0,
704 _mesa_write_index_span(ctx
, width
, x
, y
, zspan
, 0,
705 ispan
, NULL
, GL_BITMAP
);
715 * Do glDrawPixels of RGBA pixels.
718 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
719 GLsizei width
, GLsizei height
,
720 GLenum format
, GLenum type
, const GLvoid
*pixels
)
722 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
723 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
724 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
725 const GLint desty
= y
;
726 GLdepth zspan
[MAX_WIDTH
];
727 GLfloat fogSpan
[MAX_WIDTH
];
729 GLfloat
*convImage
= NULL
;
730 GLuint transferOps
= ctx
->_ImageTransferState
;
732 if (!_mesa_is_legal_format_and_type(format
, type
)) {
733 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(format or type)");
737 /* Try an optimized glDrawPixels first */
738 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
))
741 /* Fragment depth values */
742 if (ctx
->Depth
.Test
|| ctx
->Fog
.Enabled
) {
743 /* fill in array of z values */
744 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMaxF
);
748 if (ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORDINATE_EXT
)
749 fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterFogCoord
);
751 fog
= _mesa_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
753 for (i
=0;i
<width
;i
++) {
760 if (SWRAST_CONTEXT(ctx
)->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
761 && x
+ width
<= ctx
->DrawBuffer
->Width
762 && y
+ height
<= ctx
->DrawBuffer
->Height
) {
766 quickDraw
= GL_FALSE
;
769 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
770 /* Convolution has to be handled specially. We'll create an
771 * intermediate image, applying all pixel transfer operations
772 * up to convolution. Then we'll convolve the image. Then
773 * we'll proceed with the rest of the transfer operations and
774 * rasterize the image.
777 GLfloat
*dest
, *tmpImage
;
779 tmpImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
781 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
784 convImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
787 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
791 /* Unpack the image and apply transfer ops up to convolution */
793 for (row
= 0; row
< height
; row
++) {
794 const GLvoid
*source
= _mesa_image_address(unpack
,
795 pixels
, width
, height
, format
, type
, 0, row
, 0);
796 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, (GLfloat
*) dest
,
797 format
, type
, source
, unpack
,
798 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
804 if (ctx
->Pixel
.Convolution2DEnabled
) {
805 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
808 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
809 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
813 /* continue transfer ops and draw the convolved image */
814 unpack
= &_mesa_native_packing
;
818 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
825 GLchan rgba
[MAX_WIDTH
][4];
827 if (width
> MAX_WIDTH
)
829 for (row
= 0; row
< height
; row
++, y
++) {
830 const GLvoid
*source
= _mesa_image_address(unpack
,
831 pixels
, width
, height
, format
, type
, 0, row
, 0);
832 _mesa_unpack_chan_color_span(ctx
, width
, GL_RGBA
, (GLchan
*) rgba
,
833 format
, type
, source
, unpack
,
835 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
836 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
839 if (ctx
->Texture
._ReallyEnabled
&& ctx
->Pixel
.PixelTextureEnabled
) {
840 GLchan primary_rgba
[MAX_WIDTH
][4];
842 DEFARRAY(GLfloat
, s
, MAX_WIDTH
); /* mac 32k limitation */
843 DEFARRAY(GLfloat
, t
, MAX_WIDTH
);
844 DEFARRAY(GLfloat
, r
, MAX_WIDTH
);
845 DEFARRAY(GLfloat
, q
, MAX_WIDTH
);
846 CHECKARRAY(s
, return); /* mac 32k limitation */
847 CHECKARRAY(t
, return);
848 CHECKARRAY(r
, return);
849 CHECKARRAY(q
, return);
851 /* XXX not sure how multitexture is supposed to work here */
852 MEMCPY(primary_rgba
, rgba
, 4 * width
* sizeof(GLchan
));
854 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
855 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
856 _mesa_pixeltexgen(ctx
, width
, (const GLchan (*)[4]) rgba
,
858 _swrast_texture_fragments(ctx
, unit
, width
, s
, t
, r
, NULL
,
859 (CONST
GLchan (*)[4]) primary_rgba
,
863 UNDEFARRAY(s
); /* mac 32k limitation */
870 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, width
, x
, y
,
871 (CONST
GLchan (*)[4]) rgba
, NULL
);
874 _mesa_write_zoomed_rgba_span(ctx
, width
, x
, y
, zspan
, fogSpan
,
875 (CONST
GLchan (*)[4]) rgba
, desty
);
878 _mesa_write_rgba_span(ctx
, (GLuint
) width
, x
, y
, zspan
, fogSpan
,
879 rgba
, NULL
, GL_BITMAP
);
892 * Execute glDrawPixels
895 _swrast_DrawPixels( GLcontext
*ctx
,
897 GLsizei width
, GLsizei height
,
898 GLenum format
, GLenum type
,
899 const struct gl_pixelstore_attrib
*unpack
,
900 const GLvoid
*pixels
)
902 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
906 if (swrast
->NewState
)
907 _swrast_validate_derived( ctx
);
909 RENDER_START(swrast
,ctx
);
912 case GL_STENCIL_INDEX
:
913 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
915 case GL_DEPTH_COMPONENT
:
916 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
919 if (ctx
->Visual
.rgbMode
)
920 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, pixels
);
922 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, pixels
);
929 case GL_LUMINANCE_ALPHA
:
935 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
);
938 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(format)" );
941 RENDER_FINISH(swrast
,ctx
);