1 /* $Id: s_drawpix.c,v 1.41 2002/12/05 04:48:53 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 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.
37 #include "s_context.h"
38 #include "s_drawpix.h"
39 #include "s_pixeltex.h"
41 #include "s_stencil.h"
47 * Given the dest position, size and skipPixels and skipRows values
48 * for a glDrawPixels command, perform clipping of the image bounds
49 * so the result lies withing the context's buffer bounds.
50 * Return: GL_TRUE if image is ready for drawing
51 * GL_FALSE if image was completely clipped away (draw nothing)
54 _mesa_clip_pixelrect(const GLcontext
*ctx
,
55 GLint
*destX
, GLint
*destY
,
56 GLsizei
*width
, GLsizei
*height
,
57 GLint
*skipPixels
, GLint
*skipRows
)
59 const GLframebuffer
*buffer
= ctx
->DrawBuffer
;
62 if (*destX
< buffer
->_Xmin
) {
63 *skipPixels
+= (buffer
->_Xmin
- *destX
);
64 *width
-= (buffer
->_Xmin
- *destX
);
65 *destX
= buffer
->_Xmin
;
68 if (*destX
+ *width
> buffer
->_Xmax
)
69 *width
-= (*destX
+ *width
- buffer
->_Xmax
);
75 if (*destY
< buffer
->_Ymin
) {
76 *skipRows
+= (buffer
->_Ymin
- *destY
);
77 *height
-= (buffer
->_Ymin
- *destY
);
78 *destY
= buffer
->_Ymin
;
81 if (*destY
+ *height
> buffer
->_Ymax
)
82 *height
-= (*destY
+ *height
- buffer
->_Ymax
);
93 * Try to do a fast and simple RGB(a) glDrawPixels.
94 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
97 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
98 GLsizei width
, GLsizei height
,
99 GLenum format
, GLenum type
, const GLvoid
*pixels
)
101 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
102 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
105 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
107 if (!ctx
->Current
.RasterPosValid
) {
108 return GL_TRUE
; /* no-op */
112 _mesa_span_default_z(ctx
, &span
);
113 if (ctx
->Fog
.Enabled
)
114 _mesa_span_default_fog(ctx
, &span
);
115 if (ctx
->Texture
._EnabledUnits
)
116 _mesa_span_default_texcoords(ctx
, &span
);
118 if ((SWRAST_CONTEXT(ctx
)->_RasterMask
& ~CLIP_BIT
) == 0
119 && ctx
->Texture
._EnabledUnits
== 0
120 && unpack
->Alignment
== 1
121 && !unpack
->SwapBytes
122 && !unpack
->LsbFirst
) {
126 GLint drawWidth
= width
; /* actual width drawn */
127 GLint drawHeight
= height
; /* actual height drawn */
128 GLint skipPixels
= unpack
->SkipPixels
;
129 GLint skipRows
= unpack
->SkipRows
;
131 GLdepth zSpan
[MAX_WIDTH
]; /* only used when zooming */
134 if (unpack
->RowLength
> 0)
135 rowLength
= unpack
->RowLength
;
139 /* If we're not using pixel zoom then do all clipping calculations
140 * now. Otherwise, we'll let the _mesa_write_zoomed_*_span() functions
141 * handle the clipping.
143 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
144 /* horizontal clipping */
145 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
146 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
147 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
148 destX
= ctx
->DrawBuffer
->_Xmin
;
150 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
151 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
155 /* vertical clipping */
156 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
157 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
158 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
159 destY
= ctx
->DrawBuffer
->_Ymin
;
161 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
162 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
166 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
167 /* upside-down image */
168 /* horizontal clipping */
169 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
170 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
171 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
172 destX
= ctx
->DrawBuffer
->_Xmin
;
174 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
175 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
179 /* vertical clipping */
180 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
181 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
182 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
183 destY
= ctx
->DrawBuffer
->_Ymax
;
185 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
186 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
191 /* setup array of fragment Z value to pass to zoom function */
192 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMaxF
);
194 if (drawWidth
< MAX_WIDTH
)
195 return GL_FALSE
; /* take the general path solution */
196 for (i
=0; i
<drawWidth
; i
++)
199 /* save Y value of first row */
200 zoomY0
= IROUND(ctx
->Current
.RasterPos
[1]);
206 * The window region at (destX, destY) of size (drawWidth, drawHeight)
207 * will be written to.
208 * We'll take pixel data from buffer pointed to by "pixels" but we'll
209 * skip "skipRows" rows and skip "skipPixels" pixels/row.
212 if (format
== GL_RGBA
&& type
== CHAN_TYPE
213 && ctx
->_ImageTransferState
==0) {
214 if (ctx
->Visual
.rgbMode
) {
215 GLchan
*src
= (GLchan
*) pixels
216 + (skipRows
* rowLength
+ skipPixels
) * 4;
217 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
220 for (row
=0; row
<drawHeight
; row
++) {
221 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
222 (CONST
GLchan (*)[4]) src
, NULL
);
223 src
+= rowLength
* 4;
227 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
230 for (row
=0; row
<drawHeight
; row
++) {
232 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
233 (CONST
GLchan (*)[4]) src
, NULL
);
234 src
+= rowLength
* 4;
240 for (row
=0; row
<drawHeight
; row
++) {
243 span
.end
= drawWidth
;
244 _mesa_write_zoomed_rgba_span(ctx
, &span
,
245 (CONST
GLchan (*)[4]) src
, zoomY0
, 0);
246 src
+= rowLength
* 4;
253 else if (format
== GL_RGB
&& type
== CHAN_TYPE
254 && ctx
->_ImageTransferState
== 0) {
255 if (ctx
->Visual
.rgbMode
) {
256 GLchan
*src
= (GLchan
*) pixels
257 + (skipRows
* rowLength
+ skipPixels
) * 3;
258 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
260 for (row
=0; row
<drawHeight
; row
++) {
261 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
262 (CONST
GLchan (*)[3]) src
, NULL
);
263 src
+= rowLength
* 3;
267 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
270 for (row
=0; row
<drawHeight
; row
++) {
272 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
273 (CONST
GLchan (*)[3]) src
, NULL
);
274 src
+= rowLength
* 3;
280 for (row
=0; row
<drawHeight
; row
++) {
283 span
.end
= drawWidth
;
284 _mesa_write_zoomed_rgb_span(ctx
, &span
,
285 (CONST
GLchan (*)[3]) src
, zoomY0
, 0);
286 src
+= rowLength
* 3;
293 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
294 && ctx
->_ImageTransferState
==0) {
295 if (ctx
->Visual
.rgbMode
) {
296 GLchan
*src
= (GLchan
*) pixels
297 + (skipRows
* rowLength
+ skipPixels
);
298 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
301 ASSERT(drawWidth
< MAX_WIDTH
);
302 for (row
=0; row
<drawHeight
; row
++) {
304 for (i
=0;i
<drawWidth
;i
++) {
305 span
.array
->rgb
[i
][0] = src
[i
];
306 span
.array
->rgb
[i
][1] = src
[i
];
307 span
.array
->rgb
[i
][2] = src
[i
];
309 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
310 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
315 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
318 ASSERT(drawWidth
< MAX_WIDTH
);
319 for (row
=0; row
<drawHeight
; row
++) {
321 for (i
=0;i
<drawWidth
;i
++) {
322 span
.array
->rgb
[i
][0] = src
[i
];
323 span
.array
->rgb
[i
][1] = src
[i
];
324 span
.array
->rgb
[i
][2] = src
[i
];
327 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
328 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
335 ASSERT(drawWidth
< MAX_WIDTH
);
336 for (row
=0; row
<drawHeight
; row
++) {
338 for (i
=0;i
<drawWidth
;i
++) {
339 span
.array
->rgb
[i
][0] = src
[i
];
340 span
.array
->rgb
[i
][1] = src
[i
];
341 span
.array
->rgb
[i
][2] = src
[i
];
345 span
.end
= drawWidth
;
346 _mesa_write_zoomed_rgb_span(ctx
, &span
,
347 (CONST
GLchan (*)[3]) span
.array
->rgb
, zoomY0
, 0);
355 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
356 && ctx
->_ImageTransferState
== 0) {
357 if (ctx
->Visual
.rgbMode
) {
358 GLchan
*src
= (GLchan
*) pixels
359 + (skipRows
* rowLength
+ skipPixels
)*2;
360 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
363 ASSERT(drawWidth
< MAX_WIDTH
);
364 for (row
=0; row
<drawHeight
; row
++) {
367 for (i
=0;i
<drawWidth
;i
++) {
368 span
.array
->rgba
[i
][0] = *ptr
;
369 span
.array
->rgba
[i
][1] = *ptr
;
370 span
.array
->rgba
[i
][2] = *ptr
++;
371 span
.array
->rgba
[i
][3] = *ptr
++;
373 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
374 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
379 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
382 ASSERT(drawWidth
< MAX_WIDTH
);
383 for (row
=0; row
<drawHeight
; row
++) {
386 for (i
=0;i
<drawWidth
;i
++) {
387 span
.array
->rgba
[i
][0] = *ptr
;
388 span
.array
->rgba
[i
][1] = *ptr
;
389 span
.array
->rgba
[i
][2] = *ptr
++;
390 span
.array
->rgba
[i
][3] = *ptr
++;
393 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
394 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
401 ASSERT(drawWidth
< MAX_WIDTH
);
402 for (row
=0; row
<drawHeight
; row
++) {
405 for (i
=0;i
<drawWidth
;i
++) {
406 span
.array
->rgba
[i
][0] = *ptr
;
407 span
.array
->rgba
[i
][1] = *ptr
;
408 span
.array
->rgba
[i
][2] = *ptr
++;
409 span
.array
->rgba
[i
][3] = *ptr
++;
413 span
.end
= drawWidth
;
414 _mesa_write_zoomed_rgba_span(ctx
, &span
,
415 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
, 0);
423 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
424 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
425 if (ctx
->Visual
.rgbMode
) {
426 /* convert CI data to RGBA */
427 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
430 for (row
=0; row
<drawHeight
; row
++) {
431 ASSERT(drawWidth
< MAX_WIDTH
);
432 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
433 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
434 (const GLchan (*)[4]) span
.array
->rgba
, NULL
);
440 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
443 for (row
=0; row
<drawHeight
; row
++) {
444 ASSERT(drawWidth
< MAX_WIDTH
);
445 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
447 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
448 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
456 for (row
=0; row
<drawHeight
; row
++) {
457 ASSERT(drawWidth
< MAX_WIDTH
);
458 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
461 span
.end
= drawWidth
;
462 _mesa_write_zoomed_rgba_span(ctx
, &span
,
463 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
, 0);
470 else if (ctx
->_ImageTransferState
==0) {
471 /* write CI data to CI frame buffer */
473 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
475 for (row
=0; row
<drawHeight
; row
++) {
476 (*swrast
->Driver
.WriteCI8Span
)(ctx
, drawWidth
, destX
, destY
,
490 /* can't handle this pixel format and/or data type here */
495 /* can't do a simple draw, have to use slow path */
502 * Draw color index image.
505 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
506 GLsizei width
, GLsizei height
,
507 GLenum type
, const GLvoid
*pixels
)
509 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
510 GLint row
, skipPixels
;
513 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_INDEX
);
516 _mesa_span_default_z(ctx
, &span
);
517 if (ctx
->Fog
.Enabled
)
518 _mesa_span_default_fog(ctx
, &span
);
524 while (skipPixels
< width
) {
525 span
.x
= x
+ (zoom
? 0 : skipPixels
);
527 span
.end
= (width
- skipPixels
> MAX_WIDTH
)
528 ? MAX_WIDTH
: (width
- skipPixels
);
529 ASSERT(span
.end
<= MAX_WIDTH
);
530 for (row
= 0; row
< height
; row
++, span
.y
++) {
531 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
, pixels
,
533 GL_COLOR_INDEX
, type
,
535 _mesa_unpack_index_span(ctx
, span
.end
, GL_UNSIGNED_INT
,
536 span
.array
->index
, type
, source
, &ctx
->Unpack
,
537 ctx
->_ImageTransferState
);
539 _mesa_write_zoomed_index_span(ctx
, &span
, y
, skipPixels
);
541 _mesa_write_index_span(ctx
, &span
);
543 skipPixels
+= span
.end
;
550 * Draw stencil image.
553 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
554 GLsizei width
, GLsizei height
,
555 GLenum type
, const GLvoid
*pixels
)
557 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
558 const GLint desty
= y
;
559 GLint row
, skipPixels
;
561 if (type
!= GL_BYTE
&&
562 type
!= GL_UNSIGNED_BYTE
&&
564 type
!= GL_UNSIGNED_SHORT
&&
566 type
!= GL_UNSIGNED_INT
&&
569 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(stencil type)");
573 if (ctx
->Visual
.stencilBits
== 0) {
574 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawPixels(no stencil buffer)");
578 /* if width > MAX_WIDTH, have to process image in chunks */
580 while (skipPixels
< width
) {
583 GLint spanWidth
= (width
- skipPixels
> MAX_WIDTH
)
584 ? MAX_WIDTH
: (width
- skipPixels
);
586 for (row
= 0; row
< height
; row
++, spanY
++) {
587 GLstencil values
[MAX_WIDTH
];
588 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
589 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
590 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
, pixels
,
592 GL_COLOR_INDEX
, type
,
594 _mesa_unpack_index_span(ctx
, spanWidth
, destType
, values
,
595 type
, source
, &ctx
->Unpack
,
596 ctx
->_ImageTransferState
);
597 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
598 _mesa_shift_and_offset_stencil(ctx
, spanWidth
, values
);
600 if (ctx
->Pixel
.MapStencilFlag
) {
601 _mesa_map_stencil(ctx
, spanWidth
, values
);
605 _mesa_write_zoomed_stencil_span(ctx
, (GLuint
) spanWidth
,
606 spanX
, spanY
, values
, desty
, 0);
609 _mesa_write_stencil_span(ctx
, (GLuint
) spanWidth
,
610 spanX
, spanY
, values
);
613 skipPixels
+= spanWidth
;
622 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
623 GLsizei width
, GLsizei height
,
624 GLenum type
, const GLvoid
*pixels
)
626 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
627 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
628 const GLint desty
= y
;
631 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_Z
);
634 && type
!= GL_UNSIGNED_BYTE
636 && type
!= GL_UNSIGNED_SHORT
638 && type
!= GL_UNSIGNED_INT
639 && type
!= GL_FLOAT
) {
640 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(type)");
644 _mesa_span_default_color(ctx
, &span
);
646 if (ctx
->Fog
.Enabled
)
647 _mesa_span_default_fog(ctx
, &span
);
648 if (ctx
->Texture
._EnabledUnits
)
649 _mesa_span_default_texcoords(ctx
, &span
);
651 if (type
== GL_UNSIGNED_SHORT
&& ctx
->Visual
.depthBits
== 16
652 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
653 && width
< MAX_WIDTH
) {
654 /* Special case: directly write 16-bit depth values */
659 for (row
= 0; row
< height
; row
++, span
.y
++) {
660 const GLushort
*zptr
= (const GLushort
*)
661 _mesa_image_address(&ctx
->Unpack
, pixels
, width
, height
,
662 GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
664 for (i
= 0; i
< width
; i
++)
665 span
.array
->z
[i
] = zptr
[i
];
666 _mesa_write_rgba_span(ctx
, &span
);
669 else if (type
== GL_UNSIGNED_INT
&& ctx
->Visual
.depthBits
== 32
670 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
671 && width
< MAX_WIDTH
) {
672 /* Special case: directly write 32-bit depth values */
677 for (row
= 0; row
< height
; row
++, span
.y
++) {
678 const GLuint
*zptr
= (const GLuint
*)
679 _mesa_image_address(&ctx
->Unpack
, pixels
, width
, height
,
680 GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
681 MEMCPY(span
.array
->z
, zptr
, width
* sizeof(GLdepth
));
682 _mesa_write_rgba_span(ctx
, &span
);
687 GLint row
, skipPixels
= 0;
689 /* in case width > MAX_WIDTH do the copy in chunks */
690 while (skipPixels
< width
) {
691 span
.x
= x
+ (zoom
? 0 : skipPixels
);
693 span
.end
= (width
- skipPixels
> MAX_WIDTH
)
694 ? MAX_WIDTH
: (width
- skipPixels
);
695 ASSERT(span
.end
<= MAX_WIDTH
);
696 for (row
= 0; row
< height
; row
++, span
.y
++) {
697 GLfloat floatSpan
[MAX_WIDTH
];
698 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
,
699 pixels
, width
, height
,
700 GL_DEPTH_COMPONENT
, type
,
702 _mesa_unpack_depth_span(ctx
, span
.end
, floatSpan
, type
,
704 /* clamp depth values to [0,1] and convert from floats to ints */
706 const GLfloat zs
= ctx
->DepthMaxF
;
708 for (i
= 0; i
< span
.end
; i
++) {
709 span
.array
->z
[i
] = (GLdepth
) (floatSpan
[i
] * zs
+ 0.5F
);
712 if (ctx
->Visual
.rgbMode
) {
714 _mesa_write_zoomed_rgba_span(ctx
, &span
,
715 (const GLchan (*)[4]) span
.array
->rgba
,
719 _mesa_write_rgba_span(ctx
, &span
);
723 _mesa_write_zoomed_index_span(ctx
, &span
, desty
, 0);
725 _mesa_write_index_span(ctx
, &span
);
728 skipPixels
+= span
.end
;
739 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
740 GLsizei width
, GLsizei height
,
741 GLenum format
, GLenum type
, const GLvoid
*pixels
)
743 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
744 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
745 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
746 const GLint desty
= y
;
748 GLfloat
*convImage
= NULL
;
749 GLuint transferOps
= ctx
->_ImageTransferState
;
752 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
754 if (!_mesa_is_legal_format_and_type(format
, type
)) {
755 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(format or type)");
759 /* Try an optimized glDrawPixels first */
760 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
))
764 _mesa_span_default_z(ctx
, &span
);
765 if (ctx
->Fog
.Enabled
)
766 _mesa_span_default_fog(ctx
, &span
);
767 if (ctx
->Texture
._EnabledUnits
)
768 _mesa_span_default_texcoords(ctx
, &span
);
770 if (SWRAST_CONTEXT(ctx
)->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
771 && x
+ width
<= (GLint
) ctx
->DrawBuffer
->Width
772 && y
+ height
<= (GLint
) ctx
->DrawBuffer
->Height
) {
776 quickDraw
= GL_FALSE
;
779 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
780 /* Convolution has to be handled specially. We'll create an
781 * intermediate image, applying all pixel transfer operations
782 * up to convolution. Then we'll convolve the image. Then
783 * we'll proceed with the rest of the transfer operations and
784 * rasterize the image.
787 GLfloat
*dest
, *tmpImage
;
789 tmpImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
791 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
794 convImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
797 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
801 /* Unpack the image and apply transfer ops up to convolution */
803 for (row
= 0; row
< height
; row
++) {
804 const GLvoid
*source
= _mesa_image_address(unpack
,
805 pixels
, width
, height
, format
, type
, 0, row
, 0);
806 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, (GLfloat
*) dest
,
807 format
, type
, source
, unpack
,
808 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
814 if (ctx
->Pixel
.Convolution2DEnabled
) {
815 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
818 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
819 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
823 /* continue transfer ops and draw the convolved image */
824 unpack
= &_mesa_native_packing
;
828 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
835 GLint row
, skipPixels
= 0;
837 /* if the span is wider than MAX_WIDTH we have to do it in chunks */
838 while (skipPixels
< width
) {
839 span
.x
= x
+ (zoom
? 0 : skipPixels
);
841 span
.end
= (width
- skipPixels
> MAX_WIDTH
)
842 ? MAX_WIDTH
: (width
- skipPixels
);
843 ASSERT(span
.end
<= MAX_WIDTH
);
845 for (row
= 0; row
< height
; row
++, span
.y
++) {
846 const GLvoid
*source
= _mesa_image_address(unpack
,
847 pixels
, width
, height
, format
, type
, 0, row
, skipPixels
);
849 _mesa_unpack_chan_color_span(ctx
, span
.end
, GL_RGBA
,
850 (GLchan
*) span
.array
->rgba
,
851 format
, type
, source
, unpack
,
854 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
855 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
858 if (ctx
->Pixel
.PixelTextureEnabled
&& ctx
->Texture
._EnabledUnits
) {
859 _swrast_pixel_texture(ctx
, &span
);
863 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, span
.end
, span
.x
, span
.y
,
864 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
867 _mesa_write_zoomed_rgba_span(ctx
, &span
,
868 (CONST
GLchan (*)[4]) span
.array
->rgba
, desty
, skipPixels
);
871 _mesa_write_rgba_span(ctx
, &span
);
874 skipPixels
+= span
.end
;
886 * Execute glDrawPixels
889 _swrast_DrawPixels( GLcontext
*ctx
,
891 GLsizei width
, GLsizei height
,
892 GLenum format
, GLenum type
,
893 const struct gl_pixelstore_attrib
*unpack
,
894 const GLvoid
*pixels
)
896 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
899 if (swrast
->NewState
)
900 _swrast_validate_derived( ctx
);
902 RENDER_START(swrast
,ctx
);
905 case GL_STENCIL_INDEX
:
906 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
908 case GL_DEPTH_COMPONENT
:
909 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
912 if (ctx
->Visual
.rgbMode
)
913 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, pixels
);
915 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, pixels
);
922 case GL_LUMINANCE_ALPHA
:
928 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
);
931 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(format)" );
934 RENDER_FINISH(swrast
,ctx
);
939 #if 0 /* experimental */
941 * Execute glDrawDepthPixelsMESA().
944 _swrast_DrawDepthPixelsMESA( GLcontext
*ctx
,
946 GLsizei width
, GLsizei height
,
947 GLenum colorFormat
, GLenum colorType
,
948 const GLvoid
*colors
,
949 GLenum depthType
, const GLvoid
*depths
,
950 const struct gl_pixelstore_attrib
*unpack
)
952 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
955 if (swrast
->NewState
)
956 _swrast_validate_derived( ctx
);
958 RENDER_START(swrast
,ctx
);
960 switch (colorFormat
) {
962 if (ctx
->Visual
.rgbMode
)
963 draw_rgba_pixels(ctx
, x
,y
, width
, height
, colorFormat
, colorType
, colors
);
965 draw_index_pixels(ctx
, x
, y
, width
, height
, colorType
, colors
);
972 case GL_LUMINANCE_ALPHA
:
978 draw_rgba_pixels(ctx
, x
, y
, width
, height
, colorFormat
, colorType
, colors
);
981 _mesa_error( ctx
, GL_INVALID_ENUM
,
982 "glDrawDepthPixelsMESA(colorFormat)" );
985 RENDER_FINISH(swrast
,ctx
);