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.
27 #include "bufferobj.h"
35 #include "s_context.h"
36 #include "s_drawpix.h"
37 #include "s_pixeltex.h"
39 #include "s_stencil.h"
44 * Try to do a fast and simple RGB(a) glDrawPixels.
45 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
48 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
49 GLsizei width
, GLsizei height
,
50 GLenum format
, GLenum type
,
51 const struct gl_pixelstore_attrib
*unpack
,
55 struct gl_renderbuffer
*rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
57 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
60 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
62 if (!ctx
->Current
.RasterPosValid
) {
63 return GL_TRUE
; /* no-op */
66 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
)
70 _swrast_span_default_z(ctx
, &span
);
72 _swrast_span_default_fog(ctx
, &span
);
73 if (ctx
->Texture
._EnabledCoordUnits
)
74 _swrast_span_default_texcoords(ctx
, &span
);
76 if ((SWRAST_CONTEXT(ctx
)->_RasterMask
& ~CLIP_BIT
) == 0
77 && ctx
->Texture
._EnabledCoordUnits
== 0
78 && unpack
->Alignment
== 1
80 && !unpack
->LsbFirst
) {
84 GLint drawWidth
= width
; /* actual width drawn */
85 GLint drawHeight
= height
; /* actual height drawn */
86 GLint skipPixels
= unpack
->SkipPixels
;
87 GLint skipRows
= unpack
->SkipRows
;
91 if (unpack
->RowLength
> 0)
92 rowLength
= unpack
->RowLength
;
96 /* If we're not using pixel zoom then do all clipping calculations
97 * now. Otherwise, we'll let the _swrast_write_zoomed_*_span() functions
98 * handle the clipping.
100 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
101 /* horizontal clipping */
102 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
103 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
104 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
105 destX
= ctx
->DrawBuffer
->_Xmin
;
107 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
108 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
112 /* vertical clipping */
113 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
114 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
115 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
116 destY
= ctx
->DrawBuffer
->_Ymin
;
118 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
119 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
123 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
124 /* upside-down image */
125 /* horizontal clipping */
126 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
127 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
128 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
129 destX
= ctx
->DrawBuffer
->_Xmin
;
131 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
132 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
136 /* vertical clipping */
137 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
138 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
139 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
140 destY
= ctx
->DrawBuffer
->_Ymax
;
142 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
143 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
148 if (drawWidth
> MAX_WIDTH
)
149 return GL_FALSE
; /* fall back to general case path */
151 /* save Y value of first row */
152 zoomY0
= IROUND(ctx
->Current
.RasterPos
[1]);
158 * The window region at (destX, destY) of size (drawWidth, drawHeight)
159 * will be written to.
160 * We'll take pixel data from buffer pointed to by "pixels" but we'll
161 * skip "skipRows" rows and skip "skipPixels" pixels/row.
164 if (format
== GL_RGBA
&& type
== CHAN_TYPE
165 && ctx
->_ImageTransferState
==0) {
166 if (ctx
->Visual
.rgbMode
) {
167 GLchan
*src
= (GLchan
*) pixels
168 + (skipRows
* rowLength
+ skipPixels
) * 4;
169 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
172 for (row
=0; row
<drawHeight
; row
++) {
174 if (swrast
->Driver
.WriteRGBASpan
)
175 swrast
->Driver
.WriteRGBASpan(ctx
, rb
, drawWidth
,
177 (CONST
GLchan (*)[4]) src
,
181 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
182 src
+= rowLength
* 4;
186 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
189 for (row
=0; row
<drawHeight
; row
++) {
192 if (swrast
->Driver
.WriteRGBASpan
)
193 swrast
->Driver
.WriteRGBASpan(ctx
, rb
, drawWidth
,
195 (CONST
GLchan (*)[4]) src
,
199 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
200 src
+= rowLength
* 4;
206 for (row
=0; row
<drawHeight
; row
++) {
209 span
.end
= drawWidth
;
210 _swrast_write_zoomed_rgba_span(ctx
, &span
,
211 (CONST
GLchan (*)[4]) src
, zoomY0
, 0);
212 src
+= rowLength
* 4;
219 else if (format
== GL_RGB
&& type
== CHAN_TYPE
220 && ctx
->_ImageTransferState
== 0) {
221 if (ctx
->Visual
.rgbMode
) {
222 GLchan
*src
= (GLchan
*) pixels
223 + (skipRows
* rowLength
+ skipPixels
) * 3;
224 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
226 for (row
=0; row
<drawHeight
; row
++) {
228 if (swrast
->Driver
.WriteRGBSpan
)
229 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, rb
, drawWidth
,
231 (CONST
GLchan (*)[3]) src
,
235 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
236 src
+= rowLength
* 3;
240 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
243 for (row
=0; row
<drawHeight
; row
++) {
246 if (swrast
->Driver
.WriteRGBASpan
)
247 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, rb
, drawWidth
,
249 (CONST
GLchan (*)[3]) src
,
253 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
254 src
+= rowLength
* 3;
260 for (row
=0; row
<drawHeight
; row
++) {
263 span
.end
= drawWidth
;
264 _swrast_write_zoomed_rgb_span(ctx
, &span
,
265 (CONST
GLchan (*)[3]) src
, zoomY0
, 0);
266 src
+= rowLength
* 3;
273 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
274 && ctx
->_ImageTransferState
==0) {
275 if (ctx
->Visual
.rgbMode
) {
276 GLchan
*src
= (GLchan
*) pixels
277 + (skipRows
* rowLength
+ skipPixels
);
278 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
281 ASSERT(drawWidth
<= MAX_WIDTH
);
282 for (row
=0; row
<drawHeight
; row
++) {
284 for (i
=0;i
<drawWidth
;i
++) {
285 span
.array
->rgb
[i
][0] = src
[i
];
286 span
.array
->rgb
[i
][1] = src
[i
];
287 span
.array
->rgb
[i
][2] = src
[i
];
290 if (swrast
->Driver
.WriteRGBSpan
)
291 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, rb
, drawWidth
,
293 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
296 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
,
297 span
.array
->rgb
, NULL
);
302 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
305 ASSERT(drawWidth
<= MAX_WIDTH
);
306 for (row
=0; row
<drawHeight
; row
++) {
308 for (i
=0;i
<drawWidth
;i
++) {
309 span
.array
->rgb
[i
][0] = src
[i
];
310 span
.array
->rgb
[i
][1] = src
[i
];
311 span
.array
->rgb
[i
][2] = src
[i
];
315 if (swrast
->Driver
.WriteRGBSpan
)
316 (*swrast
->Driver
.WriteRGBSpan
)(ctx
, rb
, drawWidth
,
318 (CONST
GLchan (*)[3]) span
.array
->rgb
, NULL
);
321 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
322 span
.array
->rgb
, NULL
);
329 ASSERT(drawWidth
<= MAX_WIDTH
);
330 for (row
=0; row
<drawHeight
; row
++) {
332 for (i
=0;i
<drawWidth
;i
++) {
333 span
.array
->rgb
[i
][0] = src
[i
];
334 span
.array
->rgb
[i
][1] = src
[i
];
335 span
.array
->rgb
[i
][2] = src
[i
];
339 span
.end
= drawWidth
;
340 _swrast_write_zoomed_rgb_span(ctx
, &span
,
341 (CONST
GLchan (*)[3]) span
.array
->rgb
, zoomY0
, 0);
349 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
350 && ctx
->_ImageTransferState
== 0) {
351 if (ctx
->Visual
.rgbMode
) {
352 GLchan
*src
= (GLchan
*) pixels
353 + (skipRows
* rowLength
+ skipPixels
)*2;
354 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
357 ASSERT(drawWidth
<= MAX_WIDTH
);
358 for (row
=0; row
<drawHeight
; row
++) {
361 for (i
=0;i
<drawWidth
;i
++) {
362 span
.array
->rgba
[i
][0] = *ptr
;
363 span
.array
->rgba
[i
][1] = *ptr
;
364 span
.array
->rgba
[i
][2] = *ptr
++;
365 span
.array
->rgba
[i
][3] = *ptr
++;
368 if (swrast
->Driver
.WriteRGBASpan
)
369 swrast
->Driver
.WriteRGBASpan(ctx
, rb
, drawWidth
, destX
,destY
,
370 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
373 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
374 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
++;
394 if (swrast
->Driver
.WriteRGBASpan
)
395 swrast
->Driver
.WriteRGBASpan(ctx
, rb
, drawWidth
, destX
,destY
,
396 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
399 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
400 span
.array
->rgba
, NULL
);
407 ASSERT(drawWidth
<= MAX_WIDTH
);
408 for (row
=0; row
<drawHeight
; row
++) {
411 for (i
=0;i
<drawWidth
;i
++) {
412 span
.array
->rgba
[i
][0] = *ptr
;
413 span
.array
->rgba
[i
][1] = *ptr
;
414 span
.array
->rgba
[i
][2] = *ptr
++;
415 span
.array
->rgba
[i
][3] = *ptr
++;
419 span
.end
= drawWidth
;
420 _swrast_write_zoomed_rgba_span(ctx
, &span
,
421 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
, 0);
429 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
430 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
431 if (ctx
->Visual
.rgbMode
) {
432 /* convert CI data to RGBA */
433 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
436 for (row
=0; row
<drawHeight
; row
++) {
437 ASSERT(drawWidth
<= MAX_WIDTH
);
438 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
440 if (swrast
->Driver
.WriteRGBASpan
)
441 swrast
->Driver
.WriteRGBASpan(ctx
, rb
, drawWidth
, destX
,destY
,
442 (const GLchan (*)[4]) span
.array
->rgba
, NULL
);
445 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
446 span
.array
->rgba
, NULL
);
453 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
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 if (swrast
->Driver
.WriteRGBASpan
)
462 swrast
->Driver
.WriteRGBASpan(ctx
, rb
, drawWidth
, destX
,destY
,
463 (CONST
GLchan (*)[4]) span
.array
->rgba
, NULL
);
466 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
467 span
.array
->rgba
, NULL
);
475 for (row
=0; row
<drawHeight
; row
++) {
476 ASSERT(drawWidth
<= MAX_WIDTH
);
477 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
480 span
.end
= drawWidth
;
481 _swrast_write_zoomed_rgba_span(ctx
, &span
,
482 (CONST
GLchan (*)[4]) span
.array
->rgba
, zoomY0
, 0);
489 else if (ctx
->_ImageTransferState
==0) {
490 /* write CI data to CI frame buffer */
492 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
494 for (row
=0; row
<drawHeight
; row
++) {
495 GLuint index32
[MAX_WIDTH
];
497 for (col
= 0; col
< drawWidth
; col
++)
498 index32
[col
] = src
[col
];
499 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, index32
, NULL
);
512 /* can't handle this pixel format and/or data type here */
517 /* can't do a simple draw, have to use slow path */
524 * Draw color index image.
527 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
528 GLsizei width
, GLsizei height
,
530 const struct gl_pixelstore_attrib
*unpack
,
531 const GLvoid
*pixels
)
533 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
534 GLint row
, skipPixels
;
537 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_INDEX
);
540 _swrast_span_default_z(ctx
, &span
);
541 if (ctx
->Fog
.Enabled
)
542 _swrast_span_default_fog(ctx
, &span
);
548 while (skipPixels
< width
) {
549 const GLint spanX
= x
+ (zoom
? 0 : skipPixels
);
551 const GLint spanEnd
= (width
- skipPixels
> MAX_WIDTH
)
552 ? MAX_WIDTH
: (width
- skipPixels
);
553 ASSERT(spanEnd
<= MAX_WIDTH
);
554 for (row
= 0; row
< height
; row
++, spanY
++) {
555 const GLvoid
*source
= _mesa_image_address2d(unpack
, pixels
,
557 GL_COLOR_INDEX
, type
,
559 _mesa_unpack_index_span(ctx
, spanEnd
, GL_UNSIGNED_INT
,
560 span
.array
->index
, type
, source
, unpack
,
561 ctx
->_ImageTransferState
);
563 /* These may get changed during writing/clipping */
569 _swrast_write_zoomed_index_span(ctx
, &span
, y
, skipPixels
);
571 _swrast_write_index_span(ctx
, &span
);
573 skipPixels
+= spanEnd
;
580 * Draw stencil image.
583 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
584 GLsizei width
, GLsizei height
,
586 const struct gl_pixelstore_attrib
*unpack
,
587 const GLvoid
*pixels
)
589 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
590 const GLint desty
= y
;
591 GLint row
, skipPixels
;
593 if (type
!= GL_BYTE
&&
594 type
!= GL_UNSIGNED_BYTE
&&
596 type
!= GL_UNSIGNED_SHORT
&&
598 type
!= GL_UNSIGNED_INT
&&
601 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(stencil type)");
605 if (ctx
->Visual
.stencilBits
== 0) {
606 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glDrawPixels(no stencil buffer)");
610 /* if width > MAX_WIDTH, have to process image in chunks */
612 while (skipPixels
< width
) {
613 const GLint spanX
= x
;
615 const GLint spanWidth
= (width
- skipPixels
> MAX_WIDTH
)
616 ? MAX_WIDTH
: (width
- skipPixels
);
618 for (row
= 0; row
< height
; row
++, spanY
++) {
619 GLstencil values
[MAX_WIDTH
];
620 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
621 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
622 const GLvoid
*source
= _mesa_image_address2d(unpack
, pixels
,
624 GL_COLOR_INDEX
, type
,
626 _mesa_unpack_index_span(ctx
, spanWidth
, destType
, values
,
627 type
, source
, unpack
,
628 ctx
->_ImageTransferState
);
629 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
630 _mesa_shift_and_offset_stencil(ctx
, spanWidth
, values
);
632 if (ctx
->Pixel
.MapStencilFlag
) {
633 _mesa_map_stencil(ctx
, spanWidth
, values
);
637 _swrast_write_zoomed_stencil_span(ctx
, (GLuint
) spanWidth
,
638 spanX
, spanY
, values
, desty
, 0);
641 _swrast_write_stencil_span(ctx
, (GLuint
) spanWidth
,
642 spanX
, spanY
, values
);
645 skipPixels
+= spanWidth
;
654 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
655 GLsizei width
, GLsizei height
,
657 const struct gl_pixelstore_attrib
*unpack
,
658 const GLvoid
*pixels
)
660 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
661 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
662 const GLint desty
= y
;
665 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_Z
);
668 && type
!= GL_UNSIGNED_BYTE
670 && type
!= GL_UNSIGNED_SHORT
672 && type
!= GL_UNSIGNED_INT
673 && type
!= GL_FLOAT
) {
674 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(type)");
678 _swrast_span_default_color(ctx
, &span
);
680 if (ctx
->Fog
.Enabled
)
681 _swrast_span_default_fog(ctx
, &span
);
682 if (ctx
->Texture
._EnabledCoordUnits
)
683 _swrast_span_default_texcoords(ctx
, &span
);
685 if (type
== GL_UNSIGNED_SHORT
686 && ctx
->Visual
.depthBits
== 16
689 && ctx
->Visual
.rgbMode
690 && width
<= MAX_WIDTH
) {
691 /* Special case: directly write 16-bit depth values */
692 GLint row
, spanY
= y
;
693 for (row
= 0; row
< height
; row
++, spanY
++) {
694 const GLushort
*zSrc
= (const GLushort
*)
695 _mesa_image_address2d(unpack
, pixels
, width
, height
,
696 GL_DEPTH_COMPONENT
, type
, row
, 0);
698 for (i
= 0; i
< width
; i
++)
699 span
.array
->z
[i
] = zSrc
[i
];
703 _swrast_write_rgba_span(ctx
, &span
);
706 else if (type
== GL_UNSIGNED_INT
707 && sizeof(GLdepth
) == 4
710 && ctx
->Visual
.rgbMode
711 && width
<= MAX_WIDTH
) {
712 /* Special case: shift 32-bit values down to ctx->Visual.depthBits */
713 const GLint shift
= 32 - ctx
->Visual
.depthBits
;
714 GLint row
, spanY
= y
;
715 for (row
= 0; row
< height
; row
++, spanY
++) {
716 const GLuint
*zSrc
= (const GLuint
*)
717 _mesa_image_address2d(unpack
, pixels
, width
, height
,
718 GL_DEPTH_COMPONENT
, type
, row
, 0);
720 MEMCPY(span
.array
->z
, zSrc
, width
* sizeof(GLdepth
));
724 for (col
= 0; col
< width
; col
++)
725 span
.array
->z
[col
] = zSrc
[col
] >> shift
;
730 _swrast_write_rgba_span(ctx
, &span
);
735 const GLfloat depthMax
= ctx
->DrawBuffer
->_DepthMaxF
;
736 GLint row
, skipPixels
= 0;
738 /* in case width > MAX_WIDTH do the copy in chunks */
739 while (skipPixels
< width
) {
740 const GLint spanX
= x
+ (zoom
? 0 : skipPixels
);
742 const GLint spanEnd
= (width
- skipPixels
> MAX_WIDTH
)
743 ? MAX_WIDTH
: (width
- skipPixels
);
744 ASSERT(span
.end
<= MAX_WIDTH
);
745 for (row
= 0; row
< height
; row
++, spanY
++) {
746 GLfloat floatSpan
[MAX_WIDTH
];
747 const GLvoid
*zSrc
= _mesa_image_address2d(unpack
,
748 pixels
, width
, height
,
749 GL_DEPTH_COMPONENT
, type
,
752 /* Set these for each row since the _swrast_write_* function may
753 * change them while clipping.
759 _mesa_unpack_depth_span(ctx
, span
.end
, floatSpan
, type
,
761 /* clamp depth values to [0,1] and convert from floats to ints */
764 for (i
= 0; i
< span
.end
; i
++) {
765 span
.array
->z
[i
] = (GLdepth
) (floatSpan
[i
] * depthMax
);
769 _swrast_write_zoomed_depth_span(ctx
, &span
, desty
, skipPixels
);
771 else if (ctx
->Visual
.rgbMode
) {
772 _swrast_write_rgba_span(ctx
, &span
);
775 _swrast_write_index_span(ctx
, &span
);
778 skipPixels
+= spanEnd
;
789 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
790 GLsizei width
, GLsizei height
,
791 GLenum format
, GLenum type
,
792 const struct gl_pixelstore_attrib
*unpack
,
793 const GLvoid
*pixels
)
795 struct gl_renderbuffer
*rb
= NULL
; /* only used for quickDraw path */
796 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
797 const GLint desty
= y
;
799 GLfloat
*convImage
= NULL
;
800 GLuint transferOps
= ctx
->_ImageTransferState
;
803 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
805 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
806 _mesa_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(format or type)");
810 /* Try an optimized glDrawPixels first */
811 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
))
815 _swrast_span_default_z(ctx
, &span
);
816 if (ctx
->Fog
.Enabled
)
817 _swrast_span_default_fog(ctx
, &span
);
818 if (ctx
->Texture
._EnabledCoordUnits
)
819 _swrast_span_default_texcoords(ctx
, &span
);
821 if (SWRAST_CONTEXT(ctx
)->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
822 && x
+ width
<= (GLint
) ctx
->DrawBuffer
->Width
823 && y
+ height
<= (GLint
) ctx
->DrawBuffer
->Height
824 && ctx
->DrawBuffer
->_NumColorDrawBuffers
[0] == 1) {
826 rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
829 quickDraw
= GL_FALSE
;
833 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
834 /* Convolution has to be handled specially. We'll create an
835 * intermediate image, applying all pixel transfer operations
836 * up to convolution. Then we'll convolve the image. Then
837 * we'll proceed with the rest of the transfer operations and
838 * rasterize the image.
841 GLfloat
*dest
, *tmpImage
;
843 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
845 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
848 convImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
850 _mesa_free(tmpImage
);
851 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
855 /* Unpack the image and apply transfer ops up to convolution */
857 for (row
= 0; row
< height
; row
++) {
858 const GLvoid
*source
= _mesa_image_address2d(unpack
,
859 pixels
, width
, height
, format
, type
, row
, 0);
860 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
, (GLfloat
*) dest
,
861 format
, type
, source
, unpack
,
862 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
);
867 if (ctx
->Pixel
.Convolution2DEnabled
) {
868 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
871 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
872 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
874 _mesa_free(tmpImage
);
876 /* continue transfer ops and draw the convolved image */
877 unpack
= &ctx
->DefaultPacking
;
881 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
888 const GLuint interpMask
= span
.interpMask
;
889 const GLuint arrayMask
= span
.arrayMask
;
890 GLint row
, skipPixels
= 0;
892 /* if the span is wider than MAX_WIDTH we have to do it in chunks */
893 while (skipPixels
< width
) {
894 const GLint spanX
= x
+ (zoom
? 0 : skipPixels
);
896 const GLint spanEnd
= (width
- skipPixels
> MAX_WIDTH
)
897 ? MAX_WIDTH
: (width
- skipPixels
);
898 ASSERT(span
.end
<= MAX_WIDTH
);
900 for (row
= 0; row
< height
; row
++, spanY
++) {
901 const GLvoid
*source
= _mesa_image_address2d(unpack
,
902 pixels
, width
, height
, format
, type
, row
, skipPixels
);
904 /* Set these for each row since the _swrast_write_* function may
905 * change them while clipping.
910 span
.arrayMask
= arrayMask
;
911 span
.interpMask
= interpMask
;
913 _mesa_unpack_color_span_chan(ctx
, span
.end
, GL_RGBA
,
914 (GLchan
*) span
.array
->rgba
,
915 format
, type
, source
, unpack
,
918 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
919 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
922 if (ctx
->Pixel
.PixelTextureEnabled
&& ctx
->Texture
._EnabledUnits
) {
923 _swrast_pixel_texture(ctx
, &span
);
928 rb
->PutRow(ctx
, rb
, span
.end
, span
.x
, span
.y
,
929 span
.array
->rgba
, NULL
);
932 _swrast_write_zoomed_rgba_span(ctx
, &span
,
933 (CONST
GLchan (*)[4]) span
.array
->rgba
, desty
, skipPixels
);
936 _swrast_write_rgba_span(ctx
, &span
);
940 skipPixels
+= spanEnd
;
945 _mesa_free(convImage
);
952 * Execute glDrawPixels
955 _swrast_DrawPixels( GLcontext
*ctx
,
957 GLsizei width
, GLsizei height
,
958 GLenum format
, GLenum type
,
959 const struct gl_pixelstore_attrib
*unpack
,
960 const GLvoid
*pixels
)
962 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
964 if (swrast
->NewState
)
965 _swrast_validate_derived( ctx
);
967 if (unpack
->BufferObj
->Name
) {
968 /* unpack from PBO */
970 if (!_mesa_validate_pbo_access(2, unpack
, width
, height
, 1,
971 format
, type
, pixels
)) {
972 _mesa_error(ctx
, GL_INVALID_OPERATION
,
973 "glDrawPixels(invalid PBO access)");
976 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
980 /* buffer is already mapped - that's an error */
981 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glDrawPixels(PBO is mapped)");
984 pixels
= ADD_POINTERS(buf
, pixels
);
987 RENDER_START(swrast
,ctx
);
990 case GL_STENCIL_INDEX
:
991 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
993 case GL_DEPTH_COMPONENT
:
994 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
997 if (ctx
->Visual
.rgbMode
)
998 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, unpack
, pixels
);
1000 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
1007 case GL_LUMINANCE_ALPHA
:
1013 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
);
1016 _mesa_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(format)" );
1017 /* don't return yet, clean-up */
1020 RENDER_FINISH(swrast
,ctx
);
1022 if (unpack
->BufferObj
->Name
) {
1023 /* done with PBO so unmap it now */
1024 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
1031 #if 0 /* experimental */
1033 * Execute glDrawDepthPixelsMESA().
1036 _swrast_DrawDepthPixelsMESA( GLcontext
*ctx
,
1038 GLsizei width
, GLsizei height
,
1039 GLenum colorFormat
, GLenum colorType
,
1040 const GLvoid
*colors
,
1041 GLenum depthType
, const GLvoid
*depths
,
1042 const struct gl_pixelstore_attrib
*unpack
)
1044 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1046 if (swrast
->NewState
)
1047 _swrast_validate_derived( ctx
);
1049 RENDER_START(swrast
,ctx
);
1051 switch (colorFormat
) {
1052 case GL_COLOR_INDEX
:
1053 if (ctx
->Visual
.rgbMode
)
1054 draw_rgba_pixels(ctx
, x
,y
, width
, height
, colorFormat
, colorType
, unpack
, colors
);
1056 draw_index_pixels(ctx
, x
, y
, width
, height
, colorType
, unpack
, colors
);
1063 case GL_LUMINANCE_ALPHA
:
1069 draw_rgba_pixels(ctx
, x
, y
, width
, height
, colorFormat
, colorType
, unpack
, colors
);
1072 _mesa_error( ctx
, GL_INVALID_ENUM
,
1073 "glDrawDepthPixelsMESA(colorFormat)" );
1076 RENDER_FINISH(swrast
,ctx
);