2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 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"
36 #include "s_context.h"
37 #include "s_drawpix.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
,
54 const GLint imgX
= x
, imgY
= y
;
55 struct gl_renderbuffer
*rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
56 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
59 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
61 if (swrast
->_RasterMask
& MULTI_DRAW_BIT
)
64 if (ctx
->_ImageTransferState
) {
65 /* don't handle any pixel transfer options here */
70 _swrast_span_default_z(ctx
, &span
);
71 if (swrast
->_FogEnabled
)
72 _swrast_span_default_fog(ctx
, &span
);
73 if (ctx
->Texture
._EnabledCoordUnits
)
74 _swrast_span_default_texcoords(ctx
, &span
);
76 if ((swrast
->_RasterMask
& ~CLIP_BIT
) == 0
77 && ctx
->Texture
._EnabledCoordUnits
== 0
78 && unpack
->Alignment
== 1 /* XXX may not really need this */
80 && !unpack
->LsbFirst
) {
82 /* XXX there's a lot of clipping code here that should be replaced
83 * by a call to _mesa_clip_drawpixels().
87 GLint drawWidth
= width
; /* actual width drawn */
88 GLint drawHeight
= height
; /* actual height drawn */
89 GLint skipPixels
= unpack
->SkipPixels
;
90 GLint skipRows
= unpack
->SkipRows
;
93 if (unpack
->RowLength
> 0)
94 rowLength
= unpack
->RowLength
;
98 /* If we're not using pixel zoom then do all clipping calculations
99 * now. Otherwise, we'll let the _swrast_write_zoomed_*_span() functions
100 * handle the clipping.
102 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
103 /* horizontal clipping */
104 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
105 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
106 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
107 destX
= ctx
->DrawBuffer
->_Xmin
;
109 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
110 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
114 /* vertical clipping */
115 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
116 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
117 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
118 destY
= ctx
->DrawBuffer
->_Ymin
;
120 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
121 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
125 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
126 /* upside-down image */
127 /* horizontal clipping */
128 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
129 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
130 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
131 destX
= ctx
->DrawBuffer
->_Xmin
;
133 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
134 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
138 /* vertical clipping */
139 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
140 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
141 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
142 destY
= ctx
->DrawBuffer
->_Ymax
;
144 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
145 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
150 if (drawWidth
> MAX_WIDTH
)
151 return GL_FALSE
; /* fall back to general case path */
157 * The window region at (destX, destY) of size (drawWidth, drawHeight)
158 * will be written to.
159 * We'll take pixel data from buffer pointed to by "pixels" but we'll
160 * skip "skipRows" rows and skip "skipPixels" pixels/row.
163 if (format
== GL_RGBA
&& type
== CHAN_TYPE
) {
164 if (ctx
->Visual
.rgbMode
) {
165 const GLchan
*src
= (const GLchan
*) pixels
166 + (skipRows
* rowLength
+ skipPixels
) * 4;
167 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
170 for (row
=0; row
<drawHeight
; row
++) {
171 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
172 src
+= rowLength
* 4;
176 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
179 for (row
=0; row
<drawHeight
; row
++) {
181 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
182 src
+= rowLength
* 4;
188 for (row
=0; row
<drawHeight
; row
++) {
190 span
.y
= destY
+ row
;
191 span
.end
= drawWidth
;
192 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
193 (CONST
GLchan (*)[4]) src
);
194 src
+= rowLength
* 4;
200 else if (format
== GL_RGB
&& type
== CHAN_TYPE
) {
201 if (ctx
->Visual
.rgbMode
) {
202 const GLchan
*src
= (const GLchan
*) pixels
203 + (skipRows
* rowLength
+ skipPixels
) * 3;
204 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
206 for (row
=0; row
<drawHeight
; row
++) {
207 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
208 src
+= rowLength
* 3;
212 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
215 for (row
=0; row
<drawHeight
; row
++) {
217 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
218 src
+= rowLength
* 3;
224 for (row
=0; row
<drawHeight
; row
++) {
227 span
.end
= drawWidth
;
228 _swrast_write_zoomed_rgb_span(ctx
, imgX
, imgY
, &span
,
229 (CONST
GLchan (*)[3]) src
);
230 src
+= rowLength
* 3;
237 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
) {
238 if (ctx
->Visual
.rgbMode
) {
239 const GLchan
*src
= (const GLchan
*) pixels
240 + (skipRows
* rowLength
+ skipPixels
);
241 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
244 ASSERT(drawWidth
<= MAX_WIDTH
);
245 for (row
=0; row
<drawHeight
; row
++) {
247 for (i
=0;i
<drawWidth
;i
++) {
248 span
.array
->rgb
[i
][0] = src
[i
];
249 span
.array
->rgb
[i
][1] = src
[i
];
250 span
.array
->rgb
[i
][2] = src
[i
];
252 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
,
253 span
.array
->rgb
, NULL
);
258 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
261 ASSERT(drawWidth
<= MAX_WIDTH
);
262 for (row
=0; row
<drawHeight
; row
++) {
264 for (i
=0;i
<drawWidth
;i
++) {
265 span
.array
->rgb
[i
][0] = src
[i
];
266 span
.array
->rgb
[i
][1] = src
[i
];
267 span
.array
->rgb
[i
][2] = src
[i
];
270 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
271 span
.array
->rgb
, NULL
);
278 ASSERT(drawWidth
<= MAX_WIDTH
);
279 for (row
=0; row
<drawHeight
; row
++) {
281 for (i
=0;i
<drawWidth
;i
++) {
282 span
.array
->rgb
[i
][0] = src
[i
];
283 span
.array
->rgb
[i
][1] = src
[i
];
284 span
.array
->rgb
[i
][2] = src
[i
];
288 span
.end
= drawWidth
;
289 _swrast_write_zoomed_rgb_span(ctx
, imgX
, imgY
, &span
,
290 (CONST
GLchan (*)[3]) span
.array
->rgb
);
298 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
) {
299 if (ctx
->Visual
.rgbMode
) {
300 const GLchan
*src
= (const GLchan
*) pixels
301 + (skipRows
* rowLength
+ skipPixels
)*2;
302 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
305 ASSERT(drawWidth
<= MAX_WIDTH
);
306 for (row
=0; row
<drawHeight
; row
++) {
308 const GLchan
*ptr
= src
;
309 for (i
=0;i
<drawWidth
;i
++) {
310 span
.array
->rgba
[i
][0] = *ptr
;
311 span
.array
->rgba
[i
][1] = *ptr
;
312 span
.array
->rgba
[i
][2] = *ptr
++;
313 span
.array
->rgba
[i
][3] = *ptr
++;
315 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
316 span
.array
->rgba
, NULL
);
321 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
324 ASSERT(drawWidth
<= MAX_WIDTH
);
325 for (row
=0; row
<drawHeight
; row
++) {
327 const GLchan
*ptr
= src
;
328 for (i
=0;i
<drawWidth
;i
++) {
329 span
.array
->rgba
[i
][0] = *ptr
;
330 span
.array
->rgba
[i
][1] = *ptr
;
331 span
.array
->rgba
[i
][2] = *ptr
++;
332 span
.array
->rgba
[i
][3] = *ptr
++;
335 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
336 span
.array
->rgba
, NULL
);
343 ASSERT(drawWidth
<= MAX_WIDTH
);
344 for (row
=0; row
<drawHeight
; row
++) {
345 const GLchan
*ptr
= src
;
347 for (i
=0;i
<drawWidth
;i
++) {
348 span
.array
->rgba
[i
][0] = *ptr
;
349 span
.array
->rgba
[i
][1] = *ptr
;
350 span
.array
->rgba
[i
][2] = *ptr
++;
351 span
.array
->rgba
[i
][3] = *ptr
++;
355 span
.end
= drawWidth
;
356 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
357 (CONST
GLchan (*)[4]) span
.array
->rgba
);
365 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
367 (const GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
368 if (ctx
->Visual
.rgbMode
) {
369 /* convert CI data to RGBA */
370 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
373 for (row
=0; row
<drawHeight
; row
++) {
374 ASSERT(drawWidth
<= MAX_WIDTH
);
375 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
376 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
377 span
.array
->rgba
, NULL
);
383 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
386 for (row
=0; row
<drawHeight
; row
++) {
387 ASSERT(drawWidth
<= MAX_WIDTH
);
388 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
390 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
391 span
.array
->rgba
, NULL
);
399 for (row
=0; row
<drawHeight
; row
++) {
400 ASSERT(drawWidth
<= MAX_WIDTH
);
401 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
404 span
.end
= drawWidth
;
405 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
406 (CONST
GLchan (*)[4]) span
.array
->rgba
);
414 /* write CI data to CI frame buffer */
416 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
418 for (row
=0; row
<drawHeight
; row
++) {
419 GLuint index32
[MAX_WIDTH
];
421 for (col
= 0; col
< drawWidth
; col
++)
422 index32
[col
] = src
[col
];
423 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, index32
, NULL
);
436 /* can't handle this pixel format and/or data type here */
441 /* can't do a simple draw, have to use slow path */
448 * Draw color index image.
451 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
452 GLsizei width
, GLsizei height
,
454 const struct gl_pixelstore_attrib
*unpack
,
455 const GLvoid
*pixels
)
457 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
458 const GLint imgX
= x
, imgY
= y
;
459 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
460 GLint row
, skipPixels
;
463 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_INDEX
);
466 _swrast_span_default_z(ctx
, &span
);
467 if (swrast
->_FogEnabled
)
468 _swrast_span_default_fog(ctx
, &span
);
474 while (skipPixels
< width
) {
475 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
476 ASSERT(spanWidth
<= MAX_WIDTH
);
477 for (row
= 0; row
< height
; row
++) {
478 const GLvoid
*source
= _mesa_image_address2d(unpack
, pixels
,
480 GL_COLOR_INDEX
, type
,
482 _mesa_unpack_index_span(ctx
, spanWidth
, GL_UNSIGNED_INT
,
483 span
.array
->index
, type
, source
, unpack
,
484 ctx
->_ImageTransferState
);
486 /* These may get changed during writing/clipping */
487 span
.x
= x
+ skipPixels
;
489 span
.end
= spanWidth
;
492 _swrast_write_zoomed_index_span(ctx
, imgX
, imgY
, &span
);
494 _swrast_write_index_span(ctx
, &span
);
496 skipPixels
+= spanWidth
;
503 * Draw stencil image.
506 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
507 GLsizei width
, GLsizei height
,
509 const struct gl_pixelstore_attrib
*unpack
,
510 const GLvoid
*pixels
)
512 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
515 /* if width > MAX_WIDTH, have to process image in chunks */
517 while (skipPixels
< width
) {
518 const GLint spanX
= x
+ skipPixels
;
519 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
521 for (row
= 0; row
< height
; row
++) {
522 const GLint spanY
= y
+ row
;
523 GLstencil values
[MAX_WIDTH
];
524 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
525 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
526 const GLvoid
*source
= _mesa_image_address2d(unpack
, pixels
,
528 GL_COLOR_INDEX
, type
,
530 _mesa_unpack_index_span(ctx
, spanWidth
, destType
, values
,
531 type
, source
, unpack
,
532 ctx
->_ImageTransferState
);
533 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
534 _mesa_shift_and_offset_stencil(ctx
, spanWidth
, values
);
536 if (ctx
->Pixel
.MapStencilFlag
) {
537 _mesa_map_stencil(ctx
, spanWidth
, values
);
541 _swrast_write_zoomed_stencil_span(ctx
, x
, y
, spanWidth
,
542 spanX
, spanY
, values
);
545 _swrast_write_stencil_span(ctx
, spanWidth
, spanX
, spanY
, values
);
548 skipPixels
+= spanWidth
;
557 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
558 GLsizei width
, GLsizei height
,
560 const struct gl_pixelstore_attrib
*unpack
,
561 const GLvoid
*pixels
)
563 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
564 const GLboolean scaleOrBias
565 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
566 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
569 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_Z
);
571 _swrast_span_default_color(ctx
, &span
);
573 if (swrast
->_FogEnabled
)
574 _swrast_span_default_fog(ctx
, &span
);
575 if (ctx
->Texture
._EnabledCoordUnits
)
576 _swrast_span_default_texcoords(ctx
, &span
);
578 if (type
== GL_UNSIGNED_SHORT
579 && ctx
->DrawBuffer
->Visual
.depthBits
== 16
582 && ctx
->Visual
.rgbMode
583 && width
<= MAX_WIDTH
) {
584 /* Special case: directly write 16-bit depth values */
586 for (row
= 0; row
< height
; row
++) {
587 const GLushort
*zSrc
= (const GLushort
*)
588 _mesa_image_address2d(unpack
, pixels
, width
, height
,
589 GL_DEPTH_COMPONENT
, type
, row
, 0);
591 for (i
= 0; i
< width
; i
++)
592 span
.array
->z
[i
] = zSrc
[i
];
596 _swrast_write_rgba_span(ctx
, &span
);
599 else if (type
== GL_UNSIGNED_INT
602 && ctx
->Visual
.rgbMode
603 && width
<= MAX_WIDTH
) {
604 /* Special case: shift 32-bit values down to Visual.depthBits */
605 const GLint shift
= 32 - ctx
->DrawBuffer
->Visual
.depthBits
;
607 for (row
= 0; row
< height
; row
++) {
608 const GLuint
*zSrc
= (const GLuint
*)
609 _mesa_image_address2d(unpack
, pixels
, width
, height
,
610 GL_DEPTH_COMPONENT
, type
, row
, 0);
612 _mesa_memcpy(span
.array
->z
, zSrc
, width
* sizeof(GLuint
));
616 for (col
= 0; col
< width
; col
++)
617 span
.array
->z
[col
] = zSrc
[col
] >> shift
;
622 _swrast_write_rgba_span(ctx
, &span
);
627 const GLfloat depthMax
= ctx
->DrawBuffer
->_DepthMaxF
;
628 GLint skipPixels
= 0;
630 /* in case width > MAX_WIDTH do the copy in chunks */
631 while (skipPixels
< width
) {
632 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
634 ASSERT(span
.end
<= MAX_WIDTH
);
635 for (row
= 0; row
< height
; row
++) {
636 const GLvoid
*zSrc
= _mesa_image_address2d(unpack
,
637 pixels
, width
, height
,
638 GL_DEPTH_COMPONENT
, type
,
641 /* Set these for each row since the _swrast_write_* function may
642 * change them while clipping.
644 span
.x
= x
+ skipPixels
;
646 span
.end
= spanWidth
;
648 _mesa_unpack_depth_span(ctx
, spanWidth
,
649 GL_UNSIGNED_INT
, span
.array
->z
, depthMax
,
652 _swrast_write_zoomed_depth_span(ctx
, x
, y
, &span
);
654 else if (ctx
->Visual
.rgbMode
) {
655 _swrast_write_rgba_span(ctx
, &span
);
658 _swrast_write_index_span(ctx
, &span
);
661 skipPixels
+= spanWidth
;
672 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
673 GLsizei width
, GLsizei height
,
674 GLenum format
, GLenum type
,
675 const struct gl_pixelstore_attrib
*unpack
,
676 const GLvoid
*pixels
)
678 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
679 const GLint imgX
= x
, imgY
= y
;
680 struct gl_renderbuffer
*rb
= NULL
; /* only used for quickDraw path */
681 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
683 GLfloat
*convImage
= NULL
;
684 GLuint transferOps
= ctx
->_ImageTransferState
;
687 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
689 /* Try an optimized glDrawPixels first */
690 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
))
694 _swrast_span_default_z(ctx
, &span
);
695 if (swrast
->_FogEnabled
)
696 _swrast_span_default_fog(ctx
, &span
);
697 if (ctx
->Texture
._EnabledCoordUnits
)
698 _swrast_span_default_texcoords(ctx
, &span
);
700 if (swrast
->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
701 && x
+ width
<= (GLint
) ctx
->DrawBuffer
->Width
702 && y
+ height
<= (GLint
) ctx
->DrawBuffer
->Height
703 && ctx
->DrawBuffer
->_NumColorDrawBuffers
[0] == 1) {
705 rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
708 quickDraw
= GL_FALSE
;
712 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
713 /* Convolution has to be handled specially. We'll create an
714 * intermediate image, applying all pixel transfer operations
715 * up to convolution. Then we'll convolve the image. Then
716 * we'll proceed with the rest of the transfer operations and
717 * rasterize the image.
720 GLfloat
*dest
, *tmpImage
;
722 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
724 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
727 convImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
729 _mesa_free(tmpImage
);
730 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
734 /* Unpack the image and apply transfer ops up to convolution */
736 for (row
= 0; row
< height
; row
++) {
737 const GLvoid
*source
= _mesa_image_address2d(unpack
,
738 pixels
, width
, height
, format
, type
, row
, 0);
739 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
, (GLfloat
*) dest
,
740 format
, type
, source
, unpack
,
741 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
);
746 if (ctx
->Pixel
.Convolution2DEnabled
) {
747 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
750 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
751 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
753 _mesa_free(tmpImage
);
755 /* continue transfer ops and draw the convolved image */
756 unpack
= &ctx
->DefaultPacking
;
760 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
767 const GLbitfield interpMask
= span
.interpMask
;
768 const GLbitfield arrayMask
= span
.arrayMask
;
769 GLint skipPixels
= 0;
771 /* if the span is wider than MAX_WIDTH we have to do it in chunks */
772 while (skipPixels
< width
) {
773 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
776 ASSERT(span
.end
<= MAX_WIDTH
);
778 for (row
= 0; row
< height
; row
++) {
779 const GLvoid
*source
= _mesa_image_address2d(unpack
,
780 pixels
, width
, height
, format
, type
, row
, skipPixels
);
782 /* Set these for each row since the _swrast_write_* function may
783 * change them while clipping.
785 span
.x
= x
+ skipPixels
;
787 span
.end
= spanWidth
;
788 span
.arrayMask
= arrayMask
;
789 span
.interpMask
= interpMask
;
791 _mesa_unpack_color_span_chan(ctx
, spanWidth
, GL_RGBA
,
792 (GLchan
*) span
.array
->rgba
,
793 format
, type
, source
, unpack
,
796 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
797 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
802 rb
->PutRow(ctx
, rb
, span
.end
, span
.x
, span
.y
,
803 span
.array
->rgba
, NULL
);
806 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
807 (CONST
GLchan (*)[4]) span
.array
->rgba
);
810 _swrast_write_rgba_span(ctx
, &span
);
814 skipPixels
+= spanWidth
;
819 _mesa_free(convImage
);
825 * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
826 * The only per-pixel operations that apply are depth scale/bias,
827 * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
829 * Also, only the depth buffer and stencil buffers are touched, not the
833 draw_depth_stencil_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
834 GLsizei width
, GLsizei height
, GLenum type
,
835 const struct gl_pixelstore_attrib
*unpack
,
836 const GLvoid
*pixels
)
838 const GLint imgX
= x
, imgY
= y
;
839 const GLboolean scaleOrBias
840 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
841 const GLfloat depthScale
= ctx
->DrawBuffer
->_DepthMaxF
;
842 const GLuint stencilMask
= ctx
->Stencil
.WriteMask
[0];
843 const GLuint stencilType
= (STENCIL_BITS
== 8) ?
844 GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
845 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
846 struct gl_renderbuffer
*depthRb
, *stencilRb
;
847 struct gl_pixelstore_attrib clippedUnpack
= *unpack
;
850 if (!_mesa_clip_drawpixels(ctx
, &x
, &y
, &width
, &height
,
852 /* totally clipped */
857 depthRb
= ctx
->ReadBuffer
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
858 stencilRb
= ctx
->ReadBuffer
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
862 if (depthRb
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
&&
863 stencilRb
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
&&
864 depthRb
== stencilRb
&&
868 (stencilMask
& 0xff) == 0xff) {
869 /* This is the ideal case.
870 * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer.
871 * Plus, no pixel transfer ops, zooming, or masking needed.
874 for (i
= 0; i
< height
; i
++) {
875 const GLuint
*src
= (const GLuint
*)
876 _mesa_image_address2d(&clippedUnpack
, pixels
, width
, height
,
877 GL_DEPTH_STENCIL_EXT
, type
, i
, 0);
878 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, src
, NULL
);
882 /* sub-optimal cases:
883 * Separate depth/stencil buffers, or pixel transfer ops required.
885 /* XXX need to handle very wide images (skippixels) */
888 depthRb
= ctx
->DrawBuffer
->_DepthBuffer
;
889 stencilRb
= ctx
->DrawBuffer
->_StencilBuffer
;
891 for (i
= 0; i
< height
; i
++) {
892 const GLuint
*depthStencilSrc
= (const GLuint
*)
893 _mesa_image_address2d(&clippedUnpack
, pixels
, width
, height
,
894 GL_DEPTH_STENCIL_EXT
, type
, i
, 0);
896 if (ctx
->Depth
.Mask
) {
897 if (!scaleOrBias
&& ctx
->DrawBuffer
->Visual
.depthBits
== 24) {
898 /* fast path 24-bit zbuffer */
899 GLuint zValues
[MAX_WIDTH
];
901 ASSERT(depthRb
->DataType
== GL_UNSIGNED_INT
);
902 for (j
= 0; j
< width
; j
++) {
903 zValues
[j
] = depthStencilSrc
[j
] >> 8;
906 _swrast_write_zoomed_z_span(ctx
, imgX
, imgY
, width
,
909 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, zValues
,NULL
);
911 else if (!scaleOrBias
&& ctx
->DrawBuffer
->Visual
.depthBits
== 16) {
912 /* fast path 16-bit zbuffer */
913 GLushort zValues
[MAX_WIDTH
];
915 ASSERT(depthRb
->DataType
== GL_UNSIGNED_SHORT
);
916 for (j
= 0; j
< width
; j
++) {
917 zValues
[j
] = depthStencilSrc
[j
] >> 16;
920 _swrast_write_zoomed_z_span(ctx
, imgX
, imgY
, width
,
923 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, zValues
,NULL
);
927 GLuint zValues
[MAX_WIDTH
]; /* 16 or 32-bit Z value storage */
928 _mesa_unpack_depth_span(ctx
, width
,
929 depthRb
->DataType
, zValues
, depthScale
,
930 type
, depthStencilSrc
, &clippedUnpack
);
932 _swrast_write_zoomed_z_span(ctx
, imgX
, imgY
, width
, x
,
936 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, zValues
,NULL
);
941 if (stencilMask
!= 0x0) {
942 GLstencil stencilValues
[MAX_WIDTH
];
943 /* get stencil values, with shift/offset/mapping */
944 _mesa_unpack_stencil_span(ctx
, width
, stencilType
, stencilValues
,
945 type
, depthStencilSrc
, &clippedUnpack
,
946 ctx
->_ImageTransferState
);
948 _swrast_write_zoomed_stencil_span(ctx
, imgX
, imgY
, width
,
949 x
, y
+ i
, stencilValues
);
951 _swrast_write_stencil_span(ctx
, width
, x
, y
+ i
, stencilValues
);
960 * Execute software-based glDrawPixels.
961 * By time we get here, all error checking will have been done.
964 _swrast_DrawPixels( GLcontext
*ctx
,
966 GLsizei width
, GLsizei height
,
967 GLenum format
, GLenum type
,
968 const struct gl_pixelstore_attrib
*unpack
,
969 const GLvoid
*pixels
)
971 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
973 RENDER_START(swrast
,ctx
);
976 _mesa_update_state(ctx
);
978 if (swrast
->NewState
)
979 _swrast_validate_derived( ctx
);
981 if (unpack
->BufferObj
->Name
) {
982 /* unpack from PBO */
984 if (!_mesa_validate_pbo_access(2, unpack
, width
, height
, 1,
985 format
, type
, pixels
)) {
986 _mesa_error(ctx
, GL_INVALID_OPERATION
,
987 "glDrawPixels(invalid PBO access)");
990 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
994 /* buffer is already mapped - that's an error */
995 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glDrawPixels(PBO is mapped)");
998 pixels
= ADD_POINTERS(buf
, pixels
);
1002 case GL_STENCIL_INDEX
:
1003 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
1005 case GL_DEPTH_COMPONENT
:
1006 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
1008 case GL_COLOR_INDEX
:
1009 if (ctx
->Visual
.rgbMode
)
1010 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, unpack
, pixels
);
1012 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
1019 case GL_LUMINANCE_ALPHA
:
1025 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
);
1027 case GL_DEPTH_STENCIL_EXT
:
1028 draw_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
1029 type
, unpack
, pixels
);
1032 _mesa_problem(ctx
, "unexpected format in _swrast_DrawPixels");
1033 /* don't return yet, clean-up */
1038 RENDER_FINISH(swrast
,ctx
);
1040 if (unpack
->BufferObj
->Name
) {
1041 /* done with PBO so unmap it now */
1042 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
1049 #if 0 /* experimental */
1051 * Execute glDrawDepthPixelsMESA().
1054 _swrast_DrawDepthPixelsMESA( GLcontext
*ctx
,
1056 GLsizei width
, GLsizei height
,
1057 GLenum colorFormat
, GLenum colorType
,
1058 const GLvoid
*colors
,
1059 GLenum depthType
, const GLvoid
*depths
,
1060 const struct gl_pixelstore_attrib
*unpack
)
1062 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1064 if (swrast
->NewState
)
1065 _swrast_validate_derived( ctx
);
1067 RENDER_START(swrast
,ctx
);
1069 switch (colorFormat
) {
1070 case GL_COLOR_INDEX
:
1071 if (ctx
->Visual
.rgbMode
)
1072 draw_rgba_pixels(ctx
, x
,y
, width
, height
, colorFormat
, colorType
,
1075 draw_index_pixels(ctx
, x
, y
, width
, height
, colorType
,
1083 case GL_LUMINANCE_ALPHA
:
1089 draw_rgba_pixels(ctx
, x
, y
, width
, height
, colorFormat
, colorType
,
1093 _mesa_problem(ctx
, "unexpected format in glDrawDepthPixelsMESA");
1096 RENDER_FINISH(swrast
,ctx
);