2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 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"
38 #include "s_stencil.h"
43 * Try to do a fast and simple RGB(a) glDrawPixels.
44 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
47 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
48 GLsizei width
, GLsizei height
,
49 GLenum format
, GLenum type
,
50 const struct gl_pixelstore_attrib
*unpack
,
53 const GLint imgX
= x
, imgY
= y
;
54 struct gl_renderbuffer
*rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
55 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
58 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
60 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
)
64 _swrast_span_default_z(ctx
, &span
);
65 if (swrast
->_FogEnabled
)
66 _swrast_span_default_fog(ctx
, &span
);
67 if (ctx
->Texture
._EnabledCoordUnits
)
68 _swrast_span_default_texcoords(ctx
, &span
);
70 if ((SWRAST_CONTEXT(ctx
)->_RasterMask
& ~CLIP_BIT
) == 0
71 && ctx
->Texture
._EnabledCoordUnits
== 0
72 && unpack
->Alignment
== 1
74 && !unpack
->LsbFirst
) {
76 /* XXX there's a lot of clipping code here that should be replaced
77 * by a call to _mesa_clip_drawpixels().
81 GLint drawWidth
= width
; /* actual width drawn */
82 GLint drawHeight
= height
; /* actual height drawn */
83 GLint skipPixels
= unpack
->SkipPixels
;
84 GLint skipRows
= unpack
->SkipRows
;
87 if (unpack
->RowLength
> 0)
88 rowLength
= unpack
->RowLength
;
92 /* If we're not using pixel zoom then do all clipping calculations
93 * now. Otherwise, we'll let the _swrast_write_zoomed_*_span() functions
94 * handle the clipping.
96 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
97 /* horizontal clipping */
98 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
99 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
100 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
101 destX
= ctx
->DrawBuffer
->_Xmin
;
103 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
104 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
108 /* vertical clipping */
109 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
110 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
111 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
112 destY
= ctx
->DrawBuffer
->_Ymin
;
114 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
115 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
119 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
120 /* upside-down image */
121 /* horizontal clipping */
122 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
123 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
124 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
125 destX
= ctx
->DrawBuffer
->_Xmin
;
127 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
128 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
132 /* vertical clipping */
133 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
134 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
135 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
136 destY
= ctx
->DrawBuffer
->_Ymax
;
138 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
139 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
144 if (drawWidth
> MAX_WIDTH
)
145 return GL_FALSE
; /* fall back to general case path */
151 * The window region at (destX, destY) of size (drawWidth, drawHeight)
152 * will be written to.
153 * We'll take pixel data from buffer pointed to by "pixels" but we'll
154 * skip "skipRows" rows and skip "skipPixels" pixels/row.
157 if (format
== GL_RGBA
&& type
== CHAN_TYPE
158 && ctx
->_ImageTransferState
==0) {
159 if (ctx
->Visual
.rgbMode
) {
160 GLchan
*src
= (GLchan
*) pixels
161 + (skipRows
* rowLength
+ skipPixels
) * 4;
162 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
165 for (row
=0; row
<drawHeight
; row
++) {
166 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
167 src
+= rowLength
* 4;
171 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
174 for (row
=0; row
<drawHeight
; row
++) {
176 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
177 src
+= rowLength
* 4;
183 for (row
=0; row
<drawHeight
; row
++) {
185 span
.y
= destY
+ row
;
186 span
.end
= drawWidth
;
187 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
188 (CONST
GLchan (*)[4]) src
);
189 src
+= rowLength
* 4;
195 else if (format
== GL_RGB
&& type
== CHAN_TYPE
196 && ctx
->_ImageTransferState
== 0) {
197 if (ctx
->Visual
.rgbMode
) {
198 GLchan
*src
= (GLchan
*) pixels
199 + (skipRows
* rowLength
+ skipPixels
) * 3;
200 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
202 for (row
=0; row
<drawHeight
; row
++) {
203 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
204 src
+= rowLength
* 3;
208 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
211 for (row
=0; row
<drawHeight
; row
++) {
213 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
214 src
+= rowLength
* 3;
220 for (row
=0; row
<drawHeight
; row
++) {
223 span
.end
= drawWidth
;
224 _swrast_write_zoomed_rgb_span(ctx
, imgX
, imgY
, &span
,
225 (CONST
GLchan (*)[3]) src
);
226 src
+= rowLength
* 3;
233 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
234 && ctx
->_ImageTransferState
==0) {
235 if (ctx
->Visual
.rgbMode
) {
236 GLchan
*src
= (GLchan
*) pixels
237 + (skipRows
* rowLength
+ skipPixels
);
238 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
241 ASSERT(drawWidth
<= MAX_WIDTH
);
242 for (row
=0; row
<drawHeight
; row
++) {
244 for (i
=0;i
<drawWidth
;i
++) {
245 span
.array
->rgb
[i
][0] = src
[i
];
246 span
.array
->rgb
[i
][1] = src
[i
];
247 span
.array
->rgb
[i
][2] = src
[i
];
249 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
,
250 span
.array
->rgb
, NULL
);
255 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
258 ASSERT(drawWidth
<= MAX_WIDTH
);
259 for (row
=0; row
<drawHeight
; row
++) {
261 for (i
=0;i
<drawWidth
;i
++) {
262 span
.array
->rgb
[i
][0] = src
[i
];
263 span
.array
->rgb
[i
][1] = src
[i
];
264 span
.array
->rgb
[i
][2] = src
[i
];
267 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
268 span
.array
->rgb
, NULL
);
275 ASSERT(drawWidth
<= MAX_WIDTH
);
276 for (row
=0; row
<drawHeight
; row
++) {
278 for (i
=0;i
<drawWidth
;i
++) {
279 span
.array
->rgb
[i
][0] = src
[i
];
280 span
.array
->rgb
[i
][1] = src
[i
];
281 span
.array
->rgb
[i
][2] = src
[i
];
285 span
.end
= drawWidth
;
286 _swrast_write_zoomed_rgb_span(ctx
, imgX
, imgY
, &span
,
287 (CONST
GLchan (*)[3]) span
.array
->rgb
);
295 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
296 && ctx
->_ImageTransferState
== 0) {
297 if (ctx
->Visual
.rgbMode
) {
298 GLchan
*src
= (GLchan
*) pixels
299 + (skipRows
* rowLength
+ skipPixels
)*2;
300 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
303 ASSERT(drawWidth
<= MAX_WIDTH
);
304 for (row
=0; row
<drawHeight
; row
++) {
307 for (i
=0;i
<drawWidth
;i
++) {
308 span
.array
->rgba
[i
][0] = *ptr
;
309 span
.array
->rgba
[i
][1] = *ptr
;
310 span
.array
->rgba
[i
][2] = *ptr
++;
311 span
.array
->rgba
[i
][3] = *ptr
++;
313 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
314 span
.array
->rgba
, NULL
);
319 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
322 ASSERT(drawWidth
<= MAX_WIDTH
);
323 for (row
=0; row
<drawHeight
; row
++) {
326 for (i
=0;i
<drawWidth
;i
++) {
327 span
.array
->rgba
[i
][0] = *ptr
;
328 span
.array
->rgba
[i
][1] = *ptr
;
329 span
.array
->rgba
[i
][2] = *ptr
++;
330 span
.array
->rgba
[i
][3] = *ptr
++;
333 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
334 span
.array
->rgba
, NULL
);
341 ASSERT(drawWidth
<= MAX_WIDTH
);
342 for (row
=0; row
<drawHeight
; row
++) {
345 for (i
=0;i
<drawWidth
;i
++) {
346 span
.array
->rgba
[i
][0] = *ptr
;
347 span
.array
->rgba
[i
][1] = *ptr
;
348 span
.array
->rgba
[i
][2] = *ptr
++;
349 span
.array
->rgba
[i
][3] = *ptr
++;
353 span
.end
= drawWidth
;
354 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
355 (CONST
GLchan (*)[4]) span
.array
->rgba
);
363 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
364 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
365 if (ctx
->Visual
.rgbMode
) {
366 /* convert CI data to RGBA */
367 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
370 for (row
=0; row
<drawHeight
; row
++) {
371 ASSERT(drawWidth
<= MAX_WIDTH
);
372 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
373 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
374 span
.array
->rgba
, NULL
);
380 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
383 for (row
=0; row
<drawHeight
; row
++) {
384 ASSERT(drawWidth
<= MAX_WIDTH
);
385 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
387 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
388 span
.array
->rgba
, NULL
);
396 for (row
=0; row
<drawHeight
; row
++) {
397 ASSERT(drawWidth
<= MAX_WIDTH
);
398 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
401 span
.end
= drawWidth
;
402 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
403 (CONST
GLchan (*)[4]) span
.array
->rgba
);
410 else if (ctx
->_ImageTransferState
==0) {
411 /* write CI data to CI frame buffer */
413 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
415 for (row
=0; row
<drawHeight
; row
++) {
416 GLuint index32
[MAX_WIDTH
];
418 for (col
= 0; col
< drawWidth
; col
++)
419 index32
[col
] = src
[col
];
420 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, index32
, NULL
);
433 /* can't handle this pixel format and/or data type here */
438 /* can't do a simple draw, have to use slow path */
445 * Draw color index image.
448 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
449 GLsizei width
, GLsizei height
,
451 const struct gl_pixelstore_attrib
*unpack
,
452 const GLvoid
*pixels
)
454 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
455 const GLint imgX
= x
, imgY
= y
;
456 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
457 GLint row
, skipPixels
;
460 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_INDEX
);
463 _swrast_span_default_z(ctx
, &span
);
464 if (swrast
->_FogEnabled
)
465 _swrast_span_default_fog(ctx
, &span
);
471 while (skipPixels
< width
) {
472 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
473 ASSERT(spanWidth
<= MAX_WIDTH
);
474 for (row
= 0; row
< height
; row
++) {
475 const GLvoid
*source
= _mesa_image_address2d(unpack
, pixels
,
477 GL_COLOR_INDEX
, type
,
479 _mesa_unpack_index_span(ctx
, spanWidth
, GL_UNSIGNED_INT
,
480 span
.array
->index
, type
, source
, unpack
,
481 ctx
->_ImageTransferState
);
483 /* These may get changed during writing/clipping */
484 span
.x
= x
+ skipPixels
;
486 span
.end
= spanWidth
;
489 _swrast_write_zoomed_index_span(ctx
, imgX
, imgY
, &span
);
491 _swrast_write_index_span(ctx
, &span
);
493 skipPixels
+= spanWidth
;
500 * Draw stencil image.
503 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
504 GLsizei width
, GLsizei height
,
506 const struct gl_pixelstore_attrib
*unpack
,
507 const GLvoid
*pixels
)
509 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
512 /* if width > MAX_WIDTH, have to process image in chunks */
514 while (skipPixels
< width
) {
515 const GLint spanX
= x
+ skipPixels
;
516 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
518 for (row
= 0; row
< height
; row
++) {
519 const GLint spanY
= y
+ row
;
520 GLstencil values
[MAX_WIDTH
];
521 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
522 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
523 const GLvoid
*source
= _mesa_image_address2d(unpack
, pixels
,
525 GL_COLOR_INDEX
, type
,
527 _mesa_unpack_index_span(ctx
, spanWidth
, destType
, values
,
528 type
, source
, unpack
,
529 ctx
->_ImageTransferState
);
530 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
531 _mesa_shift_and_offset_stencil(ctx
, spanWidth
, values
);
533 if (ctx
->Pixel
.MapStencilFlag
) {
534 _mesa_map_stencil(ctx
, spanWidth
, values
);
538 _swrast_write_zoomed_stencil_span(ctx
, x
, y
, spanWidth
,
539 spanX
, spanY
, values
);
542 _swrast_write_stencil_span(ctx
, spanWidth
, spanX
, spanY
, values
);
545 skipPixels
+= spanWidth
;
554 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
555 GLsizei width
, GLsizei height
,
557 const struct gl_pixelstore_attrib
*unpack
,
558 const GLvoid
*pixels
)
560 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
561 const GLboolean scaleOrBias
562 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
563 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
566 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_Z
);
568 _swrast_span_default_color(ctx
, &span
);
570 if (swrast
->_FogEnabled
)
571 _swrast_span_default_fog(ctx
, &span
);
572 if (ctx
->Texture
._EnabledCoordUnits
)
573 _swrast_span_default_texcoords(ctx
, &span
);
575 if (type
== GL_UNSIGNED_SHORT
576 && ctx
->DrawBuffer
->Visual
.depthBits
== 16
579 && ctx
->Visual
.rgbMode
580 && width
<= MAX_WIDTH
) {
581 /* Special case: directly write 16-bit depth values */
583 for (row
= 0; row
< height
; row
++) {
584 const GLushort
*zSrc
= (const GLushort
*)
585 _mesa_image_address2d(unpack
, pixels
, width
, height
,
586 GL_DEPTH_COMPONENT
, type
, row
, 0);
588 for (i
= 0; i
< width
; i
++)
589 span
.array
->z
[i
] = zSrc
[i
];
593 _swrast_write_rgba_span(ctx
, &span
);
596 else if (type
== GL_UNSIGNED_INT
599 && ctx
->Visual
.rgbMode
600 && width
<= MAX_WIDTH
) {
601 /* Special case: shift 32-bit values down to Visual.depthBits */
602 const GLint shift
= 32 - ctx
->DrawBuffer
->Visual
.depthBits
;
604 for (row
= 0; row
< height
; row
++) {
605 const GLuint
*zSrc
= (const GLuint
*)
606 _mesa_image_address2d(unpack
, pixels
, width
, height
,
607 GL_DEPTH_COMPONENT
, type
, row
, 0);
609 _mesa_memcpy(span
.array
->z
, zSrc
, width
* sizeof(GLuint
));
613 for (col
= 0; col
< width
; col
++)
614 span
.array
->z
[col
] = zSrc
[col
] >> shift
;
619 _swrast_write_rgba_span(ctx
, &span
);
624 const GLfloat depthMax
= ctx
->DrawBuffer
->_DepthMaxF
;
625 GLint skipPixels
= 0;
627 /* in case width > MAX_WIDTH do the copy in chunks */
628 while (skipPixels
< width
) {
629 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
631 ASSERT(span
.end
<= MAX_WIDTH
);
632 for (row
= 0; row
< height
; row
++) {
633 const GLvoid
*zSrc
= _mesa_image_address2d(unpack
,
634 pixels
, width
, height
,
635 GL_DEPTH_COMPONENT
, type
,
638 /* Set these for each row since the _swrast_write_* function may
639 * change them while clipping.
641 span
.x
= x
+ skipPixels
;
643 span
.end
= spanWidth
;
645 _mesa_unpack_depth_span(ctx
, spanWidth
,
646 GL_UNSIGNED_INT
, span
.array
->z
, depthMax
,
649 _swrast_write_zoomed_depth_span(ctx
, x
, y
, &span
);
651 else if (ctx
->Visual
.rgbMode
) {
652 _swrast_write_rgba_span(ctx
, &span
);
655 _swrast_write_index_span(ctx
, &span
);
658 skipPixels
+= spanWidth
;
669 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
670 GLsizei width
, GLsizei height
,
671 GLenum format
, GLenum type
,
672 const struct gl_pixelstore_attrib
*unpack
,
673 const GLvoid
*pixels
)
675 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
676 const GLint imgX
= x
, imgY
= y
;
677 struct gl_renderbuffer
*rb
= NULL
; /* only used for quickDraw path */
678 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
680 GLfloat
*convImage
= NULL
;
681 GLuint transferOps
= ctx
->_ImageTransferState
;
684 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
686 /* Try an optimized glDrawPixels first */
687 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
))
691 _swrast_span_default_z(ctx
, &span
);
692 if (swrast
->_FogEnabled
)
693 _swrast_span_default_fog(ctx
, &span
);
694 if (ctx
->Texture
._EnabledCoordUnits
)
695 _swrast_span_default_texcoords(ctx
, &span
);
697 if (SWRAST_CONTEXT(ctx
)->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
698 && x
+ width
<= (GLint
) ctx
->DrawBuffer
->Width
699 && y
+ height
<= (GLint
) ctx
->DrawBuffer
->Height
700 && ctx
->DrawBuffer
->_NumColorDrawBuffers
[0] == 1) {
702 rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
705 quickDraw
= GL_FALSE
;
709 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
710 /* Convolution has to be handled specially. We'll create an
711 * intermediate image, applying all pixel transfer operations
712 * up to convolution. Then we'll convolve the image. Then
713 * we'll proceed with the rest of the transfer operations and
714 * rasterize the image.
717 GLfloat
*dest
, *tmpImage
;
719 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
721 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
724 convImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
726 _mesa_free(tmpImage
);
727 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
731 /* Unpack the image and apply transfer ops up to convolution */
733 for (row
= 0; row
< height
; row
++) {
734 const GLvoid
*source
= _mesa_image_address2d(unpack
,
735 pixels
, width
, height
, format
, type
, row
, 0);
736 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
, (GLfloat
*) dest
,
737 format
, type
, source
, unpack
,
738 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
);
743 if (ctx
->Pixel
.Convolution2DEnabled
) {
744 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
747 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
748 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
750 _mesa_free(tmpImage
);
752 /* continue transfer ops and draw the convolved image */
753 unpack
= &ctx
->DefaultPacking
;
757 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
764 const GLbitfield interpMask
= span
.interpMask
;
765 const GLbitfield arrayMask
= span
.arrayMask
;
766 GLint skipPixels
= 0;
768 /* if the span is wider than MAX_WIDTH we have to do it in chunks */
769 while (skipPixels
< width
) {
770 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
773 ASSERT(span
.end
<= MAX_WIDTH
);
775 for (row
= 0; row
< height
; row
++) {
776 const GLvoid
*source
= _mesa_image_address2d(unpack
,
777 pixels
, width
, height
, format
, type
, row
, skipPixels
);
779 /* Set these for each row since the _swrast_write_* function may
780 * change them while clipping.
782 span
.x
= x
+ skipPixels
;
784 span
.end
= spanWidth
;
785 span
.arrayMask
= arrayMask
;
786 span
.interpMask
= interpMask
;
788 _mesa_unpack_color_span_chan(ctx
, spanWidth
, GL_RGBA
,
789 (GLchan
*) span
.array
->rgba
,
790 format
, type
, source
, unpack
,
793 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
794 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
799 rb
->PutRow(ctx
, rb
, span
.end
, span
.x
, span
.y
,
800 span
.array
->rgba
, NULL
);
803 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
804 (CONST
GLchan (*)[4]) span
.array
->rgba
);
807 _swrast_write_rgba_span(ctx
, &span
);
811 skipPixels
+= spanWidth
;
816 _mesa_free(convImage
);
822 * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
823 * The only per-pixel operations that apply are depth scale/bias,
824 * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
826 * Also, only the depth buffer and stencil buffers are touched, not the
830 draw_depth_stencil_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
831 GLsizei width
, GLsizei height
, GLenum type
,
832 const struct gl_pixelstore_attrib
*unpack
,
833 const GLvoid
*pixels
)
835 const GLint imgX
= x
, imgY
= y
;
836 const GLboolean scaleOrBias
=
837 ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
838 const GLfloat depthScale
= ctx
->DrawBuffer
->_DepthMaxF
;
839 const GLuint stencilMask
= ctx
->Stencil
.WriteMask
[0];
840 const GLuint stencilType
= (STENCIL_BITS
== 8) ?
841 GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
842 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
843 struct gl_renderbuffer
*depthRb
, *stencilRb
;
844 struct gl_pixelstore_attrib clippedUnpack
= *unpack
;
847 if (!_mesa_clip_drawpixels(ctx
, &x
, &y
, &width
, &height
,
849 /* totally clipped */
854 depthRb
= ctx
->ReadBuffer
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
855 stencilRb
= ctx
->ReadBuffer
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
859 if (depthRb
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
&&
860 stencilRb
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
&&
861 depthRb
== stencilRb
&&
865 (stencilMask
& 0xff) == 0xff) {
866 /* This is the ideal case.
867 * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer.
868 * Plus, no pixel transfer ops, zooming, or masking needed.
871 for (i
= 0; i
< height
; i
++) {
872 const GLuint
*src
= (const GLuint
*)
873 _mesa_image_address2d(&clippedUnpack
, pixels
, width
, height
,
874 GL_DEPTH_STENCIL_EXT
, type
, i
, 0);
875 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, src
, NULL
);
879 /* sub-optimal cases:
880 * Separate depth/stencil buffers, or pixel transfer ops required.
882 /* XXX need to handle very wide images (skippixels) */
885 depthRb
= ctx
->DrawBuffer
->_DepthBuffer
;
886 stencilRb
= ctx
->DrawBuffer
->_StencilBuffer
;
888 for (i
= 0; i
< height
; i
++) {
889 const GLuint
*depthStencilSrc
= (const GLuint
*)
890 _mesa_image_address2d(&clippedUnpack
, pixels
, width
, height
,
891 GL_DEPTH_STENCIL_EXT
, type
, i
, 0);
893 if (ctx
->Depth
.Mask
) {
894 if (!scaleOrBias
&& ctx
->DrawBuffer
->Visual
.depthBits
== 24) {
895 /* fast path 24-bit zbuffer */
896 GLuint zValues
[MAX_WIDTH
];
898 ASSERT(depthRb
->DataType
== GL_UNSIGNED_INT
);
899 for (j
= 0; j
< width
; j
++) {
900 zValues
[j
] = depthStencilSrc
[j
] >> 8;
903 _swrast_write_zoomed_z_span(ctx
, imgX
, imgY
, width
,
906 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, zValues
,NULL
);
908 else if (!scaleOrBias
&& ctx
->DrawBuffer
->Visual
.depthBits
== 16) {
909 /* fast path 16-bit zbuffer */
910 GLushort zValues
[MAX_WIDTH
];
912 ASSERT(depthRb
->DataType
== GL_UNSIGNED_SHORT
);
913 for (j
= 0; j
< width
; j
++) {
914 zValues
[j
] = depthStencilSrc
[j
] >> 16;
917 _swrast_write_zoomed_z_span(ctx
, imgX
, imgY
, width
,
920 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, zValues
,NULL
);
924 GLuint zValues
[MAX_WIDTH
]; /* 16 or 32-bit Z value storage */
925 _mesa_unpack_depth_span(ctx
, width
,
926 depthRb
->DataType
, zValues
, depthScale
,
927 type
, depthStencilSrc
, &clippedUnpack
);
929 _swrast_write_zoomed_z_span(ctx
, imgX
, imgY
, width
, x
,
933 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, zValues
,NULL
);
938 if (stencilMask
!= 0x0) {
939 GLstencil stencilValues
[MAX_WIDTH
];
940 /* get stencil values, with shift/offset/mapping */
941 _mesa_unpack_stencil_span(ctx
, width
, stencilType
, stencilValues
,
942 type
, depthStencilSrc
, &clippedUnpack
,
943 ctx
->_ImageTransferState
);
945 _swrast_write_zoomed_stencil_span(ctx
, imgX
, imgY
, width
,
946 x
, y
+ i
, stencilValues
);
948 _swrast_write_stencil_span(ctx
, width
, x
, y
+ i
, stencilValues
);
957 * Execute software-based glDrawPixels.
958 * By time we get here, all error checking will have been done.
961 _swrast_DrawPixels( GLcontext
*ctx
,
963 GLsizei width
, GLsizei height
,
964 GLenum format
, GLenum type
,
965 const struct gl_pixelstore_attrib
*unpack
,
966 const GLvoid
*pixels
)
968 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
970 if (swrast
->NewState
)
971 _swrast_validate_derived( ctx
);
973 if (unpack
->BufferObj
->Name
) {
974 /* unpack from PBO */
976 if (!_mesa_validate_pbo_access(2, unpack
, width
, height
, 1,
977 format
, type
, pixels
)) {
978 _mesa_error(ctx
, GL_INVALID_OPERATION
,
979 "glDrawPixels(invalid PBO access)");
982 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
986 /* buffer is already mapped - that's an error */
987 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glDrawPixels(PBO is mapped)");
990 pixels
= ADD_POINTERS(buf
, pixels
);
993 RENDER_START(swrast
,ctx
);
996 case GL_STENCIL_INDEX
:
997 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
999 case GL_DEPTH_COMPONENT
:
1000 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
1002 case GL_COLOR_INDEX
:
1003 if (ctx
->Visual
.rgbMode
)
1004 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, unpack
, pixels
);
1006 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
1013 case GL_LUMINANCE_ALPHA
:
1019 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
);
1021 case GL_DEPTH_STENCIL_EXT
:
1022 draw_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
1023 type
, unpack
, pixels
);
1026 _mesa_problem(ctx
, "unexpected format in _swrast_DrawPixels");
1027 /* don't return yet, clean-up */
1030 RENDER_FINISH(swrast
,ctx
);
1032 if (unpack
->BufferObj
->Name
) {
1033 /* done with PBO so unmap it now */
1034 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
1041 #if 0 /* experimental */
1043 * Execute glDrawDepthPixelsMESA().
1046 _swrast_DrawDepthPixelsMESA( GLcontext
*ctx
,
1048 GLsizei width
, GLsizei height
,
1049 GLenum colorFormat
, GLenum colorType
,
1050 const GLvoid
*colors
,
1051 GLenum depthType
, const GLvoid
*depths
,
1052 const struct gl_pixelstore_attrib
*unpack
)
1054 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1056 if (swrast
->NewState
)
1057 _swrast_validate_derived( ctx
);
1059 RENDER_START(swrast
,ctx
);
1061 switch (colorFormat
) {
1062 case GL_COLOR_INDEX
:
1063 if (ctx
->Visual
.rgbMode
)
1064 draw_rgba_pixels(ctx
, x
,y
, width
, height
, colorFormat
, colorType
,
1067 draw_index_pixels(ctx
, x
, y
, width
, height
, colorType
,
1075 case GL_LUMINANCE_ALPHA
:
1081 draw_rgba_pixels(ctx
, x
, y
, width
, height
, colorFormat
, colorType
,
1085 _mesa_problem(ctx
, "unexpected format in glDrawDepthPixelsMESA");
1088 RENDER_FINISH(swrast
,ctx
);