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"
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
,
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
)
65 _swrast_span_default_z(ctx
, &span
);
66 if (swrast
->_FogEnabled
)
67 _swrast_span_default_fog(ctx
, &span
);
68 if (ctx
->Texture
._EnabledCoordUnits
)
69 _swrast_span_default_texcoords(ctx
, &span
);
71 if ((SWRAST_CONTEXT(ctx
)->_RasterMask
& ~CLIP_BIT
) == 0
72 && ctx
->Texture
._EnabledCoordUnits
== 0
73 && unpack
->Alignment
== 1
75 && !unpack
->LsbFirst
) {
77 /* XXX there's a lot of clipping code here that should be replaced
78 * by a call to _mesa_clip_drawpixels().
82 GLint drawWidth
= width
; /* actual width drawn */
83 GLint drawHeight
= height
; /* actual height drawn */
84 GLint skipPixels
= unpack
->SkipPixels
;
85 GLint skipRows
= unpack
->SkipRows
;
88 if (unpack
->RowLength
> 0)
89 rowLength
= unpack
->RowLength
;
93 /* If we're not using pixel zoom then do all clipping calculations
94 * now. Otherwise, we'll let the _swrast_write_zoomed_*_span() functions
95 * handle the clipping.
97 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
98 /* horizontal clipping */
99 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
100 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
101 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
102 destX
= ctx
->DrawBuffer
->_Xmin
;
104 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
105 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
109 /* vertical clipping */
110 if (destY
< ctx
->DrawBuffer
->_Ymin
) {
111 skipRows
+= (ctx
->DrawBuffer
->_Ymin
- destY
);
112 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- destY
);
113 destY
= ctx
->DrawBuffer
->_Ymin
;
115 if (destY
+ drawHeight
> ctx
->DrawBuffer
->_Ymax
)
116 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->_Ymax
);
120 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
121 /* upside-down image */
122 /* horizontal clipping */
123 if (destX
< ctx
->DrawBuffer
->_Xmin
) {
124 skipPixels
+= (ctx
->DrawBuffer
->_Xmin
- destX
);
125 drawWidth
-= (ctx
->DrawBuffer
->_Xmin
- destX
);
126 destX
= ctx
->DrawBuffer
->_Xmin
;
128 if (destX
+ drawWidth
> ctx
->DrawBuffer
->_Xmax
)
129 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->_Xmax
);
133 /* vertical clipping */
134 if (destY
> ctx
->DrawBuffer
->_Ymax
) {
135 skipRows
+= (destY
- ctx
->DrawBuffer
->_Ymax
);
136 drawHeight
-= (destY
- ctx
->DrawBuffer
->_Ymax
);
137 destY
= ctx
->DrawBuffer
->_Ymax
;
139 if (destY
- drawHeight
< ctx
->DrawBuffer
->_Ymin
)
140 drawHeight
-= (ctx
->DrawBuffer
->_Ymin
- (destY
- drawHeight
));
145 if (drawWidth
> MAX_WIDTH
)
146 return GL_FALSE
; /* fall back to general case path */
152 * The window region at (destX, destY) of size (drawWidth, drawHeight)
153 * will be written to.
154 * We'll take pixel data from buffer pointed to by "pixels" but we'll
155 * skip "skipRows" rows and skip "skipPixels" pixels/row.
158 if (format
== GL_RGBA
&& type
== CHAN_TYPE
159 && ctx
->_ImageTransferState
==0) {
160 if (ctx
->Visual
.rgbMode
) {
161 GLchan
*src
= (GLchan
*) pixels
162 + (skipRows
* rowLength
+ skipPixels
) * 4;
163 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
166 for (row
=0; row
<drawHeight
; row
++) {
167 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
168 src
+= rowLength
* 4;
172 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
175 for (row
=0; row
<drawHeight
; row
++) {
177 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
178 src
+= rowLength
* 4;
184 for (row
=0; row
<drawHeight
; row
++) {
186 span
.y
= destY
+ row
;
187 span
.end
= drawWidth
;
188 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
189 (CONST
GLchan (*)[4]) src
);
190 src
+= rowLength
* 4;
196 else if (format
== GL_RGB
&& type
== CHAN_TYPE
197 && ctx
->_ImageTransferState
== 0) {
198 if (ctx
->Visual
.rgbMode
) {
199 GLchan
*src
= (GLchan
*) pixels
200 + (skipRows
* rowLength
+ skipPixels
) * 3;
201 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
203 for (row
=0; row
<drawHeight
; row
++) {
204 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
205 src
+= rowLength
* 3;
209 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
212 for (row
=0; row
<drawHeight
; row
++) {
214 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
, src
, NULL
);
215 src
+= rowLength
* 3;
221 for (row
=0; row
<drawHeight
; row
++) {
224 span
.end
= drawWidth
;
225 _swrast_write_zoomed_rgb_span(ctx
, imgX
, imgY
, &span
,
226 (CONST
GLchan (*)[3]) src
);
227 src
+= rowLength
* 3;
234 else if (format
== GL_LUMINANCE
&& type
== CHAN_TYPE
235 && ctx
->_ImageTransferState
==0) {
236 if (ctx
->Visual
.rgbMode
) {
237 GLchan
*src
= (GLchan
*) pixels
238 + (skipRows
* rowLength
+ skipPixels
);
239 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
242 ASSERT(drawWidth
<= MAX_WIDTH
);
243 for (row
=0; row
<drawHeight
; row
++) {
245 for (i
=0;i
<drawWidth
;i
++) {
246 span
.array
->rgb
[i
][0] = src
[i
];
247 span
.array
->rgb
[i
][1] = src
[i
];
248 span
.array
->rgb
[i
][2] = src
[i
];
250 rb
->PutRowRGB(ctx
, rb
, drawWidth
, destX
, destY
,
251 span
.array
->rgb
, NULL
);
256 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
259 ASSERT(drawWidth
<= MAX_WIDTH
);
260 for (row
=0; row
<drawHeight
; row
++) {
262 for (i
=0;i
<drawWidth
;i
++) {
263 span
.array
->rgb
[i
][0] = src
[i
];
264 span
.array
->rgb
[i
][1] = src
[i
];
265 span
.array
->rgb
[i
][2] = src
[i
];
268 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
269 span
.array
->rgb
, NULL
);
276 ASSERT(drawWidth
<= MAX_WIDTH
);
277 for (row
=0; row
<drawHeight
; row
++) {
279 for (i
=0;i
<drawWidth
;i
++) {
280 span
.array
->rgb
[i
][0] = src
[i
];
281 span
.array
->rgb
[i
][1] = src
[i
];
282 span
.array
->rgb
[i
][2] = src
[i
];
286 span
.end
= drawWidth
;
287 _swrast_write_zoomed_rgb_span(ctx
, imgX
, imgY
, &span
,
288 (CONST
GLchan (*)[3]) span
.array
->rgb
);
296 else if (format
== GL_LUMINANCE_ALPHA
&& type
== CHAN_TYPE
297 && ctx
->_ImageTransferState
== 0) {
298 if (ctx
->Visual
.rgbMode
) {
299 GLchan
*src
= (GLchan
*) pixels
300 + (skipRows
* rowLength
+ skipPixels
)*2;
301 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
304 ASSERT(drawWidth
<= MAX_WIDTH
);
305 for (row
=0; row
<drawHeight
; row
++) {
308 for (i
=0;i
<drawWidth
;i
++) {
309 span
.array
->rgba
[i
][0] = *ptr
;
310 span
.array
->rgba
[i
][1] = *ptr
;
311 span
.array
->rgba
[i
][2] = *ptr
++;
312 span
.array
->rgba
[i
][3] = *ptr
++;
314 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
315 span
.array
->rgba
, NULL
);
320 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
323 ASSERT(drawWidth
<= MAX_WIDTH
);
324 for (row
=0; row
<drawHeight
; row
++) {
327 for (i
=0;i
<drawWidth
;i
++) {
328 span
.array
->rgba
[i
][0] = *ptr
;
329 span
.array
->rgba
[i
][1] = *ptr
;
330 span
.array
->rgba
[i
][2] = *ptr
++;
331 span
.array
->rgba
[i
][3] = *ptr
++;
334 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
335 span
.array
->rgba
, NULL
);
342 ASSERT(drawWidth
<= MAX_WIDTH
);
343 for (row
=0; row
<drawHeight
; row
++) {
346 for (i
=0;i
<drawWidth
;i
++) {
347 span
.array
->rgba
[i
][0] = *ptr
;
348 span
.array
->rgba
[i
][1] = *ptr
;
349 span
.array
->rgba
[i
][2] = *ptr
++;
350 span
.array
->rgba
[i
][3] = *ptr
++;
354 span
.end
= drawWidth
;
355 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
356 (CONST
GLchan (*)[4]) span
.array
->rgba
);
364 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
365 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
366 if (ctx
->Visual
.rgbMode
) {
367 /* convert CI data to RGBA */
368 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
371 for (row
=0; row
<drawHeight
; row
++) {
372 ASSERT(drawWidth
<= MAX_WIDTH
);
373 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
374 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
375 span
.array
->rgba
, NULL
);
381 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
384 for (row
=0; row
<drawHeight
; row
++) {
385 ASSERT(drawWidth
<= MAX_WIDTH
);
386 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
388 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
,
389 span
.array
->rgba
, NULL
);
397 for (row
=0; row
<drawHeight
; row
++) {
398 ASSERT(drawWidth
<= MAX_WIDTH
);
399 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, span
.array
->rgba
);
402 span
.end
= drawWidth
;
403 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
404 (CONST
GLchan (*)[4]) span
.array
->rgba
);
411 else if (ctx
->_ImageTransferState
==0) {
412 /* write CI data to CI frame buffer */
414 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
416 for (row
=0; row
<drawHeight
; row
++) {
417 GLuint index32
[MAX_WIDTH
];
419 for (col
= 0; col
< drawWidth
; col
++)
420 index32
[col
] = src
[col
];
421 rb
->PutRow(ctx
, rb
, drawWidth
, destX
, destY
, index32
, NULL
);
434 /* can't handle this pixel format and/or data type here */
439 /* can't do a simple draw, have to use slow path */
446 * Draw color index image.
449 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
450 GLsizei width
, GLsizei height
,
452 const struct gl_pixelstore_attrib
*unpack
,
453 const GLvoid
*pixels
)
455 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
456 const GLint imgX
= x
, imgY
= y
;
457 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
458 GLint row
, skipPixels
;
461 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_INDEX
);
464 _swrast_span_default_z(ctx
, &span
);
465 if (swrast
->_FogEnabled
)
466 _swrast_span_default_fog(ctx
, &span
);
472 while (skipPixels
< width
) {
473 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
474 ASSERT(spanWidth
<= MAX_WIDTH
);
475 for (row
= 0; row
< height
; row
++) {
476 const GLvoid
*source
= _mesa_image_address2d(unpack
, pixels
,
478 GL_COLOR_INDEX
, type
,
480 _mesa_unpack_index_span(ctx
, spanWidth
, GL_UNSIGNED_INT
,
481 span
.array
->index
, type
, source
, unpack
,
482 ctx
->_ImageTransferState
);
484 /* These may get changed during writing/clipping */
485 span
.x
= x
+ skipPixels
;
487 span
.end
= spanWidth
;
490 _swrast_write_zoomed_index_span(ctx
, imgX
, imgY
, &span
);
492 _swrast_write_index_span(ctx
, &span
);
494 skipPixels
+= spanWidth
;
501 * Draw stencil image.
504 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
505 GLsizei width
, GLsizei height
,
507 const struct gl_pixelstore_attrib
*unpack
,
508 const GLvoid
*pixels
)
510 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
513 /* if width > MAX_WIDTH, have to process image in chunks */
515 while (skipPixels
< width
) {
516 const GLint spanX
= x
+ skipPixels
;
517 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
519 for (row
= 0; row
< height
; row
++) {
520 const GLint spanY
= y
+ row
;
521 GLstencil values
[MAX_WIDTH
];
522 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
523 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
524 const GLvoid
*source
= _mesa_image_address2d(unpack
, pixels
,
526 GL_COLOR_INDEX
, type
,
528 _mesa_unpack_index_span(ctx
, spanWidth
, destType
, values
,
529 type
, source
, unpack
,
530 ctx
->_ImageTransferState
);
531 if (ctx
->_ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
532 _mesa_shift_and_offset_stencil(ctx
, spanWidth
, values
);
534 if (ctx
->Pixel
.MapStencilFlag
) {
535 _mesa_map_stencil(ctx
, spanWidth
, values
);
539 _swrast_write_zoomed_stencil_span(ctx
, x
, y
, spanWidth
,
540 spanX
, spanY
, values
);
543 _swrast_write_stencil_span(ctx
, spanWidth
, spanX
, spanY
, values
);
546 skipPixels
+= spanWidth
;
555 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
556 GLsizei width
, GLsizei height
,
558 const struct gl_pixelstore_attrib
*unpack
,
559 const GLvoid
*pixels
)
561 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
562 const GLboolean scaleOrBias
563 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
564 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
567 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_Z
);
569 _swrast_span_default_color(ctx
, &span
);
571 if (swrast
->_FogEnabled
)
572 _swrast_span_default_fog(ctx
, &span
);
573 if (ctx
->Texture
._EnabledCoordUnits
)
574 _swrast_span_default_texcoords(ctx
, &span
);
576 if (type
== GL_UNSIGNED_SHORT
577 && ctx
->DrawBuffer
->Visual
.depthBits
== 16
580 && ctx
->Visual
.rgbMode
581 && width
<= MAX_WIDTH
) {
582 /* Special case: directly write 16-bit depth values */
584 for (row
= 0; row
< height
; row
++) {
585 const GLushort
*zSrc
= (const GLushort
*)
586 _mesa_image_address2d(unpack
, pixels
, width
, height
,
587 GL_DEPTH_COMPONENT
, type
, row
, 0);
589 for (i
= 0; i
< width
; i
++)
590 span
.array
->z
[i
] = zSrc
[i
];
594 _swrast_write_rgba_span(ctx
, &span
);
597 else if (type
== GL_UNSIGNED_INT
600 && ctx
->Visual
.rgbMode
601 && width
<= MAX_WIDTH
) {
602 /* Special case: shift 32-bit values down to Visual.depthBits */
603 const GLint shift
= 32 - ctx
->DrawBuffer
->Visual
.depthBits
;
605 for (row
= 0; row
< height
; row
++) {
606 const GLuint
*zSrc
= (const GLuint
*)
607 _mesa_image_address2d(unpack
, pixels
, width
, height
,
608 GL_DEPTH_COMPONENT
, type
, row
, 0);
610 _mesa_memcpy(span
.array
->z
, zSrc
, width
* sizeof(GLuint
));
614 for (col
= 0; col
< width
; col
++)
615 span
.array
->z
[col
] = zSrc
[col
] >> shift
;
620 _swrast_write_rgba_span(ctx
, &span
);
625 const GLfloat depthMax
= ctx
->DrawBuffer
->_DepthMaxF
;
626 GLint skipPixels
= 0;
628 /* in case width > MAX_WIDTH do the copy in chunks */
629 while (skipPixels
< width
) {
630 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
632 ASSERT(span
.end
<= MAX_WIDTH
);
633 for (row
= 0; row
< height
; row
++) {
634 const GLvoid
*zSrc
= _mesa_image_address2d(unpack
,
635 pixels
, width
, height
,
636 GL_DEPTH_COMPONENT
, type
,
639 /* Set these for each row since the _swrast_write_* function may
640 * change them while clipping.
642 span
.x
= x
+ skipPixels
;
644 span
.end
= spanWidth
;
646 _mesa_unpack_depth_span(ctx
, spanWidth
,
647 GL_UNSIGNED_INT
, span
.array
->z
, depthMax
,
650 _swrast_write_zoomed_depth_span(ctx
, x
, y
, &span
);
652 else if (ctx
->Visual
.rgbMode
) {
653 _swrast_write_rgba_span(ctx
, &span
);
656 _swrast_write_index_span(ctx
, &span
);
659 skipPixels
+= spanWidth
;
670 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
671 GLsizei width
, GLsizei height
,
672 GLenum format
, GLenum type
,
673 const struct gl_pixelstore_attrib
*unpack
,
674 const GLvoid
*pixels
)
676 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
677 const GLint imgX
= x
, imgY
= y
;
678 struct gl_renderbuffer
*rb
= NULL
; /* only used for quickDraw path */
679 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
681 GLfloat
*convImage
= NULL
;
682 GLuint transferOps
= ctx
->_ImageTransferState
;
685 INIT_SPAN(span
, GL_BITMAP
, 0, 0, SPAN_RGBA
);
687 /* Try an optimized glDrawPixels first */
688 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
))
692 _swrast_span_default_z(ctx
, &span
);
693 if (swrast
->_FogEnabled
)
694 _swrast_span_default_fog(ctx
, &span
);
695 if (ctx
->Texture
._EnabledCoordUnits
)
696 _swrast_span_default_texcoords(ctx
, &span
);
698 if (SWRAST_CONTEXT(ctx
)->_RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
699 && x
+ width
<= (GLint
) ctx
->DrawBuffer
->Width
700 && y
+ height
<= (GLint
) ctx
->DrawBuffer
->Height
701 && ctx
->DrawBuffer
->_NumColorDrawBuffers
[0] == 1) {
703 rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
706 quickDraw
= GL_FALSE
;
710 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
711 /* Convolution has to be handled specially. We'll create an
712 * intermediate image, applying all pixel transfer operations
713 * up to convolution. Then we'll convolve the image. Then
714 * we'll proceed with the rest of the transfer operations and
715 * rasterize the image.
718 GLfloat
*dest
, *tmpImage
;
720 tmpImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
722 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
725 convImage
= (GLfloat
*) _mesa_malloc(width
* height
* 4 * sizeof(GLfloat
));
727 _mesa_free(tmpImage
);
728 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
732 /* Unpack the image and apply transfer ops up to convolution */
734 for (row
= 0; row
< height
; row
++) {
735 const GLvoid
*source
= _mesa_image_address2d(unpack
,
736 pixels
, width
, height
, format
, type
, row
, 0);
737 _mesa_unpack_color_span_float(ctx
, width
, GL_RGBA
, (GLfloat
*) dest
,
738 format
, type
, source
, unpack
,
739 transferOps
& IMAGE_PRE_CONVOLUTION_BITS
);
744 if (ctx
->Pixel
.Convolution2DEnabled
) {
745 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
748 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
749 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
751 _mesa_free(tmpImage
);
753 /* continue transfer ops and draw the convolved image */
754 unpack
= &ctx
->DefaultPacking
;
758 transferOps
&= IMAGE_POST_CONVOLUTION_BITS
;
765 const GLbitfield interpMask
= span
.interpMask
;
766 const GLbitfield arrayMask
= span
.arrayMask
;
767 GLint skipPixels
= 0;
769 /* if the span is wider than MAX_WIDTH we have to do it in chunks */
770 while (skipPixels
< width
) {
771 const GLint spanWidth
= MIN2(width
- skipPixels
, MAX_WIDTH
);
774 ASSERT(span
.end
<= MAX_WIDTH
);
776 for (row
= 0; row
< height
; row
++) {
777 const GLvoid
*source
= _mesa_image_address2d(unpack
,
778 pixels
, width
, height
, format
, type
, row
, skipPixels
);
780 /* Set these for each row since the _swrast_write_* function may
781 * change them while clipping.
783 span
.x
= x
+ skipPixels
;
785 span
.end
= spanWidth
;
786 span
.arrayMask
= arrayMask
;
787 span
.interpMask
= interpMask
;
789 _mesa_unpack_color_span_chan(ctx
, spanWidth
, GL_RGBA
,
790 (GLchan
*) span
.array
->rgba
,
791 format
, type
, source
, unpack
,
794 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
795 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
798 if (ctx
->Pixel
.PixelTextureEnabled
&& ctx
->Texture
._EnabledUnits
) {
799 _swrast_pixel_texture(ctx
, &span
);
804 rb
->PutRow(ctx
, rb
, span
.end
, span
.x
, span
.y
,
805 span
.array
->rgba
, NULL
);
808 _swrast_write_zoomed_rgba_span(ctx
, imgX
, imgY
, &span
,
809 (CONST
GLchan (*)[4]) span
.array
->rgba
);
812 _swrast_write_rgba_span(ctx
, &span
);
816 skipPixels
+= spanWidth
;
821 _mesa_free(convImage
);
827 * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
828 * The only per-pixel operations that apply are depth scale/bias,
829 * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
831 * Also, only the depth buffer and stencil buffers are touched, not the
835 draw_depth_stencil_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
836 GLsizei width
, GLsizei height
, GLenum type
,
837 const struct gl_pixelstore_attrib
*unpack
,
838 const GLvoid
*pixels
)
840 const GLint imgX
= x
, imgY
= y
;
841 const GLboolean scaleOrBias
=
842 ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
843 const GLfloat depthScale
= ctx
->DrawBuffer
->_DepthMaxF
;
844 const GLuint stencilMask
= ctx
->Stencil
.WriteMask
[0];
845 const GLuint stencilType
= (STENCIL_BITS
== 8) ?
846 GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
847 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!= 1.0 || ctx
->Pixel
.ZoomY
!= 1.0;
848 struct gl_renderbuffer
*depthRb
, *stencilRb
;
849 struct gl_pixelstore_attrib clippedUnpack
= *unpack
;
852 if (!_mesa_clip_drawpixels(ctx
, &x
, &y
, &width
, &height
,
854 /* totally clipped */
859 depthRb
= ctx
->ReadBuffer
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
860 stencilRb
= ctx
->ReadBuffer
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
864 if (depthRb
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
&&
865 stencilRb
->_BaseFormat
== GL_DEPTH_STENCIL_EXT
&&
866 depthRb
== stencilRb
&&
870 (stencilMask
& 0xff) == 0xff) {
871 /* This is the ideal case.
872 * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer.
873 * Plus, no pixel transfer ops, zooming, or masking needed.
876 for (i
= 0; i
< height
; i
++) {
877 const GLuint
*src
= (const GLuint
*)
878 _mesa_image_address2d(&clippedUnpack
, pixels
, width
, height
,
879 GL_DEPTH_STENCIL_EXT
, type
, i
, 0);
880 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, src
, NULL
);
884 /* sub-optimal cases:
885 * Separate depth/stencil buffers, or pixel transfer ops required.
887 /* XXX need to handle very wide images (skippixels) */
890 depthRb
= ctx
->DrawBuffer
->_DepthBuffer
;
891 stencilRb
= ctx
->DrawBuffer
->_StencilBuffer
;
893 for (i
= 0; i
< height
; i
++) {
894 const GLuint
*depthStencilSrc
= (const GLuint
*)
895 _mesa_image_address2d(&clippedUnpack
, pixels
, width
, height
,
896 GL_DEPTH_STENCIL_EXT
, type
, i
, 0);
898 if (ctx
->Depth
.Mask
) {
899 if (!scaleOrBias
&& ctx
->DrawBuffer
->Visual
.depthBits
== 24) {
900 /* fast path 24-bit zbuffer */
901 GLuint zValues
[MAX_WIDTH
];
903 ASSERT(depthRb
->DataType
== GL_UNSIGNED_INT
);
904 for (j
= 0; j
< width
; j
++) {
905 zValues
[j
] = depthStencilSrc
[j
] >> 8;
908 _swrast_write_zoomed_z_span(ctx
, imgX
, imgY
, width
,
911 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, zValues
,NULL
);
913 else if (!scaleOrBias
&& ctx
->DrawBuffer
->Visual
.depthBits
== 16) {
914 /* fast path 16-bit zbuffer */
915 GLushort zValues
[MAX_WIDTH
];
917 ASSERT(depthRb
->DataType
== GL_UNSIGNED_SHORT
);
918 for (j
= 0; j
< width
; j
++) {
919 zValues
[j
] = depthStencilSrc
[j
] >> 16;
922 _swrast_write_zoomed_z_span(ctx
, imgX
, imgY
, width
,
925 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, zValues
,NULL
);
929 GLuint zValues
[MAX_WIDTH
]; /* 16 or 32-bit Z value storage */
930 _mesa_unpack_depth_span(ctx
, width
,
931 depthRb
->DataType
, zValues
, depthScale
,
932 type
, depthStencilSrc
, &clippedUnpack
);
934 _swrast_write_zoomed_z_span(ctx
, imgX
, imgY
, width
, x
,
938 depthRb
->PutRow(ctx
, depthRb
, width
, x
, y
+ i
, zValues
,NULL
);
943 if (stencilMask
!= 0x0) {
944 GLstencil stencilValues
[MAX_WIDTH
];
945 /* get stencil values, with shift/offset/mapping */
946 _mesa_unpack_stencil_span(ctx
, width
, stencilType
, stencilValues
,
947 type
, depthStencilSrc
, &clippedUnpack
,
948 ctx
->_ImageTransferState
);
950 _swrast_write_zoomed_stencil_span(ctx
, imgX
, imgY
, width
,
951 x
, y
+ i
, stencilValues
);
953 _swrast_write_stencil_span(ctx
, width
, x
, y
+ i
, stencilValues
);
962 * Execute software-based glDrawPixels.
963 * By time we get here, all error checking will have been done.
966 _swrast_DrawPixels( GLcontext
*ctx
,
968 GLsizei width
, GLsizei height
,
969 GLenum format
, GLenum type
,
970 const struct gl_pixelstore_attrib
*unpack
,
971 const GLvoid
*pixels
)
973 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
975 if (swrast
->NewState
)
976 _swrast_validate_derived( ctx
);
978 if (unpack
->BufferObj
->Name
) {
979 /* unpack from PBO */
981 if (!_mesa_validate_pbo_access(2, unpack
, width
, height
, 1,
982 format
, type
, pixels
)) {
983 _mesa_error(ctx
, GL_INVALID_OPERATION
,
984 "glDrawPixels(invalid PBO access)");
987 buf
= (GLubyte
*) ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
991 /* buffer is already mapped - that's an error */
992 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glDrawPixels(PBO is mapped)");
995 pixels
= ADD_POINTERS(buf
, pixels
);
998 RENDER_START(swrast
,ctx
);
1001 case GL_STENCIL_INDEX
:
1002 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
1004 case GL_DEPTH_COMPONENT
:
1005 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
1007 case GL_COLOR_INDEX
:
1008 if (ctx
->Visual
.rgbMode
)
1009 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, unpack
, pixels
);
1011 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, unpack
, pixels
);
1018 case GL_LUMINANCE_ALPHA
:
1024 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, unpack
, pixels
);
1026 case GL_DEPTH_STENCIL_EXT
:
1027 draw_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
1028 type
, unpack
, pixels
);
1031 _mesa_problem(ctx
, "unexpected format in _swrast_DrawPixels");
1032 /* don't return yet, clean-up */
1035 RENDER_FINISH(swrast
,ctx
);
1037 if (unpack
->BufferObj
->Name
) {
1038 /* done with PBO so unmap it now */
1039 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_UNPACK_BUFFER_EXT
,
1046 #if 0 /* experimental */
1048 * Execute glDrawDepthPixelsMESA().
1051 _swrast_DrawDepthPixelsMESA( GLcontext
*ctx
,
1053 GLsizei width
, GLsizei height
,
1054 GLenum colorFormat
, GLenum colorType
,
1055 const GLvoid
*colors
,
1056 GLenum depthType
, const GLvoid
*depths
,
1057 const struct gl_pixelstore_attrib
*unpack
)
1059 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1061 if (swrast
->NewState
)
1062 _swrast_validate_derived( ctx
);
1064 RENDER_START(swrast
,ctx
);
1066 switch (colorFormat
) {
1067 case GL_COLOR_INDEX
:
1068 if (ctx
->Visual
.rgbMode
)
1069 draw_rgba_pixels(ctx
, x
,y
, width
, height
, colorFormat
, colorType
,
1072 draw_index_pixels(ctx
, x
, y
, width
, height
, colorType
,
1080 case GL_LUMINANCE_ALPHA
:
1086 draw_rgba_pixels(ctx
, x
, y
, width
, height
, colorFormat
, colorType
,
1090 _mesa_problem(ctx
, "unexpected format in glDrawDepthPixelsMESA");
1093 RENDER_FINISH(swrast
,ctx
);