1 /* $Id: drawpix.c,v 1.3 1999/10/08 09:27:10 keithw 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;
491 assert(image
->Format
== GL_STENCIL_INDEX
);
492 assert(image
->Type
== GL_UNSIGNED_BYTE
|| image
->Type
== GL_BITMAP
);
494 if (image
->Type
== GL_UNSIGNED_BYTE
)
495 widthInBytes
= image
->Width
;
497 widthInBytes
= (image
->Width
+ 7) / 8;
498 width
= image
->Width
;
499 height
= image
->Height
;
501 /* process the image row by row */
502 for (i
=0;i
<height
;i
++,y
++) {
503 GLstencil
*src
= (GLstencil
*)image
->Data
+ i
* widthInBytes
;
504 GLstencil
*stencilValues
;
505 GLstencil stencilCopy
[MAX_WIDTH
];
507 if (image
->Type
== GL_BITMAP
) {
508 /* convert bitmap data to GLubyte (0 or 1) data */
510 for (j
= 0; j
< width
; j
++) {
511 stencilCopy
[j
] = ( src
[j
>> 3] >> (7 - (j
& 0x7)) ) & 1;
516 if (ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.IndexShift
517 || ctx
->Pixel
.MapStencilFlag
) {
519 /* make copy of stencil values */
520 if (src
!= stencilCopy
)
521 MEMCPY( stencilCopy
, src
, width
* sizeof(GLstencil
));
523 /* apply shift and offset */
524 if (ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.IndexShift
) {
525 gl_shift_and_offset_stencil( ctx
, width
, stencilCopy
);
529 if (ctx
->Pixel
.MapStencilFlag
) {
530 gl_map_stencil( ctx
, width
, stencilCopy
);
533 stencilValues
= stencilCopy
;
536 /* use stencil values in-place */
540 /* write stencil values to stencil buffer */
542 gl_write_zoomed_stencil_span( ctx
, (GLuint
) width
, x
, y
,
543 stencilValues
, desty
);
546 gl_write_stencil_span( ctx
, (GLuint
) width
, x
, y
, stencilValues
);
554 * Do a glDrawPixels of depth values.
556 static void draw_depth_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
557 const struct gl_image
*image
)
560 const GLint desty
= y
;
561 GLubyte rgba
[MAX_WIDTH
][4];
562 GLuint ispan
[MAX_WIDTH
];
563 const GLboolean bias_or_scale
= ctx
->Pixel
.DepthBias
!=0.0 || ctx
->Pixel
.DepthScale
!=1.0;
564 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
567 assert(image
->Format
== GL_DEPTH_COMPONENT
);
569 width
= image
->Width
;
570 height
= image
->Height
;
573 if (ctx
->Visual
->RGBAflag
) {
574 GLint r
= (GLint
) (ctx
->Current
.RasterColor
[0] * 255.0F
);
575 GLint g
= (GLint
) (ctx
->Current
.RasterColor
[1] * 255.0F
);
576 GLint b
= (GLint
) (ctx
->Current
.RasterColor
[2] * 255.0F
);
577 GLint a
= (GLint
) (ctx
->Current
.RasterColor
[3] * 255.0F
);
579 for (i
=0; i
<width
; i
++) {
588 for (i
=0;i
<width
;i
++) {
589 ispan
[i
] = ctx
->Current
.RasterIndex
;
593 if (image
->Type
==GL_UNSIGNED_SHORT
&& sizeof(GLdepth
)==sizeof(GLushort
)
594 && !bias_or_scale
&& !zoom
&& ctx
->Visual
->RGBAflag
) {
595 /* Special case: directly write 16-bit depth values */
597 for (j
=0;j
<height
;j
++,y
++) {
598 GLdepth
*zptr
= (GLdepth
*) image
->Data
+ j
* width
;
599 gl_write_rgba_span( ctx
, width
, x
, y
, zptr
, rgba
, GL_BITMAP
);
602 else if (image
->Type
==GL_UNSIGNED_INT
&& sizeof(GLdepth
)==sizeof(GLuint
)
603 && !bias_or_scale
&& !zoom
&& ctx
->Visual
->RGBAflag
) {
604 /* Special case: directly write 32-bit depth values */
606 /* Compute shift value to scale 32-bit uints down to depth values. */
608 GLuint max
= MAX_DEPTH
;
609 while ((max
&0x80000000)==0) {
613 for (j
=0;j
<height
;j
++,y
++) {
614 GLdepth zspan
[MAX_WIDTH
];
615 GLuint
*zptr
= (GLuint
*) image
->Data
+ j
* width
;
616 for (i
=0;i
<width
;i
++) {
617 zspan
[i
] = zptr
[i
] >> shift
;
619 gl_write_rgba_span( ctx
, width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
623 /* General case (slower) */
626 /* process image row by row */
627 for (i
=0;i
<height
;i
++,y
++) {
628 GLfloat depth
[MAX_WIDTH
];
629 GLdepth zspan
[MAX_WIDTH
];
631 switch (image
->Type
) {
632 case GL_UNSIGNED_SHORT
:
634 GLushort
*src
= (GLushort
*) image
->Data
+ i
* width
;
635 for (j
=0;j
<width
;j
++) {
636 depth
[j
] = USHORT_TO_FLOAT( *src
++ );
640 case GL_UNSIGNED_INT
:
642 GLuint
*src
= (GLuint
*) image
->Data
+ i
* width
;
643 for (j
=0;j
<width
;j
++) {
644 depth
[j
] = UINT_TO_FLOAT( *src
++ );
650 GLfloat
*src
= (GLfloat
*) image
->Data
+ i
* width
;
651 for (j
=0;j
<width
;j
++) {
657 gl_problem(ctx
, "Bad type in draw_depth_pixels");
661 /* apply depth scale and bias */
662 if (ctx
->Pixel
.DepthScale
!=1.0 || ctx
->Pixel
.DepthBias
!=0.0) {
663 for (j
=0;j
<width
;j
++) {
664 depth
[j
] = depth
[j
] * ctx
->Pixel
.DepthScale
+ ctx
->Pixel
.DepthBias
;
668 /* clamp depth values to [0,1] and convert from floats to integers */
669 for (j
=0;j
<width
;j
++) {
670 zspan
[j
] = (GLdepth
) (CLAMP( depth
[j
], 0.0F
, 1.0F
) * DEPTH_SCALE
);
673 if (ctx
->Visual
->RGBAflag
) {
675 gl_write_zoomed_rgba_span( ctx
, width
, x
, y
, zspan
,
676 (const GLubyte (*)[4])rgba
, desty
);
679 gl_write_rgba_span( ctx
, width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
684 gl_write_zoomed_index_span( ctx
, width
, x
, y
, zspan
,
688 gl_write_index_span( ctx
, width
, x
, y
, zspan
, ispan
, GL_BITMAP
);
698 /* Simple unpacking parameters: */
699 static struct gl_pixelstore_attrib NoUnpack
= {
706 GL_FALSE
, /* SwapBytes */
707 GL_FALSE
/* LsbFirst */
712 * Do glDrawPixels of RGBA pixels.
714 static void draw_rgba_pixels( GLcontext
*ctx
, GLint x
, GLint y
,
715 const struct gl_image
*image
)
719 const GLint desty
= y
;
720 GLdepth zspan
[MAX_WIDTH
];
722 const GLboolean zoom
= ctx
->Pixel
.ZoomX
!=1.0 || ctx
->Pixel
.ZoomY
!=1.0;
726 /* Try an optimized glDrawPixels first */
727 if (gl_direct_DrawPixels(ctx
, &NoUnpack
, image
->Width
, image
->Height
,
728 image
->Format
, image
->Type
, image
->Data
))
731 width
= image
->Width
;
732 height
= image
->Height
;
734 /* Fragment depth values */
735 if (ctx
->Depth
.Test
) {
736 /* fill in array of z values */
737 GLdepth z
= (GLdepth
) (ctx
->Current
.RasterPos
[2] * DEPTH_SCALE
);
738 for (i
=0;i
<width
;i
++) {
743 if (ctx
->RasterMask
==0 && !zoom
&& x
>=0 && y
>=0
744 && x
+width
<=ctx
->Buffer
->Width
&& y
+height
<=ctx
->Buffer
->Height
) {
748 quickDraw
= GL_FALSE
;
752 /* General solution */
753 GLboolean r_flag
, g_flag
, b_flag
, a_flag
, l_flag
;
755 GLubyte rgba
[MAX_WIDTH
][4];
756 GLfloat rf
[MAX_WIDTH
];
757 GLfloat gf
[MAX_WIDTH
];
758 GLfloat bf
[MAX_WIDTH
];
759 DEFARRAY(GLfloat
,af
,MAX_WIDTH
);
760 CHECKARRAY(af
,return);
762 r_flag
= g_flag
= b_flag
= a_flag
= l_flag
= GL_FALSE
;
763 switch (image
->Format
) {
781 r_flag
= g_flag
= b_flag
= GL_TRUE
;
788 case GL_LUMINANCE_ALPHA
:
789 l_flag
= a_flag
= GL_TRUE
;
793 r_flag
= g_flag
= b_flag
= a_flag
= GL_TRUE
;
797 gl_problem(ctx
, "Bad type in draw_rgba_pixels");
801 /* process the image row by row */
802 for (i
=0;i
<height
;i
++,y
++) {
803 /* convert to floats */
804 switch (image
->Type
) {
805 case GL_UNSIGNED_BYTE
:
807 GLubyte
*src
= (GLubyte
*) image
->Data
+ i
* width
* components
;
808 for (j
=0;j
<width
;j
++) {
810 rf
[j
] = gf
[j
] = bf
[j
] = UBYTE_TO_FLOAT(*src
++);
813 rf
[j
] = r_flag
? UBYTE_TO_FLOAT(*src
++) : 0.0;
814 gf
[j
] = g_flag
? UBYTE_TO_FLOAT(*src
++) : 0.0;
815 bf
[j
] = b_flag
? UBYTE_TO_FLOAT(*src
++) : 0.0;
817 af
[j
] = a_flag
? UBYTE_TO_FLOAT(*src
++) : 1.0;
823 GLfloat
*src
= (GLfloat
*) image
->Data
+ i
* width
* components
;
824 for (j
=0;j
<width
;j
++) {
826 rf
[j
] = gf
[j
] = bf
[j
] = *src
++;
829 rf
[j
] = r_flag
? *src
++ : 0.0;
830 gf
[j
] = g_flag
? *src
++ : 0.0;
831 bf
[j
] = b_flag
? *src
++ : 0.0;
833 af
[j
] = a_flag
? *src
++ : 1.0;
838 gl_problem( ctx
, "draw_rgba_pixels type" );
842 /* apply scale and bias */
843 if (ctx
->Pixel
.ScaleOrBiasRGBA
) {
844 gl_scale_and_bias_color(ctx
, width
, rf
, gf
, bf
, af
);
847 /* apply pixel mappings */
848 if (ctx
->Pixel
.MapColorFlag
) {
849 gl_map_color(ctx
, width
, rf
, gf
, bf
, af
);
852 /* convert to integers */
853 for (j
=0;j
<width
;j
++) {
854 rgba
[j
][RCOMP
] = (GLint
) (rf
[j
] * 255.0F
);
855 rgba
[j
][GCOMP
] = (GLint
) (gf
[j
] * 255.0F
);
856 rgba
[j
][BCOMP
] = (GLint
) (bf
[j
] * 255.0F
);
857 rgba
[j
][ACOMP
] = (GLint
) (af
[j
] * 255.0F
);
860 /* write to frame buffer */
862 (*ctx
->Driver
.WriteRGBASpan
)( ctx
, width
, x
, y
,
863 (const GLubyte (*)[4])rgba
, NULL
);
866 gl_write_zoomed_rgba_span( ctx
, width
, x
, y
, zspan
,
867 (const GLubyte (*)[4])rgba
, desty
);
870 gl_write_rgba_span( ctx
, (GLuint
) width
, x
, y
, zspan
, rgba
, GL_BITMAP
);
881 * Execute glDrawPixels
883 void gl_DrawPixels( GLcontext
* ctx
, struct gl_image
*image
)
885 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawPixels");
888 if (gl_image_error_test( ctx
, image
, "glDrawPixels" ))
891 if (ctx
->RenderMode
==GL_RENDER
) {
893 if (!ctx
->Current
.RasterPosValid
) {
897 x
= (GLint
) (ctx
->Current
.RasterPos
[0] + 0.5F
);
898 y
= (GLint
) (ctx
->Current
.RasterPos
[1] + 0.5F
);
900 switch (image
->Format
) {
902 draw_index_pixels( ctx
, x
, y
, image
);
904 case GL_STENCIL_INDEX
:
905 draw_stencil_pixels( ctx
, x
, y
, image
);
907 case GL_DEPTH_COMPONENT
:
908 draw_depth_pixels( ctx
, x
, y
, image
);
916 case GL_LUMINANCE_ALPHA
:
918 draw_rgba_pixels( ctx
, x
, y
, image
);
921 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawPixels" );
925 else if (ctx
->RenderMode
==GL_FEEDBACK
) {
926 if (ctx
->Current
.RasterPosValid
) {
928 GLfloat texcoord
[4], invq
;
929 UBYTE_RGBA_TO_FLOAT_RGBA(color
, ctx
->Current
.ByteColor
);
930 invq
= 1.0F
/ ctx
->Current
.Texcoord
[0][3];
931 texcoord
[0] = ctx
->Current
.Texcoord
[0][0] * invq
;
932 texcoord
[1] = ctx
->Current
.Texcoord
[0][1] * invq
;
933 texcoord
[2] = ctx
->Current
.Texcoord
[0][2] * invq
;
934 texcoord
[3] = ctx
->Current
.Texcoord
[0][3];
935 FEEDBACK_TOKEN( ctx
, (GLfloat
) (GLint
) GL_DRAW_PIXEL_TOKEN
);
936 gl_feedback_vertex( ctx
,
937 ctx
->Current
.RasterPos
,
938 color
, ctx
->Current
.Index
, texcoord
);
941 else if (ctx
->RenderMode
==GL_SELECT
) {
942 if (ctx
->Current
.RasterPosValid
) {
943 gl_update_hitflag( ctx
, ctx
->Current
.RasterPos
[2] );