1 /* $Id: drawpix.c,v 1.30 2000/08/23 14:32:06 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
53 * Given the dest position, size and skipPixels and skipRows values
54 * for a glDrawPixels command, perform clipping of the image bounds
55 * so the result lies withing the context's buffer bounds.
56 * Return: GL_TRUE if image is ready for drawing
57 * GL_FALSE if image was completely clipped away (draw nothing)
60 _mesa_clip_pixelrect(const GLcontext
*ctx
,
61 GLint
*destX
, GLint
*destY
,
62 GLsizei
*width
, GLsizei
*height
,
63 GLint
*skipPixels
, GLint
*skipRows
)
65 const GLframebuffer
*buffer
= ctx
->DrawBuffer
;
68 if (*destX
< buffer
->Xmin
) {
69 *skipPixels
+= (buffer
->Xmin
- *destX
);
70 *width
-= (buffer
->Xmin
- *destX
);
71 *destX
= buffer
->Xmin
;
74 if (*destX
+ *width
> buffer
->Xmax
)
75 *width
-= (*destX
+ *width
- buffer
->Xmax
- 1);
81 if (*destY
< buffer
->Ymin
) {
82 *skipRows
+= (buffer
->Ymin
- *destY
);
83 *height
-= (buffer
->Ymin
- *destY
);
84 *destY
= buffer
->Ymin
;
87 if (*destY
+ *height
> buffer
->Ymax
)
88 *height
-= (*destY
+ *height
- buffer
->Ymax
- 1);
99 * Try to do a fast and simple RGB(a) glDrawPixels.
100 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
103 fast_draw_pixels(GLcontext
*ctx
, GLint x
, GLint y
,
104 GLsizei width
, GLsizei height
,
105 GLenum format
, GLenum type
, const GLvoid
*pixels
)
107 const GLuint cantTransferBits
=
108 IMAGE_SCALE_BIAS_BIT
|
109 IMAGE_SHIFT_OFFSET_BIT
|
110 IMAGE_MAP_COLOR_BIT
|
111 IMAGE_COLOR_TABLE_BIT
|
112 IMAGE_CONVOLUTION_BIT
|
113 IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT
|
114 IMAGE_COLOR_MATRIX_BIT
|
115 IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT
|
116 IMAGE_HISTOGRAM_BIT
|
118 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
119 GLubyte rgb
[MAX_WIDTH
][3];
120 GLubyte rgba
[MAX_WIDTH
][4];
122 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx
, "glDrawPixels",
126 if (!ctx
->Current
.RasterPosValid
) {
127 return GL_TRUE
; /* no-op */
130 if ((ctx
->RasterMask
&(~(SCISSOR_BIT
|WINCLIP_BIT
)))==0
131 && (ctx
->ImageTransferState
& cantTransferBits
) == 0
132 && ctx
->Texture
.ReallyEnabled
== 0
133 && unpack
->Alignment
== 1
134 && !unpack
->SwapBytes
135 && !unpack
->LsbFirst
) {
139 GLint drawWidth
= width
; /* actual width drawn */
140 GLint drawHeight
= height
; /* actual height drawn */
141 GLint skipPixels
= unpack
->SkipPixels
;
142 GLint skipRows
= unpack
->SkipRows
;
144 GLdepth zSpan
[MAX_WIDTH
]; /* only used when zooming */
147 if (unpack
->RowLength
> 0)
148 rowLength
= unpack
->RowLength
;
152 /* If we're not using pixel zoom then do all clipping calculations
153 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions
154 * handle the clipping.
156 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
157 /* horizontal clipping */
158 if (destX
< ctx
->DrawBuffer
->Xmin
) {
159 skipPixels
+= (ctx
->DrawBuffer
->Xmin
- destX
);
160 drawWidth
-= (ctx
->DrawBuffer
->Xmin
- destX
);
161 destX
= ctx
->DrawBuffer
->Xmin
;
163 if (destX
+ drawWidth
> ctx
->DrawBuffer
->Xmax
)
164 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->Xmax
- 1);
168 /* vertical clipping */
169 if (destY
< ctx
->DrawBuffer
->Ymin
) {
170 skipRows
+= (ctx
->DrawBuffer
->Ymin
- destY
);
171 drawHeight
-= (ctx
->DrawBuffer
->Ymin
- destY
);
172 destY
= ctx
->DrawBuffer
->Ymin
;
174 if (destY
+ drawHeight
> ctx
->DrawBuffer
->Ymax
)
175 drawHeight
-= (destY
+ drawHeight
- ctx
->DrawBuffer
->Ymax
- 1);
179 zoomY0
= 0; /* not used - silence compiler warning */
181 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
182 /* upside-down image */
183 /* horizontal clipping */
184 if (destX
< ctx
->DrawBuffer
->Xmin
) {
185 skipPixels
+= (ctx
->DrawBuffer
->Xmin
- destX
);
186 drawWidth
-= (ctx
->DrawBuffer
->Xmin
- destX
);
187 destX
= ctx
->DrawBuffer
->Xmin
;
189 if (destX
+ drawWidth
> ctx
->DrawBuffer
->Xmax
)
190 drawWidth
-= (destX
+ drawWidth
- ctx
->DrawBuffer
->Xmax
- 1);
194 /* vertical clipping */
195 if (destY
> ctx
->DrawBuffer
->Ymax
) {
196 skipRows
+= (destY
- ctx
->DrawBuffer
->Ymax
- 1);
197 drawHeight
-= (destY
- ctx
->DrawBuffer
->Ymax
- 1);
198 destY
= ctx
->DrawBuffer
->Ymax
+ 1;
200 if (destY
- drawHeight
< ctx
->DrawBuffer
->Ymin
)
201 drawHeight
-= (ctx
->DrawBuffer
->Ymin
- (destY
- drawHeight
));
206 /* setup array of fragment Z value to pass to zoom function */
207 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->Visual
->DepthMaxF
);
209 ASSERT(drawWidth
< MAX_WIDTH
);
210 for (i
=0; i
<drawWidth
; i
++)
213 /* save Y value of first row */
214 zoomY0
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
220 * The window region at (destX, destY) of size (drawWidth, drawHeight)
221 * will be written to.
222 * We'll take pixel data from buffer pointed to by "pixels" but we'll
223 * skip "skipRows" rows and skip "skipPixels" pixels/row.
226 if (format
==GL_RGBA
&& type
==GL_UNSIGNED_BYTE
) {
227 if (ctx
->Visual
->RGBAflag
) {
228 GLubyte
*src
= (GLubyte
*) pixels
229 + (skipRows
* rowLength
+ skipPixels
) * 4;
230 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
233 for (row
=0; row
<drawHeight
; row
++) {
234 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
236 src
+= rowLength
* 4;
240 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
243 for (row
=0; row
<drawHeight
; row
++) {
245 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
247 src
+= rowLength
* 4;
253 for (row
=0; row
<drawHeight
; row
++) {
254 gl_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
255 zSpan
, (void *) src
, zoomY0
);
256 src
+= rowLength
* 4;
263 else if (format
==GL_RGB
&& type
==GL_UNSIGNED_BYTE
) {
264 if (ctx
->Visual
->RGBAflag
) {
265 GLubyte
*src
= (GLubyte
*) pixels
266 + (skipRows
* rowLength
+ skipPixels
) * 3;
267 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
269 for (row
=0; row
<drawHeight
; row
++) {
270 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
272 src
+= rowLength
* 3;
276 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
279 for (row
=0; row
<drawHeight
; row
++) {
281 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
283 src
+= rowLength
* 3;
289 for (row
=0; row
<drawHeight
; row
++) {
290 gl_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
291 zSpan
, (void *) src
, zoomY0
);
292 src
+= rowLength
* 3;
299 else if (format
==GL_LUMINANCE
&& type
==GL_UNSIGNED_BYTE
) {
300 if (ctx
->Visual
->RGBAflag
) {
301 GLubyte
*src
= (GLubyte
*) pixels
302 + (skipRows
* rowLength
+ skipPixels
);
303 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
306 ASSERT(drawWidth
< MAX_WIDTH
);
307 for (row
=0; row
<drawHeight
; row
++) {
309 for (i
=0;i
<drawWidth
;i
++) {
314 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
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
++) {
326 for (i
=0;i
<drawWidth
;i
++) {
332 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
340 ASSERT(drawWidth
< MAX_WIDTH
);
341 for (row
=0; row
<drawHeight
; row
++) {
343 for (i
=0;i
<drawWidth
;i
++) {
348 gl_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
349 zSpan
, (void *) rgb
, zoomY0
);
357 else if (format
==GL_LUMINANCE_ALPHA
&& type
==GL_UNSIGNED_BYTE
) {
358 if (ctx
->Visual
->RGBAflag
) {
359 GLubyte
*src
= (GLubyte
*) pixels
360 + (skipRows
* rowLength
+ skipPixels
)*2;
361 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
364 ASSERT(drawWidth
< MAX_WIDTH
);
365 for (row
=0; row
<drawHeight
; row
++) {
368 for (i
=0;i
<drawWidth
;i
++) {
374 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
375 (void *) rgba
, NULL
);
380 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
383 ASSERT(drawWidth
< MAX_WIDTH
);
384 for (row
=0; row
<drawHeight
; row
++) {
387 for (i
=0;i
<drawWidth
;i
++) {
394 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
395 (void *) rgba
, NULL
);
402 ASSERT(drawWidth
< MAX_WIDTH
);
403 for (row
=0; row
<drawHeight
; row
++) {
406 for (i
=0;i
<drawWidth
;i
++) {
412 gl_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
413 zSpan
, (void *) rgba
, zoomY0
);
421 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
422 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
423 if (ctx
->Visual
->RGBAflag
) {
424 /* convert CI data to RGBA */
425 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
428 for (row
=0; row
<drawHeight
; row
++) {
429 ASSERT(drawWidth
< MAX_WIDTH
);
430 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
431 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
432 (const GLubyte (*)[4])rgba
,
439 else if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==-1.0F
) {
442 for (row
=0; row
<drawHeight
; row
++) {
443 ASSERT(drawWidth
< MAX_WIDTH
);
444 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
446 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
447 (const GLubyte (*)[4])rgba
,
456 for (row
=0; row
<drawHeight
; row
++) {
457 ASSERT(drawWidth
< MAX_WIDTH
);
458 _mesa_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
459 gl_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
460 zSpan
, (void *) rgba
, zoomY0
);
468 /* write CI data to CI frame buffer */
470 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
472 for (row
=0; row
<drawHeight
; row
++) {
473 (*ctx
->Driver
.WriteCI8Span
)(ctx
, drawWidth
, destX
, destY
,
487 /* can't handle this pixel format and/or data type here */
492 /* can't do a simple draw, have to use slow path */
499 * Do glDrawPixels of index pixels.
502 draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
503 GLsizei width
, GLsizei height
,
504 GLenum type
, const GLvoid
*pixels
)
506 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
507 const GLint desty
= y
;
508 GLint row
, drawWidth
;
509 GLdepth zspan
[MAX_WIDTH
];
511 drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
513 /* Fragment depth values */
514 if (ctx
->Depth
.Test
|| ctx
->Fog
.Enabled
) {
515 GLdepth zval
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->Visual
->DepthMaxF
);
517 for (i
= 0; i
< drawWidth
; i
++) {
525 for (row
= 0; row
< height
; row
++, y
++) {
526 GLuint indexes
[MAX_WIDTH
];
527 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
528 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
529 _mesa_unpack_index_span(ctx
, drawWidth
, GL_UNSIGNED_INT
, indexes
,
530 type
, source
, &ctx
->Unpack
,
531 ctx
->ImageTransferState
);
533 gl_write_zoomed_index_span(ctx
, drawWidth
, x
, y
, zspan
, indexes
, desty
);
536 gl_write_index_span(ctx
, drawWidth
, x
, y
, zspan
, indexes
, GL_BITMAP
);
544 * Do glDrawPixels of stencil image. The image datatype may either
545 * be GLubyte or GLbitmap.
548 draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
549 GLsizei width
, GLsizei height
,
550 GLenum type
, const GLvoid
*pixels
)
552 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
553 const GLint desty
= y
;
554 GLint row
, drawWidth
;
556 if (type
!= GL_BYTE
&&
557 type
!= GL_UNSIGNED_BYTE
&&
559 type
!= GL_UNSIGNED_SHORT
&&
561 type
!= GL_UNSIGNED_INT
&&
564 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(stencil type)");
568 drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
570 for (row
= 0; row
< height
; row
++, y
++) {
571 GLstencil values
[MAX_WIDTH
];
572 GLenum destType
= (sizeof(GLstencil
) == sizeof(GLubyte
))
573 ? GL_UNSIGNED_BYTE
: GL_UNSIGNED_SHORT
;
574 const GLvoid
*source
= _mesa_image_address(&ctx
->Unpack
,
575 pixels
, width
, height
, GL_COLOR_INDEX
, type
, 0, row
, 0);
576 _mesa_unpack_index_span(ctx
, drawWidth
, destType
, values
,
577 type
, source
, &ctx
->Unpack
,
578 ctx
->ImageTransferState
);
579 if (ctx
->ImageTransferState
& IMAGE_SHIFT_OFFSET_BIT
) {
580 _mesa_shift_and_offset_stencil( ctx
, drawWidth
, values
);
582 if (ctx
->Pixel
.MapStencilFlag
) {
583 _mesa_map_stencil( ctx
, drawWidth
, values
);
587 gl_write_zoomed_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
,
591 _mesa_write_stencil_span( ctx
, (GLuint
) drawWidth
, x
, y
, values
);
599 * Do a glDrawPixels of depth values.
602 draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
603 GLsizei width
, GLsizei height
,
604 GLenum type
, const GLvoid
*pixels
)
606 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
607 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
608 const GLint desty
= y
;
609 GLubyte rgba
[MAX_WIDTH
][4];
610 GLuint ispan
[MAX_WIDTH
];
611 GLint drawWidth
= (width
> MAX_WIDTH
) ? MAX_WIDTH
: width
;
614 && type
!= GL_UNSIGNED_BYTE
616 && type
!= GL_UNSIGNED_SHORT
618 && type
!= GL_UNSIGNED_INT
619 && type
!= GL_FLOAT
) {
620 gl_error(ctx
, GL_INVALID_ENUM
, "glDrawPixels(type)");
624 /* Colors or indexes */
625 if (ctx
->Visual
->RGBAflag
) {
626 GLint r
= (GLint
) (ctx
->Current
.RasterColor
[0] * 255.0F
);
627 GLint g
= (GLint
) (ctx
->Current
.RasterColor
[1] * 255.0F
);
628 GLint b
= (GLint
) (ctx
->Current
.RasterColor
[2] * 255.0F
);
629 GLint a
= (GLint
) (ctx
->Current
.RasterColor
[3] * 255.0F
);
631 for (i
= 0; i
< drawWidth
; i
++) {
640 for (i
= 0; i
< drawWidth
; i
++) {
641 ispan
[i
] = ctx
->Current
.RasterIndex
;
645 if (type
==GL_UNSIGNED_SHORT
&& sizeof(GLdepth
)==sizeof(GLushort
)
646 && !bias_or_scale
&& !zoom
&& ctx
->Visual
->RGBAflag
) {
647 /* Special case: directly write 16-bit depth values */
649 for (row
= 0; row
< height
; row
++, y
++) {
650 GLdepth zspan
[MAX_WIDTH
];
651 const GLushort
*zptr
= _mesa_image_address(&ctx
->Unpack
,
652 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
654 for (i
= 0; i
< width
; i
++)
656 gl_write_rgba_span( ctx
, width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
659 else if (type
==GL_UNSIGNED_INT
&& ctx
->Visual
->DepthBits
== 32
660 && !bias_or_scale
&& !zoom
&& ctx
->Visual
->RGBAflag
) {
661 /* Special case: directly write 32-bit depth values */
663 for (row
= 0; row
< height
; row
++, y
++) {
664 const GLuint
*zptr
= _mesa_image_address(&ctx
->Unpack
,
665 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
666 gl_write_rgba_span( ctx
, width
, x
, y
, zptr
, rgba
, GL_BITMAP
);
672 for (row
= 0; row
< height
; row
++, y
++) {
673 GLdepth zspan
[MAX_WIDTH
];
674 const GLvoid
*src
= _mesa_image_address(&ctx
->Unpack
,
675 pixels
, width
, height
, GL_DEPTH_COMPONENT
, type
, 0, row
, 0);
676 _mesa_unpack_depth_span( ctx
, drawWidth
, zspan
, type
, src
,
677 &ctx
->Unpack
, ctx
->ImageTransferState
);
678 if (ctx
->Visual
->RGBAflag
) {
680 gl_write_zoomed_rgba_span(ctx
, width
, x
, y
, zspan
,
681 (const GLubyte (*)[4])rgba
, desty
);
684 gl_write_rgba_span(ctx
, width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
689 gl_write_zoomed_index_span(ctx
, width
, x
, y
, zspan
,
693 gl_write_index_span(ctx
, width
, x
, y
, zspan
, ispan
, GL_BITMAP
);
703 * Do glDrawPixels of RGBA pixels.
706 draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
707 GLsizei width
, GLsizei height
,
708 GLenum format
, GLenum type
, const GLvoid
*pixels
)
710 const struct gl_pixelstore_attrib
*unpack
= &ctx
->Unpack
;
711 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
712 const GLint desty
= y
;
713 GLdepth zspan
[MAX_WIDTH
];
715 GLfloat
*convImage
= NULL
;
716 GLuint transferOps
= ctx
->ImageTransferState
;
718 /* Try an optimized glDrawPixels first */
719 if (fast_draw_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
))
722 /* Fragment depth values */
723 if (ctx
->Depth
.Test
|| ctx
->Fog
.Enabled
) {
724 /* fill in array of z values */
725 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * ctx
->Visual
->DepthMaxF
);
727 for (i
=0;i
<width
;i
++) {
733 if (ctx
->RasterMask
== 0 && !zoom
&& x
>= 0 && y
>= 0
734 && x
+ width
<= ctx
->DrawBuffer
->Width
735 && y
+ height
<= ctx
->DrawBuffer
->Height
) {
739 quickDraw
= GL_FALSE
;
742 if (ctx
->Pixel
.Convolution2DEnabled
|| ctx
->Pixel
.Separable2DEnabled
) {
743 /* Convolution has to be handled specially. We'll create an
744 * intermediate image, applying all pixel transfer operations
745 * up to convolution. Then we'll convolve the image. Then
746 * we'll proceed with the rest of the transfer operations and
747 * rasterize the image.
749 const GLuint preConvTransferOps
=
750 IMAGE_SCALE_BIAS_BIT
|
751 IMAGE_SHIFT_OFFSET_BIT
|
752 IMAGE_MAP_COLOR_BIT
|
753 IMAGE_COLOR_TABLE_BIT
;
754 const GLuint postConvTransferOps
=
755 IMAGE_POST_CONVOLUTION_COLOR_TABLE_BIT
|
756 IMAGE_COLOR_MATRIX_BIT
|
757 IMAGE_POST_COLOR_MATRIX_COLOR_TABLE_BIT
|
758 IMAGE_HISTOGRAM_BIT
|
761 GLfloat
*dest
, *tmpImage
;
763 tmpImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
765 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
768 convImage
= (GLfloat
*) MALLOC(width
* height
* 4 * sizeof(GLfloat
));
771 gl_error(ctx
, GL_OUT_OF_MEMORY
, "glDrawPixels");
775 /* Unpack the image and apply transfer ops up to convolution */
777 for (row
= 0; row
< height
; row
++) {
778 const GLvoid
*source
= _mesa_image_address(unpack
,
779 pixels
, width
, height
, format
, type
, 0, row
, 0);
780 _mesa_unpack_float_color_span(ctx
, width
, GL_RGBA
, (void *) dest
,
781 format
, type
, source
, unpack
,
782 transferOps
& preConvTransferOps
,
788 if (ctx
->Pixel
.Convolution2DEnabled
) {
789 _mesa_convolve_2d_image(ctx
, &width
, &height
, tmpImage
, convImage
);
792 ASSERT(ctx
->Pixel
.Separable2DEnabled
);
793 _mesa_convolve_sep_image(ctx
, &width
, &height
, tmpImage
, convImage
);
797 /* continue transfer ops and draw the convolved image */
798 unpack
= &_mesa_native_packing
;
802 transferOps
&= postConvTransferOps
;
809 GLubyte rgba
[MAX_WIDTH
][4];
811 if (width
> MAX_WIDTH
)
813 for (row
= 0; row
< height
; row
++, y
++) {
814 const GLvoid
*source
= _mesa_image_address(unpack
,
815 pixels
, width
, height
, format
, type
, 0, row
, 0);
816 _mesa_unpack_ubyte_color_span(ctx
, width
, GL_RGBA
, (void*) rgba
,
817 format
, type
, source
, unpack
,
819 if ((ctx
->Pixel
.MinMaxEnabled
&& ctx
->MinMax
.Sink
) ||
820 (ctx
->Pixel
.HistogramEnabled
&& ctx
->Histogram
.Sink
))
823 if (ctx
->Texture
.ReallyEnabled
&& ctx
->Pixel
.PixelTextureEnabled
) {
824 GLfloat s
[MAX_WIDTH
], t
[MAX_WIDTH
], r
[MAX_WIDTH
], q
[MAX_WIDTH
];
825 GLubyte primary_rgba
[MAX_WIDTH
][4];
827 /* XXX not sure how multitexture is supposed to work here */
829 MEMCPY(primary_rgba
, rgba
, 4 * width
* sizeof(GLubyte
));
831 for (unit
= 0; unit
< MAX_TEXTURE_UNITS
; unit
++) {
832 _mesa_pixeltexgen(ctx
, width
, (const GLubyte (*)[4]) rgba
,
834 gl_texture_pixels(ctx
, unit
, width
, s
, t
, r
, NULL
,
840 (*ctx
->Driver
.WriteRGBASpan
)( ctx
, width
, x
, y
,
841 (CONST
GLubyte (*)[]) rgba
, NULL
);
844 gl_write_zoomed_rgba_span( ctx
, width
, x
, y
, zspan
,
845 (CONST
GLubyte (*)[]) rgba
, desty
);
848 gl_write_rgba_span( ctx
, (GLuint
) width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
861 * Execute glDrawPixels
864 _mesa_DrawPixels( GLsizei width
, GLsizei height
,
865 GLenum format
, GLenum type
, const GLvoid
*pixels
)
867 GET_CURRENT_CONTEXT(ctx
);
868 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawPixels");
870 if (ctx
->RenderMode
==GL_RENDER
) {
872 if (!pixels
|| !ctx
->Current
.RasterPosValid
) {
877 gl_update_state(ctx
);
880 if (ctx
->ImageTransferState
== UPDATE_IMAGE_TRANSFER_STATE
)
881 _mesa_update_image_transfer_state(ctx
);
883 x
= (GLint
) (ctx
->Current
.RasterPos
[0] + 0.5F
);
884 y
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
886 ctx
->OcclusionResult
= GL_TRUE
;
888 /* see if device driver can do the drawpix */
889 if (ctx
->Driver
.DrawPixels
890 && (*ctx
->Driver
.DrawPixels
)(ctx
, x
, y
, width
, height
, format
, type
,
891 &ctx
->Unpack
, pixels
)) {
896 case GL_STENCIL_INDEX
:
897 draw_stencil_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
899 case GL_DEPTH_COMPONENT
:
900 draw_depth_pixels( ctx
, x
, y
, width
, height
, type
, pixels
);
903 if (ctx
->Visual
->RGBAflag
)
904 draw_rgba_pixels(ctx
, x
,y
, width
, height
, format
, type
, pixels
);
906 draw_index_pixels(ctx
, x
, y
, width
, height
, type
, pixels
);
913 case GL_LUMINANCE_ALPHA
:
919 draw_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
);
922 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels(format)" );
926 else if (ctx
->RenderMode
==GL_FEEDBACK
) {
927 if (ctx
->Current
.RasterPosValid
) {
929 GLfloat texcoord
[4], invq
;
930 UBYTE_RGBA_TO_FLOAT_RGBA(color
, ctx
->Current
.ByteColor
);
931 invq
= 1.0F
/ ctx
->Current
.Texcoord
[0][3];
932 texcoord
[0] = ctx
->Current
.Texcoord
[0][0] * invq
;
933 texcoord
[1] = ctx
->Current
.Texcoord
[0][1] * invq
;
934 texcoord
[2] = ctx
->Current
.Texcoord
[0][2] * invq
;
935 texcoord
[3] = ctx
->Current
.Texcoord
[0][3];
936 FEEDBACK_TOKEN( ctx
, (GLfloat
) (GLint
) GL_DRAW_PIXEL_TOKEN
);
937 gl_feedback_vertex( ctx
,
938 ctx
->Current
.RasterPos
,
939 color
, ctx
->Current
.Index
, texcoord
);
942 else if (ctx
->RenderMode
==GL_SELECT
) {
943 if (ctx
->Current
.RasterPosValid
) {
944 gl_update_hitflag( ctx
, ctx
->Current
.RasterPos
[2] );