1 /* $Id: s_drawpix.c,v 1.47 2003/03/25 02:23:45 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2003 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.
36 #include "s_context.h"
37 #include "s_drawpix.h"
38 #include "s_pixeltex.h"
40 #include "s_stencil.h"
46 * Given the dest position, size and skipPixels and skipRows values
47 * for a glDrawPixels command, perform clipping of the image bounds
48 * so the result lies withing the context's buffer bounds.
49 * Return: GL_TRUE if image is ready for drawing
50 * GL_FALSE if image was completely clipped away (draw nothing)
53 _swrast_clip_pixelrect(const GLcontext
*ctx
,
54 GLint
*destX
, GLint
*destY
,
55 GLsizei
*width
, GLsizei
*height
,
56 GLint
*skipPixels
, GLint
*skipRows
)
58 const GLframebuffer
*buffer
= ctx
->DrawBuffer
;
61 if (*destX
< buffer
->_Xmin
) {
62 *skipPixels
+= (buffer
->_Xmin
- *destX
);
63 *width
-= (buffer
->_Xmin
- *destX
);
64 *destX
= buffer
->_Xmin
;
67 if (*destX
+ *width
> buffer
->_Xmax
)
68 *width
-= (*destX
+ *width
- buffer
->_Xmax
);
74 if (*destY
< buffer
->_Ymin
) {
75 *skipRows
+= (buffer
->_Ymin
- *destY
);
76 *height
-= (buffer
->_Ymin
- *destY
);
77 *destY
= buffer
->_Ymin
;
80 if (*destY
+ *height
> buffer
->_Ymax
)
81 *height
-= (*destY
+ *height
- buffer
->_Ymax
);
92 * Try to do a fast and simple RGB(a) glDrawPixels.
93 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
96 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
97 GLsizei width
, GLsizei height
,
98 GLenum format
, GLenum type
, const GLvoid
*pixels
)
100 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
101 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
104 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
106 if (!ctx
->Current
.RasterPosValid
) {
107 return GL_TRUE
; /* no-op */
111 _swrast_span_default_z(ctx
, &span
);
112 if (ctx
->Fog
.Enabled
)
113 _swrast_span_default_fog(ctx
, &span
);
114 if (ctx
->Texture
._EnabledUnits
)
115 _swrast_span_default_texcoords(ctx
, &span
);
117 if ((SWRAST_CONTEXT(ctx
)->_RasterMask
& ~CLIP_BIT
) == 0
118 && ctx
->Texture
._EnabledUnits
== 0
119 && unpack
->Alignment
== 1
120 && !unpack
->SwapBytes
121 && !unpack
->LsbFirst
) {
125 GLint drawWidth
= width
; /* actual width drawn */
126 GLint drawHeight
= height
; /* actual height drawn */
127 GLint skipPixels
= unpack
->SkipPixels
;
128 GLint skipRows
= unpack
->SkipRows
;
130 GLdepth zSpan
[MAX_WIDTH
]; /* only used when zooming */
133 if (unpack
->RowLength
> 0)
134 rowLength
= unpack
->RowLength
;
138 /* If we're not using pixel zoom then do all clipping calculations
139 * now. Otherwise, we'll let the _swrast_write_zoomed_*_span() functions
140 * handle the clipping.
142 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
143 /* horizontal clipping */
144 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
145 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
146 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
147 destX
= ctx
->DrawBuffer
->_Xmin
;
149 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
150 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
154 /* vertical clipping */
155 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
156 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
157 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
158 destY
= ctx
->DrawBuffer
->_Ymin
;
160 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
161 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
165 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
166 /* upside-down image */
167 /* horizontal clipping */
168 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
169 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
170 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
171 destX
= ctx
->DrawBuffer
->_Xmin
;
173 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
174 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
178 /* vertical clipping */
179 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
180 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
181 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
182 destY
= ctx
->DrawBuffer
->_Ymax
;
184 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
185 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
190 /* setup array of fragment Z value to pass to zoom function */
191 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMaxF
);
193 if (drawWidth
> MAX_WIDTH
)
194 return GL_FALSE
; /* fall back to general case path */
195 for (i
=0; i
<drawWidth
; i
++)
198 /* save Y value of first row */
199 zoomY0
= IROUND(ctx
->Current
.RasterPos
[1]);
205 * The window region at (destX, destY) of size (drawWidth, drawHeight)
206 * will be written to.
207 * We'll take pixel data from buffer pointed to by "pixels" but we'll
208 * skip "skipRows" rows and skip "skipPixels" pixels/row.
211 if (format
== GL_RGBA
&& type
== CHAN_TYPE
212 && ctx
->_ImageTransferState
==0) {
213 if (ctx
->Visual
.rgbMode
) {
214 GLchan
*src
= (GLchan
*) pixels
215 + (skipRows
* rowLength
+ skipPixels
) * 4;
216 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
219 for (row
=0; row
<drawHeight
; row
++) {
220 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
221 (CONST
GLchan (*)[4]) src
, NULL
);
222 src
+= rowLength
* 4;
226 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
229 for (row
=0; row
<drawHeight
; row
++) {
231 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
232 (CONST
GLchan (*)[4]) src
, NULL
);
233 src
+= rowLength
* 4;
239 for (row
=0; row
<drawHeight
; row
++) {
242 span
.end
= drawWidth
;
243 _swrast_write_zoomed_rgba_span(ctx
, &span
,
244 (CONST
GLchan (*)[4]) src
, zoomY0
, 0);
245 src
+= rowLength
* 4;
252 else if (format
== GL_RGB
&& type
== CHAN_TYPE
253 && ctx
->_ImageTransferState
== 0) {
254 if (ctx
->Visual
.rgbMode
) {
255 GLchan
*src
= (GLchan
*) pixels
256 + (skipRows
* rowLength
+ skipPixels
) * 3;
257 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
259 for (row
=0; row
<drawHeight
; row
++) {
260 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
261 (CONST
GLchan (*)[3]) src
, NULL
);
262 src
+= rowLength
* 3;
266 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
269 for (row
=0; row
<drawHeight
; row
++) {
271 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
272 (CONST
GLchan (*)[3]) src
, NULL
);
273 src
+= rowLength
* 3;
279 for (row
=0; row
<drawHeight
; row
++) {
282 span
.end
= drawWidth
;
283 _swrast_write_zoomed_rgb_span(ctx
, &span
,
284 (CONST
GLchan (*)[3]) src
, zoomY0
, 0);
285 src
+= rowLength
* 3;
292 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
293 && ctx
->_ImageTransferState
==0) {
294 if (ctx
->Visual
.rgbMode
) {
295 GLchan
*src
= (GLchan
*) pixels
296 + (skipRows
* rowLength
+ skipPixels
);
297 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
300 ASSERT(drawWidth
< MAX_WIDTH
);
301 for (row
=0; row
<drawHeight
; row
++) {
303 for (i
=0;i
<drawWidth
;i
++) {
304 span
.array
->rgb
[i
][0] = src
[i
];
305 span
.array
->rgb
[i
][1] = src
[i
];
306 span
.array
->rgb
[i
][2] = src
[i
];
308 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
309 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
314 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
317 ASSERT(drawWidth
< MAX_WIDTH
);
318 for (row
=0; row
<drawHeight
; row
++) {
320 for (i
=0;i
<drawWidth
;i
++) {
321 span
.array
->rgb
[i
][0] = src
[i
];
322 span
.array
->rgb
[i
][1] = src
[i
];
323 span
.array
->rgb
[i
][2] = src
[i
];
326 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
327 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
334 ASSERT(drawWidth
< MAX_WIDTH
);
335 for (row
=0; row
<drawHeight
; row
++) {
337 for (i
=0;i
<drawWidth
;i
++) {
338 span
.array
->rgb
[i
][0] = src
[i
];
339 span
.array
->rgb
[i
][1] = src
[i
];
340 span
.array
->rgb
[i
][2] = src
[i
];
344 span
.end
= drawWidth
;
345 _swrast_write_zoomed_rgb_span(ctx
, &span
,
346 (CONST
GLchan (*)[3]) span
.array
->rgb
, zoomY0
, 0);
354 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
355 && ctx
->_ImageTransferState
== 0) {
356 if (ctx
->Visual
.rgbMode
) {
357 GLchan
*src
= (GLchan
*) pixels
358 + (skipRows
* rowLength
+ skipPixels
)*2;
359 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
362 ASSERT(drawWidth
< MAX_WIDTH
);
363 for (row
=0; row
<drawHeight
; row
++) {
366 for (i
=0;i
<drawWidth
;i
++) {
367 span
.array
->rgba
[i
][0] = *ptr
;
368 span
.array
->rgba
[i
][1] = *ptr
;
369 span
.array
->rgba
[i
][2] = *ptr
++;
370 span
.array
->rgba
[i
][3] = *ptr
++;
372 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
373 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
378 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
381 ASSERT(drawWidth
< MAX_WIDTH
);
382 for (row
=0; row
<drawHeight
; row
++) {
385 for (i
=0;i
<drawWidth
;i
++) {
386 span
.array
->rgba
[i
][0] = *ptr
;
387 span
.array
->rgba
[i
][1] = *ptr
;
388 span
.array
->rgba
[i
][2] = *ptr
++;
389 span
.array
->rgba
[i
][3] = *ptr
++;
392 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
393 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
400 ASSERT(drawWidth
< MAX_WIDTH
);
401 for (row
=0; row
<drawHeight
; row
++) {
404 for (i
=0;i
<drawWidth
;i
++) {
405 span
.array
->rgba
[i
][0] = *ptr
;
406 span
.array
->rgba
[i
][1] = *ptr
;
407 span
.array
->rgba
[i
][2] = *ptr
++;
408 span
.array
->rgba
[i
][3] = *ptr
++;
412 span
.end
= drawWidth
;
413 _swrast_write_zoomed_rgba_span(ctx
, &span
,
414 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
, 0);
422 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
423 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
424 if (ctx
->Visual
.rgbMode
) {
425 /* convert CI data to RGBA */
426 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
429 for (row
=0; row
<drawHeight
; row
++) {
430 ASSERT(drawWidth
< MAX_WIDTH
);
431 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
432 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
433 (const GLchan (*)[4]) span
.array
->rgba
, NULL
);
439 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
442 for (row
=0; row
<drawHeight
; row
++) {
443 ASSERT(drawWidth
< MAX_WIDTH
);
444 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
446 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
447 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
455 for (row
=0; row
<drawHeight
; row
++) {
456 ASSERT(drawWidth
< MAX_WIDTH
);
457 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
460 span
.end
= drawWidth
;
461 _swrast_write_zoomed_rgba_span(ctx
, &span
,
462 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
, 0);
469 else if (ctx
->_ImageTransferState
==0) {
470 /* write CI data to CI frame buffer */
472 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
474 for (row
=0; row
<drawHeight
; row
++) {
475 (*swrast
->Driver
.WriteCI8Span
)(ctx
, drawWidth
, destX
, destY
,
489 /* can't handle this pixel format and/or data type here */
494 /* can't do a simple draw, have to use slow path */
501 * Draw color index image.
504 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
505 GLsizei width
, GLsizei height
,
506 GLenum type
, const GLvoid
*pixels
)
508 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
509 GLint row
, skipPixels
;
512 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_INDEX
);
515 _swrast_span_default_z(ctx
, &span
);
516 if (ctx
->Fog
.Enabled
)
517 _swrast_span_default_fog(ctx
, &span
);
523 while (skipPixels
< width
) {
524 const GLint spanX
= x
+ (zoom
? 0 : skipPixels
);
526 const GLint spanEnd
= (width
- skipPixels
> MAX_WIDTH
)
527 ? MAX_WIDTH
: (width
- skipPixels
);
528 ASSERT(spanEnd
<= MAX_WIDTH
);
529 for (row
= 0; row
< height
; row
++, span
.y
++) {
530 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
, pixels
,
532 GL_COLOR_INDEX
, type
,
534 _mesa_unpack_index_span(ctx
, span
.end
, GL_UNSIGNED_INT
,
535 span
.array
->index
, type
, source
, &ctx
->Unpack
,
536 ctx
->_ImageTransferState
);
538 /* These may get changed during writing/clipping */
544 _swrast_write_zoomed_index_span(ctx
, &span
, y
, skipPixels
);
546 _swrast_write_index_span(ctx
, &span
);
548 skipPixels
+= spanEnd
;
555 * Draw stencil image.
558 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
559 GLsizei width
, GLsizei height
,
560 GLenum type
, const GLvoid
*pixels
)
562 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
563 const GLint desty
= y
;
564 GLint row
, skipPixels
;
566 if (type
!= GL_BYTE
&&
567 type
!= GL_UNSIGNED_BYTE
&&
569 type
!= GL_UNSIGNED_SHORT
&&
571 type
!= GL_UNSIGNED_INT
&&
574 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(stencil type)");
578 if (ctx
->Visual
.stencilBits
== 0) {
579 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawPixels(no stencil buffer)");
583 /* if width > MAX_WIDTH, have to process image in chunks */
585 while (skipPixels
< width
) {
586 const GLint spanX
= x
;
588 const GLint spanWidth
= (width
- skipPixels
> MAX_WIDTH
)
589 ? MAX_WIDTH
: (width
- skipPixels
);
591 for (row
= 0; row
< height
; row
++, spanY
++) {
592 GLstencil values
[MAX_WIDTH
];
593 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
594 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
595 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
, pixels
,
597 GL_COLOR_INDEX
, type
,
599 _mesa_unpack_index_span(ctx
, spanWidth
, destType
, values
,
600 type
, source
, &ctx
->Unpack
,
601 ctx
->_ImageTransferState
);
602 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
603 _mesa_shift_and_offset_stencil(ctx
, spanWidth
, values
);
605 if (ctx
->Pixel
.MapStencilFlag
) {
606 _mesa_map_stencil(ctx
, spanWidth
, values
);
610 _swrast_write_zoomed_stencil_span(ctx
, (GLuint
) spanWidth
,
611 spanX
, spanY
, values
, desty
, 0);
614 _swrast_write_stencil_span(ctx
, (GLuint
) spanWidth
,
615 spanX
, spanY
, values
);
618 skipPixels
+= spanWidth
;
627 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
628 GLsizei width
, GLsizei height
,
629 GLenum type
, const GLvoid
*pixels
)
631 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
632 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
633 const GLint desty
= y
;
636 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_Z
);
639 && type
!= GL_UNSIGNED_BYTE
641 && type
!= GL_UNSIGNED_SHORT
643 && type
!= GL_UNSIGNED_INT
644 && type
!= GL_FLOAT
) {
645 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(type)");
649 _swrast_span_default_color(ctx
, &span
);
651 if (ctx
->Fog
.Enabled
)
652 _swrast_span_default_fog(ctx
, &span
);
653 if (ctx
->Texture
._EnabledUnits
)
654 _swrast_span_default_texcoords(ctx
, &span
);
656 if (type
== GL_UNSIGNED_SHORT
&& ctx
->Visual
.depthBits
== 16
657 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
658 && width
< MAX_WIDTH
) {
659 /* Special case: directly write 16-bit depth values */
664 for (row
= 0; row
< height
; row
++, span
.y
++) {
665 const GLushort
*zptr
= (const GLushort
*)
666 _mesa_image_address(&ctx
->Unpack
, pixels
, width
, height
,
667 GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
669 for (i
= 0; i
< width
; i
++)
670 span
.array
->z
[i
] = zptr
[i
];
671 _swrast_write_rgba_span(ctx
, &span
);
674 else if (type
== GL_UNSIGNED_INT
&& ctx
->Visual
.depthBits
== 32
675 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
676 && width
< MAX_WIDTH
) {
677 /* Special case: directly write 32-bit depth values */
682 for (row
= 0; row
< height
; row
++, span
.y
++) {
683 const GLuint
*zptr
= (const GLuint
*)
684 _mesa_image_address(&ctx
->Unpack
, pixels
, width
, height
,
685 GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
686 MEMCPY(span
.array
->z
, zptr
, width
* sizeof(GLdepth
));
687 _swrast_write_rgba_span(ctx
, &span
);
692 GLint row
, skipPixels
= 0;
694 /* in case width > MAX_WIDTH do the copy in chunks */
695 while (skipPixels
< width
) {
696 const GLint spanX
= x
+ (zoom
? 0 : skipPixels
);
698 const GLint spanEnd
= (width
- skipPixels
> MAX_WIDTH
)
699 ? MAX_WIDTH
: (width
- skipPixels
);
700 ASSERT(span
.end
<= MAX_WIDTH
);
701 for (row
= 0; row
< height
; row
++, spanY
++) {
702 GLfloat floatSpan
[MAX_WIDTH
];
703 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
,
704 pixels
, width
, height
,
705 GL_DEPTH_COMPONENT
, type
,
708 /* Set these for each row since the _swrast_write_* function may
709 * change them while clipping.
715 _mesa_unpack_depth_span(ctx
, span
.end
, floatSpan
, type
,
717 /* clamp depth values to [0,1] and convert from floats to ints */
719 const GLfloat zs
= ctx
->DepthMaxF
;
721 for (i
= 0; i
< span
.end
; i
++) {
722 span
.array
->z
[i
] = (GLdepth
) (floatSpan
[i
] * zs
+ 0.5F
);
725 if (ctx
->Visual
.rgbMode
) {
727 _swrast_write_zoomed_rgba_span(ctx
, &span
,
728 (const GLchan (*)[4]) span
.array
->rgba
,
732 _swrast_write_rgba_span(ctx
, &span
);
736 _swrast_write_zoomed_index_span(ctx
, &span
, desty
, 0);
738 _swrast_write_index_span(ctx
, &span
);
741 skipPixels
+= spanEnd
;
752 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
753 GLsizei width
, GLsizei height
,
754 GLenum format
, GLenum type
, const GLvoid
*pixels
)
756 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
757 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
758 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
759 const GLint desty
= y
;
761 GLfloat
*convImage
= NULL
;
762 GLuint transferOps
= ctx
->_ImageTransferState
;
765 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
767 if (!_mesa_is_legal_format_and_type(format
, type
)) {
768 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(format or type)");
772 /* Try an optimized glDrawPixels first */
773 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
))
777 _swrast_span_default_z(ctx
, &span
);
778 if (ctx
->Fog
.Enabled
)
779 _swrast_span_default_fog(ctx
, &span
);
780 if (ctx
->Texture
._EnabledUnits
)
781 _swrast_span_default_texcoords(ctx
, &span
);
783 if (SWRAST_CONTEXT(ctx
)->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
784 && x
+ width
<= (GLint
) ctx
->DrawBuffer
->Width
785 && y
+ height
<= (GLint
) ctx
->DrawBuffer
->Height
) {
789 quickDraw
= GL_FALSE
;
792 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
793 /* Convolution has to be handled specially. We'll create an
794 * intermediate image, applying all pixel transfer operations
795 * up to convolution. Then we'll convolve the image. Then
796 * we'll proceed with the rest of the transfer operations and
797 * rasterize the image.
800 GLfloat
*dest
, *tmpImage
;
802 tmpImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
804 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
807 convImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
810 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
814 /* Unpack the image and apply transfer ops up to convolution */
816 for (row
= 0; row
< height
; row
++) {
817 const GLvoid
*source
= _mesa_image_address(unpack
,
818 pixels
, width
, height
, format
, type
, 0, row
, 0);
819 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, (GLfloat
*) dest
,
820 format
, type
, source
, unpack
,
821 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
827 if (ctx
->Pixel
.Convolution2DEnabled
) {
828 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
831 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
832 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
836 /* continue transfer ops and draw the convolved image */
837 unpack
= &_mesa_native_packing
;
841 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
848 const GLuint interpMask
= span
.interpMask
;
849 const GLuint arrayMask
= span
.arrayMask
;
850 GLint row
, skipPixels
= 0;
852 /* if the span is wider than MAX_WIDTH we have to do it in chunks */
853 while (skipPixels
< width
) {
854 const GLint spanX
= x
+ (zoom
? 0 : skipPixels
);
856 const GLint spanEnd
= (width
- skipPixels
> MAX_WIDTH
)
857 ? MAX_WIDTH
: (width
- skipPixels
);
858 ASSERT(span
.end
<= MAX_WIDTH
);
860 for (row
= 0; row
< height
; row
++, spanY
++) {
861 const GLvoid
*source
= _mesa_image_address(unpack
,
862 pixels
, width
, height
, format
, type
, 0, row
, skipPixels
);
864 /* Set these for each row since the _swrast_write_* function may
865 * change them while clipping.
870 span
.arrayMask
= arrayMask
;
871 span
.interpMask
= interpMask
;
873 _mesa_unpack_chan_color_span(ctx
, span
.end
, GL_RGBA
,
874 (GLchan
*) span
.array
->rgba
,
875 format
, type
, source
, unpack
,
878 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
879 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
882 if (ctx
->Pixel
.PixelTextureEnabled
&& ctx
->Texture
._EnabledUnits
) {
883 _swrast_pixel_texture(ctx
, &span
);
888 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
.end
, span
.x
, span
.y
,
889 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
892 _swrast_write_zoomed_rgba_span(ctx
, &span
,
893 (CONST
GLchan (*)[4]) span
.array
->rgba
, desty
, skipPixels
);
896 _swrast_write_rgba_span(ctx
, &span
);
900 skipPixels
+= spanEnd
;
912 * Execute glDrawPixels
915 _swrast_DrawPixels( GLcontext
*ctx
,
917 GLsizei width
, GLsizei height
,
918 GLenum format
, GLenum type
,
919 const struct gl_pixelstore_attrib
*unpack
,
920 const GLvoid
*pixels
)
922 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
925 if (swrast
->NewState
)
926 _swrast_validate_derived( ctx
);
928 RENDER_START(swrast
,ctx
);
931 case GL_STENCIL_INDEX
:
932 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
934 case GL_DEPTH_COMPONENT
:
935 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
938 if (ctx
->Visual
.rgbMode
)
939 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, pixels
);
941 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, pixels
);
948 case GL_LUMINANCE_ALPHA
:
954 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
);
957 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(format)" );
960 RENDER_FINISH(swrast
,ctx
);
965 #if 0 /* experimental */
967 * Execute glDrawDepthPixelsMESA().
970 _swrast_DrawDepthPixelsMESA( GLcontext
*ctx
,
972 GLsizei width
, GLsizei height
,
973 GLenum colorFormat
, GLenum colorType
,
974 const GLvoid
*colors
,
975 GLenum depthType
, const GLvoid
*depths
,
976 const struct gl_pixelstore_attrib
*unpack
)
978 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
981 if (swrast
->NewState
)
982 _swrast_validate_derived( ctx
);
984 RENDER_START(swrast
,ctx
);
986 switch (colorFormat
) {
988 if (ctx
->Visual
.rgbMode
)
989 draw_rgba_pixels(ctx
, x
,y
, width
, height
, colorFormat
, colorType
, colors
);
991 draw_index_pixels(ctx
, x
, y
, width
, height
, colorType
, colors
);
998 case GL_LUMINANCE_ALPHA
:
1004 draw_rgba_pixels(ctx
, x
, y
, width
, height
, colorFormat
, colorType
, colors
);
1007 _mesa_error( ctx
, GL_INVALID_ENUM
,
1008 "glDrawDepthPixelsMESA(colorFormat)" );
1011 RENDER_FINISH(swrast
,ctx
);