1 /* $Id: drawpix.c,v 1.4 1999/10/19 20:33:57 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 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.
39 #include "GL/xf86glx.h"
53 #include "GL/xf86glx.h"
59 /* TODO: apply texture mapping to fragments */
63 * Try to do a fast glDrawPixels. Conditions include:
64 * not using a display list
65 * simple pixel unpacking
68 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
70 GLboolean
gl_direct_DrawPixels( GLcontext
*ctx
,
71 const struct gl_pixelstore_attrib
*unpack
,
72 GLsizei width
, GLsizei height
,
73 GLenum format
, GLenum type
,
74 const GLvoid
*pixels
)
76 GLubyte rgb
[MAX_WIDTH
][3];
77 GLubyte rgba
[MAX_WIDTH
][4];
79 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx
, "glDrawPixels",
83 if (!ctx
->Current
.RasterPosValid
) {
92 /* see if device driver can do the drawpix */
93 if (ctx
->Driver
.DrawPixels
) {
94 GLint x
= (GLint
) (ctx
->Current
.RasterPos
[0] + 0.5F
);
95 GLint y
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
96 if ((*ctx
->Driver
.DrawPixels
)(ctx
, x
, y
, width
, height
, format
, type
,
101 if ((ctx
->RasterMask
&(~(SCISSOR_BIT
|WINCLIP_BIT
)))==0
102 && ctx
->Pixel
.RedBias
==0.0 && ctx
->Pixel
.RedScale
==1.0
103 && ctx
->Pixel
.GreenBias
==0.0 && ctx
->Pixel
.GreenScale
==1.0
104 && ctx
->Pixel
.BlueBias
==0.0 && ctx
->Pixel
.BlueScale
==1.0
105 && ctx
->Pixel
.AlphaBias
==0.0 && ctx
->Pixel
.AlphaScale
==1.0
106 && ctx
->Pixel
.IndexShift
==0 && ctx
->Pixel
.IndexOffset
==0
107 && ctx
->Pixel
.MapColorFlag
==0
108 && unpack
->Alignment
==1
109 && !unpack
->SwapBytes
110 && !unpack
->LsbFirst
) {
112 GLint destX
= (GLint
) (ctx
->Current
.RasterPos
[0] + 0.5F
);
113 GLint destY
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
114 GLint drawWidth
= width
; /* actual width drawn */
115 GLint drawHeight
= height
; /* actual height drawn */
116 GLint skipPixels
= unpack
->SkipPixels
;
117 GLint skipRows
= unpack
->SkipRows
;
119 GLdepth zSpan
[MAX_WIDTH
]; /* only used when zooming */
122 if (unpack
->RowLength
> 0)
123 rowLength
= unpack
->RowLength
;
127 /* If we're not using pixel zoom then do all clipping calculations
128 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions
129 * handle the clipping.
131 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
132 /* horizontal clipping */
133 if (destX
< ctx
->Buffer
->Xmin
) {
134 skipPixels
+= (ctx
->Buffer
->Xmin
- destX
);
135 drawWidth
-= (ctx
->Buffer
->Xmin
- destX
);
136 destX
= ctx
->Buffer
->Xmin
;
138 if (destX
+ drawWidth
> ctx
->Buffer
->Xmax
)
139 drawWidth
-= (destX
+ drawWidth
- ctx
->Buffer
->Xmax
- 1);
143 /* vertical clipping */
144 if (destY
< ctx
->Buffer
->Ymin
) {
145 skipRows
+= (ctx
->Buffer
->Ymin
- destY
);
146 drawHeight
-= (ctx
->Buffer
->Ymin
- destY
);
147 destY
= ctx
->Buffer
->Ymin
;
149 if (destY
+ drawHeight
> ctx
->Buffer
->Ymax
)
150 drawHeight
-= (destY
+ drawHeight
- ctx
->Buffer
->Ymax
- 1);
155 /* setup array of fragment Z value to pass to zoom function */
156 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * DEPTH_SCALE
);
158 assert(drawWidth
< MAX_WIDTH
);
159 for (i
=0; i
<drawWidth
; i
++)
162 /* save Y value of first row */
163 zoomY0
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
169 * The window region at (destX, destY) of size (drawWidth, drawHeight)
170 * will be written to.
171 * We'll take pixel data from buffer pointed to by "pixels" but we'll
172 * skip "skipRows" rows and skip "skipPixels" pixels/row.
175 if (format
==GL_RGBA
&& type
==GL_UNSIGNED_BYTE
) {
176 if (ctx
->Visual
->RGBAflag
) {
177 GLubyte
*src
= (GLubyte
*) pixels
178 + (skipRows
* rowLength
+ skipPixels
) * 4;
179 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
182 for (row
=0; row
<drawHeight
; row
++) {
183 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
185 src
+= rowLength
* 4;
192 for (row
=0; row
<drawHeight
; row
++) {
193 gl_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
194 zSpan
, (void *) src
, zoomY0
);
195 src
+= rowLength
* 4;
202 else if (format
==GL_RGB
&& type
==GL_UNSIGNED_BYTE
) {
203 if (ctx
->Visual
->RGBAflag
) {
204 GLubyte
*src
= (GLubyte
*) pixels
205 + (skipRows
* rowLength
+ skipPixels
) * 3;
206 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
208 for (row
=0; row
<drawHeight
; row
++) {
209 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
211 src
+= rowLength
* 3;
218 for (row
=0; row
<drawHeight
; row
++) {
219 gl_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
220 zSpan
, (void *) src
, zoomY0
);
221 src
+= rowLength
* 3;
228 else if (format
==GL_LUMINANCE
&& type
==GL_UNSIGNED_BYTE
) {
229 if (ctx
->Visual
->RGBAflag
) {
230 GLubyte
*src
= (GLubyte
*) pixels
231 + (skipRows
* rowLength
+ skipPixels
);
232 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
235 assert(drawWidth
< MAX_WIDTH
);
236 for (row
=0; row
<drawHeight
; row
++) {
238 for (i
=0;i
<drawWidth
;i
++) {
243 (*ctx
->Driver
.WriteRGBSpan
)(ctx
, drawWidth
, destX
, destY
,
252 assert(drawWidth
< MAX_WIDTH
);
253 for (row
=0; row
<drawHeight
; row
++) {
255 for (i
=0;i
<drawWidth
;i
++) {
260 gl_write_zoomed_rgb_span(ctx
, drawWidth
, destX
, destY
,
261 zSpan
, (void *) rgb
, zoomY0
);
269 else if (format
==GL_LUMINANCE_ALPHA
&& type
==GL_UNSIGNED_BYTE
) {
270 if (ctx
->Visual
->RGBAflag
) {
271 GLubyte
*src
= (GLubyte
*) pixels
272 + (skipRows
* rowLength
+ skipPixels
)*2;
273 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
276 assert(drawWidth
< MAX_WIDTH
);
277 for (row
=0; row
<drawHeight
; row
++) {
280 for (i
=0;i
<drawWidth
;i
++) {
286 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
287 (void *) rgba
, NULL
);
295 assert(drawWidth
< MAX_WIDTH
);
296 for (row
=0; row
<drawHeight
; row
++) {
299 for (i
=0;i
<drawWidth
;i
++) {
305 gl_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
306 zSpan
, (void *) rgba
, zoomY0
);
314 else if (format
==GL_COLOR_INDEX
&& type
==GL_UNSIGNED_BYTE
) {
315 GLubyte
*src
= (GLubyte
*) pixels
+ skipRows
* rowLength
+ skipPixels
;
316 if (ctx
->Visual
->RGBAflag
) {
317 /* convert CI data to RGBA */
318 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
321 for (row
=0; row
<drawHeight
; row
++) {
322 assert(drawWidth
< MAX_WIDTH
);
323 gl_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
324 (*ctx
->Driver
.WriteRGBASpan
)(ctx
, drawWidth
, destX
, destY
,
325 (const GLubyte (*)[4])rgba
,
335 for (row
=0; row
<drawHeight
; row
++) {
336 assert(drawWidth
< MAX_WIDTH
);
337 gl_map_ci8_to_rgba(ctx
, drawWidth
, src
, rgba
);
338 gl_write_zoomed_rgba_span(ctx
, drawWidth
, destX
, destY
,
339 zSpan
, (void *) rgba
, zoomY0
);
347 /* write CI data to CI frame buffer */
349 if (ctx
->Pixel
.ZoomX
==1.0F
&& ctx
->Pixel
.ZoomY
==1.0F
) {
351 for (row
=0; row
<drawHeight
; row
++) {
352 (*ctx
->Driver
.WriteCI8Span
)(ctx
, drawWidth
, destX
, destY
,
366 /* can't handle this pixel format and/or data type here */
371 /* can't do direct render, have to use slow path */
379 * Do glDrawPixels of index pixels.
381 static void draw_index_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
382 const struct gl_image
*image
)
384 GLint width
, height
, widthInBytes
;
385 const GLint desty
= y
;
387 GLdepth zspan
[MAX_WIDTH
];
388 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
391 assert(image
->Format
== GL_COLOR_INDEX
);
393 width
= image
->Width
;
394 height
= image
->Height
;
395 if (image
->Type
== GL_BITMAP
)
396 widthInBytes
= (width
+ 7) / 8;
398 widthInBytes
= width
;
400 /* Fragment depth values */
401 if (ctx
->Depth
.Test
) {
402 GLdepth zval
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * DEPTH_SCALE
);
403 for (i
=0;i
<width
;i
++) {
408 /* process the image row by row */
409 for (i
=0;i
<height
;i
++,y
++) {
410 GLuint ispan
[MAX_WIDTH
];
412 /* convert to uints */
413 switch (image
->Type
) {
414 case GL_UNSIGNED_BYTE
:
416 GLubyte
*src
= (GLubyte
*) image
->Data
+ i
* width
;
417 for (j
=0;j
<width
;j
++) {
418 ispan
[j
] = (GLuint
) *src
++;
424 GLfloat
*src
= (GLfloat
*) image
->Data
+ i
* width
;
425 for (j
=0;j
<width
;j
++) {
426 ispan
[j
] = (GLuint
) (GLint
) *src
++;
432 GLubyte
*src
= (GLubyte
*) image
->Data
+ i
* widthInBytes
;
433 for (j
=0;j
<width
;j
++) {
434 ispan
[j
] = ( src
[j
>> 3] >> (7 - (j
& 0x7)) ) & 1;
439 gl_problem( ctx
, "draw_index_pixels type" );
443 /* apply shift and offset */
444 if (ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.IndexShift
) {
445 gl_shift_and_offset_ci( ctx
, width
, ispan
);
448 if (ctx
->Visual
->RGBAflag
) {
449 /* Convert index to RGBA and write to frame buffer */
450 GLubyte rgba
[MAX_WIDTH
][4];
451 gl_map_ci_to_rgba( ctx
, width
, ispan
, rgba
);
453 gl_write_zoomed_rgba_span( ctx
, width
, x
, y
, zspan
,
454 (const GLubyte (*)[4])rgba
, desty
);
457 gl_write_rgba_span( ctx
, width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
461 /* optionally apply index map then write to frame buffer */
462 if (ctx
->Pixel
.MapColorFlag
) {
463 gl_map_ci(ctx
, width
, ispan
);
466 gl_write_zoomed_index_span( ctx
, width
, x
, y
, zspan
, ispan
, desty
);
469 gl_write_index_span( ctx
, width
, x
, y
, zspan
, ispan
, GL_BITMAP
);
479 * Do glDrawPixels of stencil image. The image datatype may either
480 * be GLubyte or GLbitmap.
482 static void draw_stencil_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
483 const struct gl_image
*image
)
485 GLint widthInBytes
, width
, height
;
486 const GLint desty
= y
;
488 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
490 if (image
->Type
!= GL_BYTE
&&
491 image
->Type
!= GL_UNSIGNED_BYTE
&&
492 image
->Type
!= GL_SHORT
&&
493 image
->Type
!= GL_UNSIGNED_SHORT
&&
494 image
->Type
!= GL_INT
&&
495 image
->Type
!= GL_UNSIGNED_INT
&&
496 image
->Type
!= GL_FLOAT
&&
497 image
->Type
!= GL_BITMAP
) {
498 gl_error( ctx
, GL_INVALID_OPERATION
, "glDrawPixels(stencil type)");
503 assert(image
->Format
== GL_STENCIL_INDEX
);
504 assert(image
->Type
== GL_UNSIGNED_BYTE
|| image
->Type
== GL_BITMAP
);
506 if (image
->Type
== GL_UNSIGNED_BYTE
)
507 widthInBytes
= image
->Width
;
509 widthInBytes
= (image
->Width
+ 7) / 8;
510 width
= image
->Width
;
511 height
= image
->Height
;
513 /* process the image row by row */
514 for (i
=0;i
<height
;i
++,y
++) {
515 GLstencil
*src
= (GLstencil
*)image
->Data
+ i
* widthInBytes
;
516 GLstencil
*stencilValues
;
517 GLstencil stencilCopy
[MAX_WIDTH
];
519 if (image
->Type
== GL_BITMAP
) {
520 /* convert bitmap data to GLubyte (0 or 1) data */
522 for (j
= 0; j
< width
; j
++) {
523 stencilCopy
[j
] = ( src
[j
>> 3] >> (7 - (j
& 0x7)) ) & 1;
528 if (ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.IndexShift
529 || ctx
->Pixel
.MapStencilFlag
) {
531 /* make copy of stencil values */
532 if (src
!= stencilCopy
)
533 MEMCPY( stencilCopy
, src
, width
* sizeof(GLstencil
));
535 /* apply shift and offset */
536 if (ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.IndexShift
) {
537 gl_shift_and_offset_stencil( ctx
, width
, stencilCopy
);
541 if (ctx
->Pixel
.MapStencilFlag
) {
542 gl_map_stencil( ctx
, width
, stencilCopy
);
545 stencilValues
= stencilCopy
;
548 /* use stencil values in-place */
552 /* write stencil values to stencil buffer */
554 gl_write_zoomed_stencil_span( ctx
, (GLuint
) width
, x
, y
,
555 stencilValues
, desty
);
558 gl_write_stencil_span( ctx
, (GLuint
) width
, x
, y
, stencilValues
);
566 * Do a glDrawPixels of depth values.
568 static void draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
569 const struct gl_image
*image
)
572 const GLint desty
= y
;
573 GLubyte rgba
[MAX_WIDTH
][4];
574 GLuint ispan
[MAX_WIDTH
];
575 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
576 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
579 assert(image
->Format
== GL_DEPTH_COMPONENT
);
581 width
= image
->Width
;
582 height
= image
->Height
;
585 if (ctx
->Visual
->RGBAflag
) {
586 GLint r
= (GLint
) (ctx
->Current
.RasterColor
[0] * 255.0F
);
587 GLint g
= (GLint
) (ctx
->Current
.RasterColor
[1] * 255.0F
);
588 GLint b
= (GLint
) (ctx
->Current
.RasterColor
[2] * 255.0F
);
589 GLint a
= (GLint
) (ctx
->Current
.RasterColor
[3] * 255.0F
);
591 for (i
=0; i
<width
; i
++) {
600 for (i
=0;i
<width
;i
++) {
601 ispan
[i
] = ctx
->Current
.RasterIndex
;
605 if (image
->Type
==GL_UNSIGNED_SHORT
&& sizeof(GLdepth
)==sizeof(GLushort
)
606 && !bias_or_scale
&& !zoom
&& ctx
->Visual
->RGBAflag
) {
607 /* Special case: directly write 16-bit depth values */
609 for (j
=0;j
<height
;j
++,y
++) {
610 GLdepth
*zptr
= (GLdepth
*) image
->Data
+ j
* width
;
611 gl_write_rgba_span( ctx
, width
, x
, y
, zptr
, rgba
, GL_BITMAP
);
614 else if (image
->Type
==GL_UNSIGNED_INT
&& sizeof(GLdepth
)==sizeof(GLuint
)
615 && !bias_or_scale
&& !zoom
&& ctx
->Visual
->RGBAflag
) {
616 /* Special case: directly write 32-bit depth values */
618 /* Compute shift value to scale 32-bit uints down to depth values. */
620 GLuint max
= MAX_DEPTH
;
621 while ((max
&0x80000000)==0) {
625 for (j
=0;j
<height
;j
++,y
++) {
626 GLdepth zspan
[MAX_WIDTH
];
627 GLuint
*zptr
= (GLuint
*) image
->Data
+ j
* width
;
628 for (i
=0;i
<width
;i
++) {
629 zspan
[i
] = zptr
[i
] >> shift
;
631 gl_write_rgba_span( ctx
, width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
635 /* General case (slower) */
638 /* process image row by row */
639 for (i
=0;i
<height
;i
++,y
++) {
640 GLfloat depth
[MAX_WIDTH
];
641 GLdepth zspan
[MAX_WIDTH
];
643 switch (image
->Type
) {
644 case GL_UNSIGNED_SHORT
:
646 GLushort
*src
= (GLushort
*) image
->Data
+ i
* width
;
647 for (j
=0;j
<width
;j
++) {
648 depth
[j
] = USHORT_TO_FLOAT( *src
++ );
652 case GL_UNSIGNED_INT
:
654 GLuint
*src
= (GLuint
*) image
->Data
+ i
* width
;
655 for (j
=0;j
<width
;j
++) {
656 depth
[j
] = UINT_TO_FLOAT( *src
++ );
662 GLfloat
*src
= (GLfloat
*) image
->Data
+ i
* width
;
663 for (j
=0;j
<width
;j
++) {
669 gl_problem(ctx
, "Bad type in draw_depth_pixels");
673 /* apply depth scale and bias */
674 if (ctx
->Pixel
.DepthScale
!=1.0 || ctx
->Pixel
.DepthBias
!=0.0) {
675 for (j
=0;j
<width
;j
++) {
676 depth
[j
] = depth
[j
] * ctx
->Pixel
.DepthScale
+ ctx
->Pixel
.DepthBias
;
680 /* clamp depth values to [0,1] and convert from floats to integers */
681 for (j
=0;j
<width
;j
++) {
682 zspan
[j
] = (GLdepth
) (CLAMP( depth
[j
], 0.0F
, 1.0F
) * DEPTH_SCALE
);
685 if (ctx
->Visual
->RGBAflag
) {
687 gl_write_zoomed_rgba_span( ctx
, width
, x
, y
, zspan
,
688 (const GLubyte (*)[4])rgba
, desty
);
691 gl_write_rgba_span( ctx
, width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
696 gl_write_zoomed_index_span( ctx
, width
, x
, y
, zspan
,
700 gl_write_index_span( ctx
, width
, x
, y
, zspan
, ispan
, GL_BITMAP
);
710 /* Simple unpacking parameters: */
711 static struct gl_pixelstore_attrib NoUnpack
= {
718 GL_FALSE
, /* SwapBytes */
719 GL_FALSE
/* LsbFirst */
724 * Do glDrawPixels of RGBA pixels.
726 static void draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
727 const struct gl_image
*image
)
731 const GLint desty
= y
;
732 GLdepth zspan
[MAX_WIDTH
];
734 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
738 /* Try an optimized glDrawPixels first */
739 if (gl_direct_DrawPixels(ctx
, &NoUnpack
, image
->Width
, image
->Height
,
740 image
->Format
, image
->Type
, image
->Data
))
743 width
= image
->Width
;
744 height
= image
->Height
;
746 /* Fragment depth values */
747 if (ctx
->Depth
.Test
) {
748 /* fill in array of z values */
749 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * DEPTH_SCALE
);
750 for (i
=0;i
<width
;i
++) {
755 if (ctx
->RasterMask
==0 && !zoom
&& x
>=0 && y
>=0
756 && x
+width
<=ctx
->Buffer
->Width
&& y
+height
<=ctx
->Buffer
->Height
) {
760 quickDraw
= GL_FALSE
;
764 /* General solution */
765 GLboolean r_flag
, g_flag
, b_flag
, a_flag
, l_flag
;
767 GLubyte rgba
[MAX_WIDTH
][4];
768 GLfloat rf
[MAX_WIDTH
];
769 GLfloat gf
[MAX_WIDTH
];
770 GLfloat bf
[MAX_WIDTH
];
771 DEFARRAY(GLfloat
,af
,MAX_WIDTH
);
772 CHECKARRAY(af
,return);
774 r_flag
= g_flag
= b_flag
= a_flag
= l_flag
= GL_FALSE
;
775 switch (image
->Format
) {
793 r_flag
= g_flag
= b_flag
= GL_TRUE
;
800 case GL_LUMINANCE_ALPHA
:
801 l_flag
= a_flag
= GL_TRUE
;
805 r_flag
= g_flag
= b_flag
= a_flag
= GL_TRUE
;
809 gl_problem(ctx
, "Bad type in draw_rgba_pixels");
813 /* process the image row by row */
814 for (i
=0;i
<height
;i
++,y
++) {
815 /* convert to floats */
816 switch (image
->Type
) {
817 case GL_UNSIGNED_BYTE
:
819 GLubyte
*src
= (GLubyte
*) image
->Data
+ i
* width
* components
;
820 for (j
=0;j
<width
;j
++) {
822 rf
[j
] = gf
[j
] = bf
[j
] = UBYTE_TO_FLOAT(*src
++);
825 rf
[j
] = r_flag
? UBYTE_TO_FLOAT(*src
++) : 0.0;
826 gf
[j
] = g_flag
? UBYTE_TO_FLOAT(*src
++) : 0.0;
827 bf
[j
] = b_flag
? UBYTE_TO_FLOAT(*src
++) : 0.0;
829 af
[j
] = a_flag
? UBYTE_TO_FLOAT(*src
++) : 1.0;
835 GLfloat
*src
= (GLfloat
*) image
->Data
+ i
* width
* components
;
836 for (j
=0;j
<width
;j
++) {
838 rf
[j
] = gf
[j
] = bf
[j
] = *src
++;
841 rf
[j
] = r_flag
? *src
++ : 0.0;
842 gf
[j
] = g_flag
? *src
++ : 0.0;
843 bf
[j
] = b_flag
? *src
++ : 0.0;
845 af
[j
] = a_flag
? *src
++ : 1.0;
850 gl_problem( ctx
, "draw_rgba_pixels type" );
854 /* apply scale and bias */
855 if (ctx
->Pixel
.ScaleOrBiasRGBA
) {
856 gl_scale_and_bias_color(ctx
, width
, rf
, gf
, bf
, af
);
859 /* apply pixel mappings */
860 if (ctx
->Pixel
.MapColorFlag
) {
861 gl_map_color(ctx
, width
, rf
, gf
, bf
, af
);
864 /* convert to integers */
865 for (j
=0;j
<width
;j
++) {
866 rgba
[j
][RCOMP
] = (GLint
) (rf
[j
] * 255.0F
);
867 rgba
[j
][GCOMP
] = (GLint
) (gf
[j
] * 255.0F
);
868 rgba
[j
][BCOMP
] = (GLint
) (bf
[j
] * 255.0F
);
869 rgba
[j
][ACOMP
] = (GLint
) (af
[j
] * 255.0F
);
872 /* write to frame buffer */
874 (*ctx
->Driver
.WriteRGBASpan
)( ctx
, width
, x
, y
,
875 (const GLubyte (*)[4])rgba
, NULL
);
878 gl_write_zoomed_rgba_span( ctx
, width
, x
, y
, zspan
,
879 (const GLubyte (*)[4])rgba
, desty
);
882 gl_write_rgba_span( ctx
, (GLuint
) width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
893 * Execute glDrawPixels
895 void gl_DrawPixels( GLcontext
* ctx
, struct gl_image
*image
)
897 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawPixels");
900 if (gl_image_error_test( ctx
, image
, "glDrawPixels" ))
903 if (ctx
->RenderMode
==GL_RENDER
) {
905 if (!ctx
->Current
.RasterPosValid
) {
909 x
= (GLint
) (ctx
->Current
.RasterPos
[0] + 0.5F
);
910 y
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
912 switch (image
->Format
) {
914 draw_index_pixels( ctx
, x
, y
, image
);
916 case GL_STENCIL_INDEX
:
917 draw_stencil_pixels( ctx
, x
, y
, image
);
919 case GL_DEPTH_COMPONENT
:
920 draw_depth_pixels( ctx
, x
, y
, image
);
928 case GL_LUMINANCE_ALPHA
:
930 draw_rgba_pixels( ctx
, x
, y
, image
);
933 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels" );
937 else if (ctx
->RenderMode
==GL_FEEDBACK
) {
938 if (ctx
->Current
.RasterPosValid
) {
940 GLfloat texcoord
[4], invq
;
941 UBYTE_RGBA_TO_FLOAT_RGBA(color
, ctx
->Current
.ByteColor
);
942 invq
= 1.0F
/ ctx
->Current
.Texcoord
[0][3];
943 texcoord
[0] = ctx
->Current
.Texcoord
[0][0] * invq
;
944 texcoord
[1] = ctx
->Current
.Texcoord
[0][1] * invq
;
945 texcoord
[2] = ctx
->Current
.Texcoord
[0][2] * invq
;
946 texcoord
[3] = ctx
->Current
.Texcoord
[0][3];
947 FEEDBACK_TOKEN( ctx
, (GLfloat
) (GLint
) GL_DRAW_PIXEL_TOKEN
);
948 gl_feedback_vertex( ctx
,
949 ctx
->Current
.RasterPos
,
950 color
, ctx
->Current
.Index
, texcoord
);
953 else if (ctx
->RenderMode
==GL_SELECT
) {
954 if (ctx
->Current
.RasterPosValid
) {
955 gl_update_hitflag( ctx
, ctx
->Current
.RasterPos
[2] );