2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 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.
34 #include "s_context.h"
35 #include "s_drawpix.h"
36 #include "s_pixeltex.h"
38 #include "s_stencil.h"
44 * Given the dest position, size and skipPixels and skipRows values
45 * for a glDrawPixels command, perform clipping of the image bounds
46 * so the result lies withing the context's buffer bounds.
47 * Return: GL_TRUE if image is ready for drawing
48 * GL_FALSE if image was completely clipped away (draw nothing)
51 _swrast_clip_pixelrect(const GLcontext
*ctx
,
52 GLint
*destX
, GLint
*destY
,
53 GLsizei
*width
, GLsizei
*height
,
54 GLint
*skipPixels
, GLint
*skipRows
)
56 const GLframebuffer
*buffer
= ctx
->DrawBuffer
;
59 if (*destX
< buffer
->_Xmin
) {
60 *skipPixels
+= (buffer
->_Xmin
- *destX
);
61 *width
-= (buffer
->_Xmin
- *destX
);
62 *destX
= buffer
->_Xmin
;
65 if (*destX
+ *width
> buffer
->_Xmax
)
66 *width
-= (*destX
+ *width
- buffer
->_Xmax
);
72 if (*destY
< buffer
->_Ymin
) {
73 *skipRows
+= (buffer
->_Ymin
- *destY
);
74 *height
-= (buffer
->_Ymin
- *destY
);
75 *destY
= buffer
->_Ymin
;
78 if (*destY
+ *height
> buffer
->_Ymax
)
79 *height
-= (*destY
+ *height
- buffer
->_Ymax
);
90 * Try to do a fast and simple RGB(a) glDrawPixels.
91 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
94 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
95 GLsizei width
, GLsizei height
,
96 GLenum format
, GLenum type
,
97 const struct gl_pixelstore_attrib
*unpack
,
100 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
103 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
105 if (!ctx
->Current
.RasterPosValid
) {
106 return GL_TRUE
; /* no-op */
110 _swrast_span_default_z(ctx
, &span
);
111 if (ctx
->Fog
.Enabled
)
112 _swrast_span_default_fog(ctx
, &span
);
113 if (ctx
->Texture
._EnabledCoordUnits
)
114 _swrast_span_default_texcoords(ctx
, &span
);
116 if ((SWRAST_CONTEXT(ctx
)->_RasterMask
& ~CLIP_BIT
) == 0
117 && ctx
->Texture
._EnabledCoordUnits
== 0
118 && unpack
->Alignment
== 1
119 && !unpack
->SwapBytes
120 && !unpack
->LsbFirst
) {
124 GLint drawWidth
= width
; /* actual width drawn */
125 GLint drawHeight
= height
; /* actual height drawn */
126 GLint skipPixels
= unpack
->SkipPixels
;
127 GLint skipRows
= unpack
->SkipRows
;
131 if (unpack
->RowLength
> 0)
132 rowLength
= unpack
->RowLength
;
136 /* If we're not using pixel zoom then do all clipping calculations
137 * now. Otherwise, we'll let the _swrast_write_zoomed_*_span() functions
138 * handle the clipping.
140 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
141 /* horizontal clipping */
142 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
143 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
144 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
145 destX
= ctx
->DrawBuffer
->_Xmin
;
147 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
148 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
152 /* vertical clipping */
153 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
154 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
155 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
156 destY
= ctx
->DrawBuffer
->_Ymin
;
158 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
159 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
163 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
164 /* upside-down image */
165 /* horizontal clipping */
166 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
167 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
168 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
169 destX
= ctx
->DrawBuffer
->_Xmin
;
171 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
172 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
176 /* vertical clipping */
177 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
178 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
179 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
180 destY
= ctx
->DrawBuffer
->_Ymax
;
182 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
183 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
188 if (drawWidth
> MAX_WIDTH
)
189 return GL_FALSE
; /* fall back to general case path */
191 /* save Y value of first row */
192 zoomY0
= IROUND(ctx
->Current
.RasterPos
[1]);
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 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
214 (CONST
GLchan (*)[4]) src
, NULL
);
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 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
225 (CONST
GLchan (*)[4]) src
, NULL
);
226 src
+= rowLength
* 4;
232 for (row
=0; row
<drawHeight
; row
++) {
235 span
.end
= drawWidth
;
236 _swrast_write_zoomed_rgba_span(ctx
, &span
,
237 (CONST
GLchan (*)[4]) src
, zoomY0
, 0);
238 src
+= rowLength
* 4;
245 else if (format
== GL_RGB
&& type
== CHAN_TYPE
246 && ctx
->_ImageTransferState
== 0) {
247 if (ctx
->Visual
.rgbMode
) {
248 GLchan
*src
= (GLchan
*) pixels
249 + (skipRows
* rowLength
+ skipPixels
) * 3;
250 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
252 for (row
=0; row
<drawHeight
; row
++) {
253 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
254 (CONST
GLchan (*)[3]) src
, NULL
);
255 src
+= rowLength
* 3;
259 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
262 for (row
=0; row
<drawHeight
; row
++) {
264 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
265 (CONST
GLchan (*)[3]) src
, NULL
);
266 src
+= rowLength
* 3;
272 for (row
=0; row
<drawHeight
; row
++) {
275 span
.end
= drawWidth
;
276 _swrast_write_zoomed_rgb_span(ctx
, &span
,
277 (CONST
GLchan (*)[3]) src
, zoomY0
, 0);
278 src
+= rowLength
* 3;
285 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
286 && ctx
->_ImageTransferState
==0) {
287 if (ctx
->Visual
.rgbMode
) {
288 GLchan
*src
= (GLchan
*) pixels
289 + (skipRows
* rowLength
+ skipPixels
);
290 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
293 ASSERT(drawWidth
<= MAX_WIDTH
);
294 for (row
=0; row
<drawHeight
; row
++) {
296 for (i
=0;i
<drawWidth
;i
++) {
297 span
.array
->rgb
[i
][0] = src
[i
];
298 span
.array
->rgb
[i
][1] = src
[i
];
299 span
.array
->rgb
[i
][2] = src
[i
];
301 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
302 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
307 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
310 ASSERT(drawWidth
<= MAX_WIDTH
);
311 for (row
=0; row
<drawHeight
; row
++) {
313 for (i
=0;i
<drawWidth
;i
++) {
314 span
.array
->rgb
[i
][0] = src
[i
];
315 span
.array
->rgb
[i
][1] = src
[i
];
316 span
.array
->rgb
[i
][2] = src
[i
];
319 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
320 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
327 ASSERT(drawWidth
<= MAX_WIDTH
);
328 for (row
=0; row
<drawHeight
; row
++) {
330 for (i
=0;i
<drawWidth
;i
++) {
331 span
.array
->rgb
[i
][0] = src
[i
];
332 span
.array
->rgb
[i
][1] = src
[i
];
333 span
.array
->rgb
[i
][2] = src
[i
];
337 span
.end
= drawWidth
;
338 _swrast_write_zoomed_rgb_span(ctx
, &span
,
339 (CONST
GLchan (*)[3]) span
.array
->rgb
, zoomY0
, 0);
347 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
348 && ctx
->_ImageTransferState
== 0) {
349 if (ctx
->Visual
.rgbMode
) {
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
++) {
360 span
.array
->rgba
[i
][0] = *ptr
;
361 span
.array
->rgba
[i
][1] = *ptr
;
362 span
.array
->rgba
[i
][2] = *ptr
++;
363 span
.array
->rgba
[i
][3] = *ptr
++;
365 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
366 (CONST
GLchan (*)[4]) span
.array
->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
++) {
379 span
.array
->rgba
[i
][0] = *ptr
;
380 span
.array
->rgba
[i
][1] = *ptr
;
381 span
.array
->rgba
[i
][2] = *ptr
++;
382 span
.array
->rgba
[i
][3] = *ptr
++;
385 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
386 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
393 ASSERT(drawWidth
<= MAX_WIDTH
);
394 for (row
=0; row
<drawHeight
; row
++) {
397 for (i
=0;i
<drawWidth
;i
++) {
398 span
.array
->rgba
[i
][0] = *ptr
;
399 span
.array
->rgba
[i
][1] = *ptr
;
400 span
.array
->rgba
[i
][2] = *ptr
++;
401 span
.array
->rgba
[i
][3] = *ptr
++;
405 span
.end
= drawWidth
;
406 _swrast_write_zoomed_rgba_span(ctx
, &span
,
407 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
, 0);
415 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
416 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
417 if (ctx
->Visual
.rgbMode
) {
418 /* convert CI data to RGBA */
419 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
422 for (row
=0; row
<drawHeight
; row
++) {
423 ASSERT(drawWidth
<= MAX_WIDTH
);
424 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
425 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
426 (const GLchan (*)[4]) span
.array
->rgba
, NULL
);
432 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
435 for (row
=0; row
<drawHeight
; row
++) {
436 ASSERT(drawWidth
<= MAX_WIDTH
);
437 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
439 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
440 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
448 for (row
=0; row
<drawHeight
; row
++) {
449 ASSERT(drawWidth
<= MAX_WIDTH
);
450 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
453 span
.end
= drawWidth
;
454 _swrast_write_zoomed_rgba_span(ctx
, &span
,
455 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
, 0);
462 else if (ctx
->_ImageTransferState
==0) {
463 /* write CI data to CI frame buffer */
465 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
467 for (row
=0; row
<drawHeight
; row
++) {
468 (*swrast
->Driver
.WriteCI8Span
)(ctx
, drawWidth
, destX
, destY
,
482 /* can't handle this pixel format and/or data type here */
487 /* can't do a simple draw, have to use slow path */
494 * Draw color index image.
497 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
498 GLsizei width
, GLsizei height
,
500 const struct gl_pixelstore_attrib
*unpack
,
501 const GLvoid
*pixels
)
503 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
504 GLint row
, skipPixels
;
507 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_INDEX
);
510 _swrast_span_default_z(ctx
, &span
);
511 if (ctx
->Fog
.Enabled
)
512 _swrast_span_default_fog(ctx
, &span
);
518 while (skipPixels
< width
) {
519 const GLint spanX
= x
+ (zoom
? 0 : skipPixels
);
521 const GLint spanEnd
= (width
- skipPixels
> MAX_WIDTH
)
522 ? MAX_WIDTH
: (width
- skipPixels
);
523 ASSERT(spanEnd
<= MAX_WIDTH
);
524 for (row
= 0; row
< height
; row
++, spanY
++) {
525 const GLvoid
*source
= _mesa_image_address(unpack
, pixels
,
527 GL_COLOR_INDEX
, type
,
529 _mesa_unpack_index_span(ctx
, spanEnd
, GL_UNSIGNED_INT
,
530 span
.array
->index
, type
, source
, unpack
,
531 ctx
->_ImageTransferState
);
533 /* These may get changed during writing/clipping */
539 _swrast_write_zoomed_index_span(ctx
, &span
, y
, skipPixels
);
541 _swrast_write_index_span(ctx
, &span
);
543 skipPixels
+= spanEnd
;
550 * Draw stencil image.
553 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
554 GLsizei width
, GLsizei height
,
556 const struct gl_pixelstore_attrib
*unpack
,
557 const GLvoid
*pixels
)
559 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
560 const GLint desty
= y
;
561 GLint row
, skipPixels
;
563 if (type
!= GL_BYTE
&&
564 type
!= GL_UNSIGNED_BYTE
&&
566 type
!= GL_UNSIGNED_SHORT
&&
568 type
!= GL_UNSIGNED_INT
&&
571 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(stencil type)");
575 if (ctx
->Visual
.stencilBits
== 0) {
576 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawPixels(no stencil buffer)");
580 /* if width > MAX_WIDTH, have to process image in chunks */
582 while (skipPixels
< width
) {
583 const GLint spanX
= x
;
585 const GLint spanWidth
= (width
- skipPixels
> MAX_WIDTH
)
586 ? MAX_WIDTH
: (width
- skipPixels
);
588 for (row
= 0; row
< height
; row
++, spanY
++) {
589 GLstencil values
[MAX_WIDTH
];
590 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
591 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
592 const GLvoid
*source
= _mesa_image_address(unpack
, pixels
,
594 GL_COLOR_INDEX
, type
,
596 _mesa_unpack_index_span(ctx
, spanWidth
, destType
, values
,
597 type
, source
, unpack
,
598 ctx
->_ImageTransferState
);
599 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
600 _mesa_shift_and_offset_stencil(ctx
, spanWidth
, values
);
602 if (ctx
->Pixel
.MapStencilFlag
) {
603 _mesa_map_stencil(ctx
, spanWidth
, values
);
607 _swrast_write_zoomed_stencil_span(ctx
, (GLuint
) spanWidth
,
608 spanX
, spanY
, values
, desty
, 0);
611 _swrast_write_stencil_span(ctx
, (GLuint
) spanWidth
,
612 spanX
, spanY
, values
);
615 skipPixels
+= spanWidth
;
624 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
625 GLsizei width
, GLsizei height
,
627 const struct gl_pixelstore_attrib
*unpack
,
628 const GLvoid
*pixels
)
630 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
631 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
632 const GLint desty
= y
;
635 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_Z
);
638 && type
!= GL_UNSIGNED_BYTE
640 && type
!= GL_UNSIGNED_SHORT
642 && type
!= GL_UNSIGNED_INT
643 && type
!= GL_FLOAT
) {
644 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(type)");
648 _swrast_span_default_color(ctx
, &span
);
650 if (ctx
->Fog
.Enabled
)
651 _swrast_span_default_fog(ctx
, &span
);
652 if (ctx
->Texture
._EnabledCoordUnits
)
653 _swrast_span_default_texcoords(ctx
, &span
);
655 if (type
== GL_UNSIGNED_SHORT
656 && ctx
->Visual
.depthBits
== 16
659 && ctx
->Visual
.rgbMode
660 && width
<= MAX_WIDTH
) {
661 /* Special case: directly write 16-bit depth values */
662 GLint row
, spanY
= y
;
663 for (row
= 0; row
< height
; row
++, spanY
++) {
664 const GLushort
*zSrc
= (const GLushort
*)
665 _mesa_image_address(unpack
, pixels
, width
, height
,
666 GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
668 for (i
= 0; i
< width
; i
++)
669 span
.array
->z
[i
] = zSrc
[i
];
673 _swrast_write_rgba_span(ctx
, &span
);
676 else if (type
== GL_UNSIGNED_INT
677 && sizeof(GLdepth
) == 4
680 && ctx
->Visual
.rgbMode
681 && width
<= MAX_WIDTH
) {
682 /* Special case: shift 32-bit values down to ctx->Visual.depthBits */
683 const GLint shift
= 32 - ctx
->Visual
.depthBits
;
684 GLint row
, spanY
= y
;
685 for (row
= 0; row
< height
; row
++, spanY
++) {
686 const GLuint
*zSrc
= (const GLuint
*)
687 _mesa_image_address(unpack
, pixels
, width
, height
,
688 GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
690 MEMCPY(span
.array
->z
, zSrc
, width
* sizeof(GLdepth
));
694 for (col
= 0; col
< width
; col
++)
695 span
.array
->z
[col
] = zSrc
[col
] >> shift
;
700 _swrast_write_rgba_span(ctx
, &span
);
705 GLint row
, skipPixels
= 0;
707 /* in case width > MAX_WIDTH do the copy in chunks */
708 while (skipPixels
< width
) {
709 const GLint spanX
= x
+ (zoom
? 0 : skipPixels
);
711 const GLint spanEnd
= (width
- skipPixels
> MAX_WIDTH
)
712 ? MAX_WIDTH
: (width
- skipPixels
);
713 ASSERT(span
.end
<= MAX_WIDTH
);
714 for (row
= 0; row
< height
; row
++, spanY
++) {
715 GLfloat floatSpan
[MAX_WIDTH
];
716 const GLvoid
*zSrc
= _mesa_image_address(unpack
,
717 pixels
, width
, height
,
718 GL_DEPTH_COMPONENT
, type
,
721 /* Set these for each row since the _swrast_write_* function may
722 * change them while clipping.
728 _mesa_unpack_depth_span(ctx
, span
.end
, floatSpan
, type
,
730 /* clamp depth values to [0,1] and convert from floats to ints */
732 const GLfloat zScale
= ctx
->DepthMaxF
;
734 for (i
= 0; i
< span
.end
; i
++) {
735 span
.array
->z
[i
] = (GLdepth
) (floatSpan
[i
] * zScale
);
739 _swrast_write_zoomed_depth_span(ctx
, &span
, desty
, skipPixels
);
741 else if (ctx
->Visual
.rgbMode
) {
742 _swrast_write_rgba_span(ctx
, &span
);
745 _swrast_write_index_span(ctx
, &span
);
748 skipPixels
+= spanEnd
;
759 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
760 GLsizei width
, GLsizei height
,
761 GLenum format
, GLenum type
,
762 const struct gl_pixelstore_attrib
*unpack
,
763 const GLvoid
*pixels
)
765 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
766 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
767 const GLint desty
= y
;
769 GLfloat
*convImage
= NULL
;
770 GLuint transferOps
= ctx
->_ImageTransferState
;
773 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
775 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
776 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(format or type)");
780 /* Try an optimized glDrawPixels first */
781 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
))
785 _swrast_span_default_z(ctx
, &span
);
786 if (ctx
->Fog
.Enabled
)
787 _swrast_span_default_fog(ctx
, &span
);
788 if (ctx
->Texture
._EnabledCoordUnits
)
789 _swrast_span_default_texcoords(ctx
, &span
);
791 if (SWRAST_CONTEXT(ctx
)->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
792 && x
+ width
<= (GLint
) ctx
->DrawBuffer
->Width
793 && y
+ height
<= (GLint
) ctx
->DrawBuffer
->Height
) {
797 quickDraw
= GL_FALSE
;
800 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
801 /* Convolution has to be handled specially. We'll create an
802 * intermediate image, applying all pixel transfer operations
803 * up to convolution. Then we'll convolve the image. Then
804 * we'll proceed with the rest of the transfer operations and
805 * rasterize the image.
808 GLfloat
*dest
, *tmpImage
;
810 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
812 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
815 convImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
817 _mesa_free(tmpImage
);
818 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
822 /* Unpack the image and apply transfer ops up to convolution */
824 for (row
= 0; row
< height
; row
++) {
825 const GLvoid
*source
= _mesa_image_address(unpack
,
826 pixels
, width
, height
, format
, type
, 0, row
, 0);
827 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
, (GLfloat
*) dest
,
828 format
, type
, source
, unpack
,
829 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
);
834 if (ctx
->Pixel
.Convolution2DEnabled
) {
835 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
838 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
839 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
841 _mesa_free(tmpImage
);
843 /* continue transfer ops and draw the convolved image */
844 unpack
= &ctx
->DefaultPacking
;
848 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
855 const GLuint interpMask
= span
.interpMask
;
856 const GLuint arrayMask
= span
.arrayMask
;
857 GLint row
, skipPixels
= 0;
859 /* if the span is wider than MAX_WIDTH we have to do it in chunks */
860 while (skipPixels
< width
) {
861 const GLint spanX
= x
+ (zoom
? 0 : skipPixels
);
863 const GLint spanEnd
= (width
- skipPixels
> MAX_WIDTH
)
864 ? MAX_WIDTH
: (width
- skipPixels
);
865 ASSERT(span
.end
<= MAX_WIDTH
);
867 for (row
= 0; row
< height
; row
++, spanY
++) {
868 const GLvoid
*source
= _mesa_image_address(unpack
,
869 pixels
, width
, height
, format
, type
, 0, row
, skipPixels
);
871 /* Set these for each row since the _swrast_write_* function may
872 * change them while clipping.
877 span
.arrayMask
= arrayMask
;
878 span
.interpMask
= interpMask
;
880 _mesa_unpack_color_span_chan(ctx
, span
.end
, GL_RGBA
,
881 (GLchan
*) span
.array
->rgba
,
882 format
, type
, source
, unpack
,
885 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
886 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
889 if (ctx
->Pixel
.PixelTextureEnabled
&& ctx
->Texture
._EnabledUnits
) {
890 _swrast_pixel_texture(ctx
, &span
);
895 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
.end
, span
.x
, span
.y
,
896 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
899 _swrast_write_zoomed_rgba_span(ctx
, &span
,
900 (CONST
GLchan (*)[4]) span
.array
->rgba
, desty
, skipPixels
);
903 _swrast_write_rgba_span(ctx
, &span
);
907 skipPixels
+= spanEnd
;
912 _mesa_free(convImage
);
919 * Execute glDrawPixels
922 _swrast_DrawPixels( GLcontext
*ctx
,
924 GLsizei width
, GLsizei height
,
925 GLenum format
, GLenum type
,
926 const struct gl_pixelstore_attrib
*unpack
,
927 const GLvoid
*pixels
)
929 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
931 if (swrast
->NewState
)
932 _swrast_validate_derived( ctx
);
934 pixels
= _swrast_validate_pbo_access(unpack
, width
, height
, 1,
935 format
, type
, (GLvoid
*) pixels
);
939 RENDER_START(swrast
,ctx
);
942 case GL_STENCIL_INDEX
:
943 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
945 case GL_DEPTH_COMPONENT
:
946 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
949 if (ctx
->Visual
.rgbMode
)
950 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, unpack
, pixels
);
952 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
959 case GL_LUMINANCE_ALPHA
:
965 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
);
968 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(format)" );
971 RENDER_FINISH(swrast
,ctx
);
976 #if 0 /* experimental */
978 * Execute glDrawDepthPixelsMESA().
981 _swrast_DrawDepthPixelsMESA( GLcontext
*ctx
,
983 GLsizei width
, GLsizei height
,
984 GLenum colorFormat
, GLenum colorType
,
985 const GLvoid
*colors
,
986 GLenum depthType
, const GLvoid
*depths
,
987 const struct gl_pixelstore_attrib
*unpack
)
989 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
991 if (swrast
->NewState
)
992 _swrast_validate_derived( ctx
);
994 RENDER_START(swrast
,ctx
);
996 switch (colorFormat
) {
998 if (ctx
->Visual
.rgbMode
)
999 draw_rgba_pixels(ctx
, x
,y
, width
, height
, colorFormat
, colorType
, unpack
, colors
);
1001 draw_index_pixels(ctx
, x
, y
, width
, height
, colorType
, unpack
, colors
);
1008 case GL_LUMINANCE_ALPHA
:
1014 draw_rgba_pixels(ctx
, x
, y
, width
, height
, colorFormat
, colorType
, unpack
, colors
);
1017 _mesa_error( ctx
, GL_INVALID_ENUM
,
1018 "glDrawDepthPixelsMESA(colorFormat)" );
1021 RENDER_FINISH(swrast
,ctx
);