1 /* $Id: s_drawpix.c,v 1.40 2002/11/25 20:26:59 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.
38 #include "s_context.h"
39 #include "s_drawpix.h"
40 #include "s_pixeltex.h"
42 #include "s_stencil.h"
43 #include "s_texture.h"
49 * Given the dest position, size and skipPixels and skipRows values
50 * for a glDrawPixels command, perform clipping of the image bounds
51 * so the result lies withing the context's buffer bounds.
52 * Return: GL_TRUE if image is ready for drawing
53 * GL_FALSE if image was completely clipped away (draw nothing)
56 _mesa_clip_pixelrect(const GLcontext
*ctx
,
57 GLint
*destX
, GLint
*destY
,
58 GLsizei
*width
, GLsizei
*height
,
59 GLint
*skipPixels
, GLint
*skipRows
)
61 const GLframebuffer
*buffer
= ctx
->DrawBuffer
;
64 if (*destX
< buffer
->_Xmin
) {
65 *skipPixels
+= (buffer
->_Xmin
- *destX
);
66 *width
-= (buffer
->_Xmin
- *destX
);
67 *destX
= buffer
->_Xmin
;
70 if (*destX
+ *width
> buffer
->_Xmax
)
71 *width
-= (*destX
+ *width
- buffer
->_Xmax
);
77 if (*destY
< buffer
->_Ymin
) {
78 *skipRows
+= (buffer
->_Ymin
- *destY
);
79 *height
-= (buffer
->_Ymin
- *destY
);
80 *destY
= buffer
->_Ymin
;
83 if (*destY
+ *height
> buffer
->_Ymax
)
84 *height
-= (*destY
+ *height
- buffer
->_Ymax
);
95 * Try to do a fast and simple RGB(a) glDrawPixels.
96 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
99 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
100 GLsizei width
, GLsizei height
,
101 GLenum format
, GLenum type
, const GLvoid
*pixels
)
103 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
104 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
107 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
109 if (!ctx
->Current
.RasterPosValid
) {
110 return GL_TRUE
; /* no-op */
114 _mesa_span_default_z(ctx
, &span
);
115 if (ctx
->Fog
.Enabled
)
116 _mesa_span_default_fog(ctx
, &span
);
117 if (ctx
->Texture
._EnabledUnits
)
118 _mesa_span_default_texcoords(ctx
, &span
);
120 if ((SWRAST_CONTEXT(ctx
)->_RasterMask
& ~CLIP_BIT
) == 0
121 && ctx
->Texture
._EnabledUnits
== 0
122 && unpack
->Alignment
== 1
123 && !unpack
->SwapBytes
124 && !unpack
->LsbFirst
) {
128 GLint drawWidth
= width
; /* actual width drawn */
129 GLint drawHeight
= height
; /* actual height drawn */
130 GLint skipPixels
= unpack
->SkipPixels
;
131 GLint skipRows
= unpack
->SkipRows
;
133 GLdepth zSpan
[MAX_WIDTH
]; /* only used when zooming */
136 if (unpack
->RowLength
> 0)
137 rowLength
= unpack
->RowLength
;
141 /* If we're not using pixel zoom then do all clipping calculations
142 * now. Otherwise, we'll let the _mesa_write_zoomed_*_span() functions
143 * handle the clipping.
145 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
146 /* horizontal clipping */
147 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
148 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
149 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
150 destX
= ctx
->DrawBuffer
->_Xmin
;
152 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
153 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
157 /* vertical clipping */
158 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
159 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
160 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
161 destY
= ctx
->DrawBuffer
->_Ymin
;
163 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
164 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
168 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
169 /* upside-down image */
170 /* horizontal clipping */
171 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
172 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
173 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
174 destX
= ctx
->DrawBuffer
->_Xmin
;
176 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
177 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
181 /* vertical clipping */
182 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
183 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
184 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
185 destY
= ctx
->DrawBuffer
->_Ymax
;
187 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
188 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
193 /* setup array of fragment Z value to pass to zoom function */
194 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->DepthMaxF
);
196 ASSERT(drawWidth
< MAX_WIDTH
);
197 for (i
=0; i
<drawWidth
; i
++)
200 /* save Y value of first row */
201 zoomY0
= IROUND(ctx
->Current
.RasterPos
[1]);
207 * The window region at (destX, destY) of size (drawWidth, drawHeight)
208 * will be written to.
209 * We'll take pixel data from buffer pointed to by "pixels" but we'll
210 * skip "skipRows" rows and skip "skipPixels" pixels/row.
213 if (format
== GL_RGBA
&& type
== CHAN_TYPE
214 && ctx
->_ImageTransferState
==0) {
215 if (ctx
->Visual
.rgbMode
) {
216 GLchan
*src
= (GLchan
*) pixels
217 + (skipRows
* rowLength
+ skipPixels
) * 4;
218 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
221 for (row
=0; row
<drawHeight
; row
++) {
222 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
223 (CONST
GLchan (*)[4]) src
, NULL
);
224 src
+= rowLength
* 4;
228 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
231 for (row
=0; row
<drawHeight
; row
++) {
233 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
234 (CONST
GLchan (*)[4]) src
, NULL
);
235 src
+= rowLength
* 4;
241 for (row
=0; row
<drawHeight
; row
++) {
244 span
.end
= drawWidth
;
245 _mesa_write_zoomed_rgba_span(ctx
, &span
,
246 (CONST
GLchan (*)[4]) src
, zoomY0
);
247 src
+= rowLength
* 4;
254 else if (format
== GL_RGB
&& type
== CHAN_TYPE
255 && ctx
->_ImageTransferState
== 0) {
256 if (ctx
->Visual
.rgbMode
) {
257 GLchan
*src
= (GLchan
*) pixels
258 + (skipRows
* rowLength
+ skipPixels
) * 3;
259 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
261 for (row
=0; row
<drawHeight
; row
++) {
262 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
263 (CONST
GLchan (*)[3]) src
, NULL
);
264 src
+= rowLength
* 3;
268 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
271 for (row
=0; row
<drawHeight
; row
++) {
273 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
274 (CONST
GLchan (*)[3]) src
, NULL
);
275 src
+= rowLength
* 3;
281 for (row
=0; row
<drawHeight
; row
++) {
284 span
.end
= drawWidth
;
285 _mesa_write_zoomed_rgb_span(ctx
, &span
,
286 (CONST
GLchan (*)[3]) src
, zoomY0
);
287 src
+= rowLength
* 3;
294 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
295 && ctx
->_ImageTransferState
==0) {
296 if (ctx
->Visual
.rgbMode
) {
297 GLchan
*src
= (GLchan
*) pixels
298 + (skipRows
* rowLength
+ skipPixels
);
299 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
302 ASSERT(drawWidth
< MAX_WIDTH
);
303 for (row
=0; row
<drawHeight
; row
++) {
305 for (i
=0;i
<drawWidth
;i
++) {
306 span
.array
->rgb
[i
][0] = src
[i
];
307 span
.array
->rgb
[i
][1] = src
[i
];
308 span
.array
->rgb
[i
][2] = src
[i
];
310 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
311 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
316 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
319 ASSERT(drawWidth
< MAX_WIDTH
);
320 for (row
=0; row
<drawHeight
; row
++) {
322 for (i
=0;i
<drawWidth
;i
++) {
323 span
.array
->rgb
[i
][0] = src
[i
];
324 span
.array
->rgb
[i
][1] = src
[i
];
325 span
.array
->rgb
[i
][2] = src
[i
];
328 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
329 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
336 ASSERT(drawWidth
< MAX_WIDTH
);
337 for (row
=0; row
<drawHeight
; row
++) {
339 for (i
=0;i
<drawWidth
;i
++) {
340 span
.array
->rgb
[i
][0] = src
[i
];
341 span
.array
->rgb
[i
][1] = src
[i
];
342 span
.array
->rgb
[i
][2] = src
[i
];
346 span
.end
= drawWidth
;
347 _mesa_write_zoomed_rgb_span(ctx
, &span
,
348 (CONST
GLchan (*)[3]) span
.array
->rgb
, zoomY0
);
356 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
357 && ctx
->_ImageTransferState
== 0) {
358 if (ctx
->Visual
.rgbMode
) {
359 GLchan
*src
= (GLchan
*) pixels
360 + (skipRows
* rowLength
+ skipPixels
)*2;
361 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
364 ASSERT(drawWidth
< MAX_WIDTH
);
365 for (row
=0; row
<drawHeight
; row
++) {
368 for (i
=0;i
<drawWidth
;i
++) {
369 span
.array
->rgba
[i
][0] = *ptr
;
370 span
.array
->rgba
[i
][1] = *ptr
;
371 span
.array
->rgba
[i
][2] = *ptr
++;
372 span
.array
->rgba
[i
][3] = *ptr
++;
374 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
375 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
380 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
383 ASSERT(drawWidth
< MAX_WIDTH
);
384 for (row
=0; row
<drawHeight
; row
++) {
387 for (i
=0;i
<drawWidth
;i
++) {
388 span
.array
->rgba
[i
][0] = *ptr
;
389 span
.array
->rgba
[i
][1] = *ptr
;
390 span
.array
->rgba
[i
][2] = *ptr
++;
391 span
.array
->rgba
[i
][3] = *ptr
++;
394 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
395 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
402 ASSERT(drawWidth
< MAX_WIDTH
);
403 for (row
=0; row
<drawHeight
; row
++) {
406 for (i
=0;i
<drawWidth
;i
++) {
407 span
.array
->rgba
[i
][0] = *ptr
;
408 span
.array
->rgba
[i
][1] = *ptr
;
409 span
.array
->rgba
[i
][2] = *ptr
++;
410 span
.array
->rgba
[i
][3] = *ptr
++;
414 span
.end
= drawWidth
;
415 _mesa_write_zoomed_rgba_span(ctx
, &span
,
416 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
);
424 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
425 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
426 if (ctx
->Visual
.rgbMode
) {
427 /* convert CI data to RGBA */
428 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
431 for (row
=0; row
<drawHeight
; row
++) {
432 ASSERT(drawWidth
< MAX_WIDTH
);
433 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
434 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
435 (const GLchan (*)[4]) span
.array
->rgba
, NULL
);
441 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
444 for (row
=0; row
<drawHeight
; row
++) {
445 ASSERT(drawWidth
< MAX_WIDTH
);
446 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
448 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
449 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
457 for (row
=0; row
<drawHeight
; row
++) {
458 ASSERT(drawWidth
< MAX_WIDTH
);
459 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
462 span
.end
= drawWidth
;
463 _mesa_write_zoomed_rgba_span(ctx
, &span
,
464 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
);
471 else if (ctx
->_ImageTransferState
==0) {
472 /* write CI data to CI frame buffer */
474 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
476 for (row
=0; row
<drawHeight
; row
++) {
477 (*swrast
->Driver
.WriteCI8Span
)(ctx
, drawWidth
, destX
, destY
,
491 /* can't handle this pixel format and/or data type here */
496 /* can't do a simple draw, have to use slow path */
503 * Do glDrawPixels of index pixels.
506 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
507 GLsizei width
, GLsizei height
,
508 GLenum type
, const GLvoid
*pixels
)
510 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
511 const GLint desty
= y
;
512 GLint row
, drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
515 INIT_SPAN(span
, GL_BITMAP
, drawWidth
, 0, SPAN_INDEX
);
518 _mesa_span_default_z(ctx
, &span
);
519 if (ctx
->Fog
.Enabled
)
520 _mesa_span_default_fog(ctx
, &span
);
525 for (row
= 0; row
< height
; row
++, y
++) {
526 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
527 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
528 _mesa_unpack_index_span(ctx
, drawWidth
, GL_UNSIGNED_INT
,
530 type
, source
, &ctx
->Unpack
,
531 ctx
->_ImageTransferState
);
534 span
.end
= drawWidth
;
536 _mesa_write_zoomed_index_span(ctx
, &span
, desty
);
538 _mesa_write_index_span(ctx
, &span
);
545 * Do glDrawPixels of stencil image. The image datatype may either
546 * be GLubyte or GLbitmap.
549 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
550 GLsizei width
, GLsizei height
,
551 GLenum type
, const GLvoid
*pixels
)
553 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
554 const GLint desty
= y
;
555 GLint row
, drawWidth
;
557 if (type
!= GL_BYTE
&&
558 type
!= GL_UNSIGNED_BYTE
&&
560 type
!= GL_UNSIGNED_SHORT
&&
562 type
!= GL_UNSIGNED_INT
&&
565 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(stencil type)");
569 if (ctx
->Visual
.stencilBits
== 0) {
570 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawPixels(no stencil buffer)");
574 drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
576 for (row
= 0; row
< height
; row
++, y
++) {
577 GLstencil values
[MAX_WIDTH
];
578 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
579 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
580 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
581 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
582 _mesa_unpack_index_span(ctx
, drawWidth
, destType
, values
,
583 type
, source
, &ctx
->Unpack
,
584 ctx
->_ImageTransferState
);
585 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
586 _mesa_shift_and_offset_stencil( ctx
, drawWidth
, values
);
588 if (ctx
->Pixel
.MapStencilFlag
) {
589 _mesa_map_stencil( ctx
, drawWidth
, values
);
593 _mesa_write_zoomed_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
,
597 _mesa_write_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
, values
);
604 * Do a glDrawPixels of depth values.
607 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
608 GLsizei width
, GLsizei height
,
609 GLenum type
, const GLvoid
*pixels
)
611 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
612 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
613 const GLint desty
= y
;
614 GLint drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
617 INIT_SPAN(span
, GL_BITMAP
, drawWidth
, 0, SPAN_Z
);
620 && type
!= GL_UNSIGNED_BYTE
622 && type
!= GL_UNSIGNED_SHORT
624 && type
!= GL_UNSIGNED_INT
625 && type
!= GL_FLOAT
) {
626 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(type)");
630 _mesa_span_default_color(ctx
, &span
);
632 if (ctx
->Fog
.Enabled
)
633 _mesa_span_default_fog(ctx
, &span
);
634 if (ctx
->Texture
._EnabledUnits
)
635 _mesa_span_default_texcoords(ctx
, &span
);
637 if (type
==GL_UNSIGNED_SHORT
&& ctx
->Visual
.depthBits
== 16
638 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
) {
639 /* Special case: directly write 16-bit depth values */
643 span
.end
= drawWidth
;
644 for (row
= 0; row
< height
; row
++, span
.y
++) {
645 const GLushort
*zptr
= (const GLushort
*)
646 _mesa_image_address(&ctx
->Unpack
, pixels
, width
, height
,
647 GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
649 for (i
= 0; i
< drawWidth
; i
++)
650 span
.array
->z
[i
] = zptr
[i
];
651 _mesa_write_rgba_span(ctx
, &span
);
654 else if (type
==GL_UNSIGNED_INT
&& ctx
->Visual
.depthBits
== 32
655 && !bias_or_scale
&& !zoom
&& ctx
->Visual
.rgbMode
) {
656 /* Special case: directly write 32-bit depth values */
660 span
.end
= drawWidth
;
661 for (row
= 0; row
< height
; row
++, span
.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 MEMCPY(span
.array
->z
, zptr
, drawWidth
* sizeof(GLdepth
));
666 _mesa_write_rgba_span(ctx
, &span
);
674 span
.end
= drawWidth
;
675 for (row
= 0; row
< height
; row
++, span
.y
++) {
676 GLfloat fspan
[MAX_WIDTH
];
677 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
,
678 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
679 _mesa_unpack_depth_span( ctx
, drawWidth
, fspan
, type
, src
,
681 /* clamp depth values to [0,1] and convert from floats to integers */
683 const GLfloat zs
= ctx
->DepthMaxF
;
685 for (i
= 0; i
< drawWidth
; i
++) {
686 span
.array
->z
[i
] = (GLdepth
) (fspan
[i
] * zs
+ 0.5F
);
689 if (ctx
->Visual
.rgbMode
) {
691 _mesa_write_zoomed_rgba_span(ctx
, &span
,
692 (const GLchan (*)[4]) span
.array
->rgba
, desty
);
695 _mesa_write_rgba_span(ctx
, &span
);
699 _mesa_write_zoomed_index_span(ctx
, &span
, desty
);
701 _mesa_write_index_span(ctx
, &span
);
709 * Do glDrawPixels of RGBA pixels.
712 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
713 GLsizei width
, GLsizei height
,
714 GLenum format
, GLenum type
, const GLvoid
*pixels
)
716 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
717 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
718 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
719 const GLint desty
= y
;
721 GLfloat
*convImage
= NULL
;
722 GLuint transferOps
= ctx
->_ImageTransferState
;
725 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
727 if (!_mesa_is_legal_format_and_type(format
, type
)) {
728 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(format or type)");
732 /* Try an optimized glDrawPixels first */
733 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
))
737 _mesa_span_default_z(ctx
, &span
);
738 if (ctx
->Fog
.Enabled
)
739 _mesa_span_default_fog(ctx
, &span
);
740 if (ctx
->Texture
._EnabledUnits
)
741 _mesa_span_default_texcoords(ctx
, &span
);
743 if (SWRAST_CONTEXT(ctx
)->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
744 && x
+ width
<= (GLint
) ctx
->DrawBuffer
->Width
745 && y
+ height
<= (GLint
) ctx
->DrawBuffer
->Height
) {
749 quickDraw
= GL_FALSE
;
752 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
753 /* Convolution has to be handled specially. We'll create an
754 * intermediate image, applying all pixel transfer operations
755 * up to convolution. Then we'll convolve the image. Then
756 * we'll proceed with the rest of the transfer operations and
757 * rasterize the image.
760 GLfloat
*dest
, *tmpImage
;
762 tmpImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
764 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
767 convImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
770 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
774 /* Unpack the image and apply transfer ops up to convolution */
776 for (row
= 0; row
< height
; row
++) {
777 const GLvoid
*source
= _mesa_image_address(unpack
,
778 pixels
, width
, height
, format
, type
, 0, row
, 0);
779 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, (GLfloat
*) dest
,
780 format
, type
, source
, unpack
,
781 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
,
787 if (ctx
->Pixel
.Convolution2DEnabled
) {
788 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
791 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
792 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
796 /* continue transfer ops and draw the convolved image */
797 unpack
= &_mesa_native_packing
;
801 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
809 if (width
> MAX_WIDTH
)
812 for (row
= 0; row
< height
; row
++, y
++) {
813 const GLvoid
*source
= _mesa_image_address(unpack
,
814 pixels
, width
, height
, format
, type
, 0, row
, 0);
816 _mesa_unpack_chan_color_span(ctx
, width
, GL_RGBA
,
817 (GLchan
*) span
.array
->rgba
,
818 format
, type
, source
, unpack
,
821 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
822 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
825 if (ctx
->Pixel
.PixelTextureEnabled
&& ctx
->Texture
._EnabledUnits
) {
827 _swrast_pixel_texture(ctx
, &span
);
831 (*swrast
->Driver
.WriteRGBASpan
)(ctx
, width
, x
, y
,
832 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
838 _mesa_write_zoomed_rgba_span(ctx
, &span
,
839 (CONST
GLchan (*)[4]) span
.array
->rgba
, desty
);
845 _mesa_write_rgba_span(ctx
, &span
);
858 * Execute glDrawPixels
861 _swrast_DrawPixels( GLcontext
*ctx
,
863 GLsizei width
, GLsizei height
,
864 GLenum format
, GLenum type
,
865 const struct gl_pixelstore_attrib
*unpack
,
866 const GLvoid
*pixels
)
868 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
871 if (swrast
->NewState
)
872 _swrast_validate_derived( ctx
);
874 RENDER_START(swrast
,ctx
);
877 case GL_STENCIL_INDEX
:
878 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
880 case GL_DEPTH_COMPONENT
:
881 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
884 if (ctx
->Visual
.rgbMode
)
885 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, pixels
);
887 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, pixels
);
894 case GL_LUMINANCE_ALPHA
:
900 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
);
903 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(format)" );
906 RENDER_FINISH(swrast
,ctx
);
911 #if 0 /* experimental */
913 * Execute glDrawDepthPixelsMESA().
916 _swrast_DrawDepthPixelsMESA( GLcontext
*ctx
,
918 GLsizei width
, GLsizei height
,
919 GLenum colorFormat
, GLenum colorType
,
920 const GLvoid
*colors
,
921 GLenum depthType
, const GLvoid
*depths
,
922 const struct gl_pixelstore_attrib
*unpack
)
924 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
927 if (swrast
->NewState
)
928 _swrast_validate_derived( ctx
);
930 RENDER_START(swrast
,ctx
);
932 switch (colorFormat
) {
934 if (ctx
->Visual
.rgbMode
)
935 draw_rgba_pixels(ctx
, x
,y
, width
, height
, colorFormat
, colorType
, colors
);
937 draw_index_pixels(ctx
, x
, y
, width
, height
, colorType
, colors
);
944 case GL_LUMINANCE_ALPHA
:
950 draw_rgba_pixels(ctx
, x
, y
, width
, height
, colorFormat
, colorType
, colors
);
953 _mesa_error( ctx
, GL_INVALID_ENUM
,
954 "glDrawDepthPixelsMESA(colorFormat)" );
957 RENDER_FINISH(swrast
,ctx
);