xref: /reactos/dll/opengl/mesa/drawpix.c (revision 4561998a)
1 /* $Id: drawpix.c,v 1.16 1998/02/03 23:45:02 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.4
6  * Copyright (C) 1995-1997  Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: drawpix.c,v $
26  * Revision 1.16  1998/02/03 23:45:02  brianp
27  * added casts to prevent warnings with Amiga StormC compiler
28  *
29  * Revision 1.15  1997/08/26 02:10:11  brianp
30  * another bug fix related to glPixelStore()
31  *
32  * Revision 1.14  1997/08/24 02:31:23  brianp
33  * bug fix: glPixelStore() params weren't ignored during display list execute
34  *
35  * Revision 1.13  1997/07/24 01:25:01  brianp
36  * changed precompiled header symbol from PCH to PC_HEADER
37  *
38  * Revision 1.12  1997/06/20 02:18:23  brianp
39  * replaced Current.IntColor with Current.ByteColor
40  *
41  * Revision 1.11  1997/05/28 03:24:22  brianp
42  * added precompiled header (PCH) support
43  *
44  * Revision 1.10  1997/04/24 00:18:56  brianp
45  * added some missing UNDEFARRAY()s.  Reported by Randy Frank.
46  *
47  * Revision 1.9  1997/04/20 20:28:49  brianp
48  * replaced abort() with gl_problem()
49  *
50  * Revision 1.8  1997/04/11 23:24:25  brianp
51  * move call to gl_update_state() into gl_DrawPixels() from drawpixels()
52  *
53  * Revision 1.7  1997/03/18 01:55:47  brianp
54  * only generate feedback/selection if raster position is valid
55  *
56  * Revision 1.6  1997/02/10 20:26:57  brianp
57  * fixed memory leak in quickdraw_rgb()
58  *
59  * Revision 1.5  1997/02/03 20:30:31  brianp
60  * added a few DEFARRAY macros for BeOS
61  *
62  * Revision 1.4  1996/10/16 00:58:53  brianp
63  * renamed gl_drawpixels() to drawpixels()
64  *
65  * Revision 1.3  1996/09/27 01:26:25  brianp
66  * added missing default cases to switches
67  *
68  * Revision 1.2  1996/09/15 14:17:30  brianp
69  * now use GLframebuffer and GLvisual
70  *
71  * Revision 1.1  1996/09/13 01:38:16  brianp
72  * Initial revision
73  *
74  */
75 
76 
77 #ifdef PC_HEADER
78 #include "all.h"
79 #else
80 #include <stdlib.h>
81 #include <string.h>
82 #include "context.h"
83 #include "drawpix.h"
84 #include "feedback.h"
85 #include "dlist.h"
86 #include "macros.h"
87 #include "pixel.h"
88 #include "span.h"
89 #include "stencil.h"
90 #include "types.h"
91 #endif
92 
93 
94 
95 /* TODO:  apply texture mapping to fragments */
96 
97 
98 
99 static void draw_index_pixels( GLcontext* ctx, GLsizei width, GLsizei height,
100 			       GLenum type, const GLvoid *pixels )
101 {
102    GLint x, y, desty;
103    GLuint i, j;
104    GLdepth zspan[MAX_WIDTH];
105    GLboolean zoom;
106 
107    zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
108 
109    /* Position, depth of pixels */
110    x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
111    y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
112    desty = y;
113    if (ctx->Depth.Test) {
114       GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
115       for (i=0;i<width;i++) {
116 	 zspan[i] = zval;
117       }
118    }
119 
120    /* process the image row by row */
121    for (i=0;i<height;i++,y++) {
122       GLuint ispan[MAX_WIDTH];
123 
124       /* convert to uints */
125       switch (type) {
126 	 case GL_UNSIGNED_BYTE:
127 	    {
128 	       GLubyte *src = (GLubyte *) pixels + i * width;
129 	       for (j=0;j<width;j++) {
130 		  ispan[j] = (GLuint) *src++;
131 	       }
132 	    }
133 	    break;
134 	 case GL_BYTE:
135 	    {
136 	       GLbyte *src = (GLbyte *) pixels + i * width;
137 	       for (j=0;j<width;j++) {
138 		  ispan[j] = (GLuint) *src++;
139 	       }
140 	    }
141 	    break;
142 	 case GL_UNSIGNED_SHORT:
143 	    {
144 	       GLushort *src = (GLushort *) pixels + i * width;
145 	       for (j=0;j<width;j++) {
146 		  ispan[j] = (GLuint) *src++;
147 	       }
148 	    }
149 	    break;
150 	 case GL_SHORT:
151 	    {
152 	       GLshort *src = (GLshort *) pixels + i * width;
153 	       for (j=0;j<width;j++) {
154 		  ispan[j] = (GLuint) *src++;
155 	       }
156 	    }
157 	    break;
158 	 case GL_UNSIGNED_INT:
159 	    {
160 	       GLuint *src = (GLuint *) pixels + i * width;
161 	       for (j=0;j<width;j++) {
162 		  ispan[j] = *src++;
163 	       }
164 	    }
165 	    break;
166 	 case GL_INT:
167 	    {
168 	       GLint *src = (GLint *) pixels + i * width;
169 	       for (j=0;j<width;j++) {
170 		  ispan[j] = (GLuint) *src++;
171 	       }
172 	    }
173 	    break;
174 	 case GL_BITMAP:
175 	    /* TODO */
176 	    break;
177 	 case GL_FLOAT:
178 	    {
179 	       GLfloat *src = (GLfloat *) pixels + i * width;
180 	       for (j=0;j<width;j++) {
181 		  ispan[j] = (GLuint) (GLint) *src++;
182 	       }
183 	    }
184 	    break;
185 	 default:
186 	    gl_error( ctx, GL_INVALID_ENUM, "Internal: draw_index_pixels" );
187       }
188 
189       /* apply shift and offset */
190       if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
191 	 if (ctx->Pixel.IndexShift>=0) {
192 	    for (j=0;j<width;j++) {
193 	       ispan[j] = (ispan[j] << ctx->Pixel.IndexShift)
194 		          + ctx->Pixel.IndexOffset;
195 	    }
196 	 }
197 	 else {
198 	    for (j=0;j<width;j++) {
199 	       ispan[j] = (ispan[j] >> -ctx->Pixel.IndexShift)
200 		          + ctx->Pixel.IndexOffset;
201 	    }
202 	 }
203       }
204 
205       if (ctx->Visual->RGBAflag) {
206 	 /* Convert index to RGBA and write to frame buffer */
207 	 GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
208 	 GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
209 	 for (j=0;j<width;j++) {
210 	    red[j]   = (GLint) (ctx->Pixel.MapItoR[ispan[j]] * ctx->Visual->RedScale);
211 	    green[j] = (GLint) (ctx->Pixel.MapItoG[ispan[j]] * ctx->Visual->GreenScale);
212 	    blue[j]  = (GLint) (ctx->Pixel.MapItoB[ispan[j]] * ctx->Visual->BlueScale);
213 	    alpha[j] = (GLint) (ctx->Pixel.MapItoA[ispan[j]] * ctx->Visual->AlphaScale);
214 	 }
215          if (zoom) {
216             gl_write_zoomed_color_span( ctx, width, x, y, zspan,
217                                         red, green, blue, alpha, desty );
218          }
219          else {
220             gl_write_color_span( ctx, width, x, y, zspan,
221                                  red, green, blue, alpha, GL_BITMAP );
222          }
223       }
224       else {
225 	 /* optionally apply index map then write to frame buffer */
226 	 if (ctx->Pixel.MapColorFlag) {
227 	    for (j=0;j<width;j++) {
228 	       ispan[j] = ctx->Pixel.MapItoI[ispan[j]];
229 	    }
230 	 }
231          if (zoom) {
232             gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty );
233          }
234          else {
235             gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
236          }
237       }
238    }
239 
240 }
241 
242 
243 
244 static void draw_stencil_pixels( GLcontext* ctx, GLsizei width, GLsizei height,
245 			         GLenum type, const GLvoid *pixels )
246 {
247    GLint x, y, desty;
248    GLuint i, j;
249    GLboolean zoom;
250 
251    zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
252 
253    /* Position, depth of pixels */
254    x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
255    y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
256    desty = y;
257 
258    /* process the image row by row */
259    for (i=0;i<height;i++,y++) {
260       GLubyte stencil[MAX_WIDTH];
261 
262       /* convert to ubytes */
263       switch (type) {
264 	 case GL_UNSIGNED_BYTE:
265 	    {
266 	       GLubyte *src = (GLubyte *) pixels + i * width;
267 	       MEMCPY( stencil, src, width );
268 	    }
269 	    break;
270 	 case GL_BYTE:
271 	    {
272 	       GLbyte *src = (GLbyte *) pixels + i * width;
273 	       MEMCPY( stencil, src, width );
274 	    }
275 	    break;
276 	 case GL_UNSIGNED_SHORT:
277 	    {
278 	       GLushort *src = (GLushort *) pixels + i * width;
279 	       for (j=0;j<width;j++) {
280 		  stencil[j] = (GLubyte) ((*src++) & 0xff);
281 	       }
282 	    }
283 	    break;
284 	 case GL_SHORT:
285 	    {
286 	       GLshort *src = (GLshort *) pixels + i * width;
287 	       for (j=0;j<width;j++) {
288 		  stencil[j] = (GLubyte) ((*src++) & 0xff);
289 	       }
290 	    }
291 	    break;
292 	 case GL_UNSIGNED_INT:
293 	    {
294 	       GLuint *src = (GLuint *) pixels + i * width;
295 	       for (j=0;j<width;j++) {
296 		  stencil[j] = (GLubyte) ((*src++) & 0xff);
297 	       }
298 	    }
299 	    break;
300 	 case GL_INT:
301 	    {
302 	       GLint *src = (GLint *) pixels + i * width;
303 	       for (j=0;j<width;j++) {
304 		  stencil[j] = (GLubyte) ((*src++) & 0xff);
305 	       }
306 	    }
307 	    break;
308 	 case GL_BITMAP:
309 	    /* TODO */
310 	    break;
311 	 case GL_FLOAT:
312 	    {
313 	       GLfloat *src = (GLfloat *) pixels + i * width;
314 	       for (j=0;j<width;j++) {
315 		  stencil[j] = (GLubyte) (((GLint) *src++) & 0xff);
316 	       }
317 	    }
318 	    break;
319 	 default:
320 	    gl_error( ctx, GL_INVALID_ENUM, "Internal: draw_stencil_pixels" );
321       }
322 
323       /* apply shift and offset */
324       if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
325 	 if (ctx->Pixel.IndexShift>=0) {
326 	    for (j=0;j<width;j++) {
327 	       stencil[j] = (stencil[j] << ctx->Pixel.IndexShift)
328 		          + ctx->Pixel.IndexOffset;
329 	    }
330 	 }
331 	 else {
332 	    for (j=0;j<width;j++) {
333 	       stencil[j] = (stencil[j] >> -ctx->Pixel.IndexShift)
334 		          + ctx->Pixel.IndexOffset;
335 	    }
336 	 }
337       }
338 
339       /* mapping */
340       if (ctx->Pixel.MapStencilFlag) {
341 	 for (j=0;j<width;j++) {
342 	    stencil[j] = ctx->Pixel.MapStoS[ stencil[j] ];
343 	 }
344       }
345 
346       /* write stencil values to stencil buffer */
347       if (zoom) {
348          gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y, stencil, desty );
349       }
350       else {
351          gl_write_stencil_span( ctx, (GLuint) width, x, y, stencil );
352       }
353    }
354 }
355 
356 
357 
358 static void draw_depth_pixels( GLcontext* ctx, GLsizei width, GLsizei height,
359 			       GLenum type, const GLvoid *pixels )
360 {
361    GLint x, y, desty;
362    GLubyte red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH], alpha[MAX_WIDTH];
363    GLuint ispan[MAX_WIDTH];
364    GLboolean bias_or_scale;
365    GLboolean zoom;
366 
367    bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
368    zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
369 
370    /* Position, depth of pixels */
371    x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
372    y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
373    desty = y;
374 
375    /* Color or index */
376    if (ctx->Visual->RGBAflag) {
377       GLint r, g, b, a;
378       r = (GLint) (ctx->Current.RasterColor[0] * ctx->Visual->RedScale);
379       g = (GLint) (ctx->Current.RasterColor[1] * ctx->Visual->GreenScale);
380       b = (GLint) (ctx->Current.RasterColor[2] * ctx->Visual->BlueScale);
381       a = (GLint) (ctx->Current.RasterColor[3] * ctx->Visual->AlphaScale);
382       MEMSET( red,   r, width );
383       MEMSET( green, g, width );
384       MEMSET( blue,  b, width );
385       MEMSET( alpha, a, width );
386    }
387    else {
388       GLuint i;
389       for (i=0;i<width;i++) {
390 	 ispan[i] = ctx->Current.RasterIndex;
391       }
392    }
393 
394    if (type==GL_UNSIGNED_INT && !bias_or_scale && !zoom && ctx->Visual->RGBAflag)
395    {
396       /* Special case: directly write 32-bit depth values */
397       GLuint i, j;
398       /* Compute shift value to scale 32-bit uints down to depth values. */
399       GLuint shift = 0;
400       GLuint max = MAX_DEPTH;
401       while ((max&0x80000000)==0) {
402          max = max << 1;
403          shift++;
404       }
405       for (j=0;j<height;j++,y++) {
406          GLdepth zspan[MAX_WIDTH];
407          GLuint *zptr = (GLuint *) pixels + j * width;
408          for (i=0;i<width;i++) {
409             zspan[i] = zptr[i] >> shift;
410          }
411          gl_write_color_span( ctx, width, x, y, zspan,
412                               red, green, blue, alpha, GL_BITMAP );
413       }
414    }
415    else {
416       /* General case (slower) */
417       GLuint i, j;
418 
419       /* process image row by row */
420       for (i=0;i<height;i++,y++) {
421          GLfloat depth[MAX_WIDTH];
422          GLdepth zspan[MAX_WIDTH];
423 
424          switch (type) {
425             case GL_UNSIGNED_BYTE:
426                {
427                   GLubyte *src = (GLubyte *) pixels + i * width;
428                   for (j=0;j<width;j++) {
429                      depth[j] = UBYTE_TO_FLOAT( *src++ );
430                   }
431                }
432                break;
433             case GL_BYTE:
434                {
435                   GLbyte *src = (GLbyte *) pixels + i * width;
436                   for (j=0;j<width;j++) {
437                      depth[j] = BYTE_TO_FLOAT( *src++ );
438                   }
439                }
440                break;
441             case GL_UNSIGNED_SHORT:
442                {
443                   GLushort *src = (GLushort *) pixels + i * width;
444                   for (j=0;j<width;j++) {
445                      depth[j] = USHORT_TO_FLOAT( *src++ );
446                   }
447                }
448                break;
449             case GL_SHORT:
450                {
451                   GLshort *src = (GLshort *) pixels + i * width;
452                   for (j=0;j<width;j++) {
453                      depth[j] = SHORT_TO_FLOAT( *src++ );
454                   }
455                }
456                break;
457             case GL_UNSIGNED_INT:
458                {
459                   GLuint *src = (GLuint *) pixels + i * width;
460                   for (j=0;j<width;j++) {
461                      depth[j] = UINT_TO_FLOAT( *src++ );
462                   }
463                }
464                break;
465             case GL_INT:
466                {
467                   GLint *src = (GLint *) pixels + i * width;
468                   for (j=0;j<width;j++) {
469                      depth[j] = INT_TO_FLOAT( *src++ );
470                   }
471                }
472                break;
473             case GL_FLOAT:
474                {
475                   GLfloat *src = (GLfloat *) pixels + i * width;
476                   for (j=0;j<width;j++) {
477                      depth[j] = *src++;
478                   }
479                }
480                break;
481             default:
482                gl_problem(ctx, "Bad type in draw_depth_pixels");
483                return;
484          }
485 
486          /* apply depth scale and bias */
487          if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) {
488             for (j=0;j<width;j++) {
489                depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
490             }
491          }
492 
493          /* clamp depth values to [0,1] and convert from floats to integers */
494          for (j=0;j<width;j++) {
495             zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE);
496          }
497 
498          if (ctx->Visual->RGBAflag) {
499             if (zoom) {
500                gl_write_zoomed_color_span( ctx, width, x, y, zspan,
501                                            red, green, blue, alpha, desty );
502             }
503             else {
504                gl_write_color_span( ctx, width, x, y, zspan,
505                                     red, green, blue, alpha, GL_BITMAP );
506             }
507          }
508          else {
509             if (zoom) {
510                gl_write_zoomed_index_span( ctx, width, x, y, zspan,
511                                            ispan, GL_BITMAP );
512             }
513             else {
514                gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
515             }
516          }
517 
518       }
519    }
520 }
521 
522 
523 
524 static void draw_color_pixels(GLcontext* ctx, GLsizei width, GLsizei height,
525         GLenum format, GLenum type, const GLvoid *pixels)
526 {
527     GLuint i, j;
528     GLint x, y, desty;
529     GLdepth zspan[MAX_WIDTH];
530     GLboolean scale_or_bias, quick_draw;
531     GLboolean zoom;
532 
533     zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
534 
535     /* Position, depth of pixels */
536     x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
537     y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
538     desty = y;
539     if (ctx->Depth.Test)
540     {
541         /* fill in array of z values */
542         GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
543         for (i = 0; i < width; i++)
544         {
545             zspan[i] = z;
546         }
547     }
548 
549     /* Determine if scaling and/or biasing is needed */
550     if (ctx->Pixel.RedScale != 1.0F || ctx->Pixel.RedBias != 0.0F
551             || ctx->Pixel.GreenScale != 1.0F || ctx->Pixel.GreenBias != 0.0F
552             || ctx->Pixel.BlueScale != 1.0F || ctx->Pixel.BlueBias != 0.0F
553             || ctx->Pixel.AlphaScale != 1.0F || ctx->Pixel.AlphaBias != 0.0F)
554     {
555         scale_or_bias = GL_TRUE;
556     }
557     else
558     {
559         scale_or_bias = GL_FALSE;
560     }
561 
562     /* Determine if we can directly call the device driver function */
563     if (ctx->RasterMask == 0 && !zoom && x >= 0 && y >= 0
564             && x + width <= ctx->Buffer->Width
565             && y + height <= ctx->Buffer->Height)
566     {
567         quick_draw = GL_TRUE;
568     }
569     else
570     {
571         quick_draw = GL_FALSE;
572     }
573 
574     /* First check for common cases */
575     if (type == GL_UNSIGNED_BYTE
576             && (format == GL_RGB || format == GL_LUMINANCE || format == GL_BGR_EXT)
577             && !ctx->Pixel.MapColorFlag
578             && !scale_or_bias && ctx->Visual->EightBitColor)
579     {
580         DEFARRAY(GLubyte, alpha, MAX_WIDTH);
581         GLubyte *src = (GLubyte *) pixels;
582         /* constant alpha */
583         MEMSET(alpha, (GLint ) ctx->Visual->AlphaScale, width);
584         if (format == GL_RGB)
585         {
586             /* 8-bit RGB pixels */
587             DEFARRAY(GLubyte, red, MAX_WIDTH);
588             DEFARRAY(GLubyte, green, MAX_WIDTH);
589             DEFARRAY(GLubyte, blue, MAX_WIDTH);
590             for (i = 0; i < height; i++, y++)
591             {
592                 for (j = 0; j < width; j++)
593                 {
594                     red[j] = *src++;
595                     green[j] = *src++;
596                     blue[j] = *src++;
597                 }
598                 if (quick_draw)
599                 {
600                     (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, red, green,
601                             blue, alpha, NULL);
602                 }
603                 else if (zoom)
604                 {
605                     gl_write_zoomed_color_span(ctx, (GLuint) width, x, y, zspan,
606                             red, green, blue, alpha, desty);
607                 }
608                 else
609                 {
610                     gl_write_color_span(ctx, (GLuint) width, x, y, zspan, red,
611                             green, blue, alpha, GL_BITMAP);
612                 }
613             }
614             UNDEFARRAY( red );
615             UNDEFARRAY( green );
616             UNDEFARRAY( blue );
617         }
618         else if (format == GL_BGR_EXT)
619         {
620             /* 8-bit BGR pixels */
621             DEFARRAY(GLubyte, red, MAX_WIDTH);
622             DEFARRAY(GLubyte, green, MAX_WIDTH);
623             DEFARRAY(GLubyte, blue, MAX_WIDTH);
624             for (i = 0; i < height; i++, y++)
625             {
626                 for (j = 0; j < width; j++)
627                 {
628                     blue[j] = *src++;
629                     green[j] = *src++;
630                     red[j] = *src++;
631                 }
632                 if (quick_draw)
633                 {
634                     (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, red, green,
635                             blue, alpha, NULL);
636                 }
637                 else if (zoom)
638                 {
639                     gl_write_zoomed_color_span(ctx, (GLuint) width, x, y, zspan,
640                             red, green, blue, alpha, desty);
641                 }
642                 else
643                 {
644                     gl_write_color_span(ctx, (GLuint) width, x, y, zspan, red,
645                             green, blue, alpha, GL_BITMAP);
646                 }
647             }
648             UNDEFARRAY( red );
649             UNDEFARRAY( green );
650             UNDEFARRAY( blue );
651         }
652         else
653         {
654             /* 8-bit Luminance pixels */
655             GLubyte *lum = (GLubyte *) pixels;
656             for (i = 0; i < height; i++, y++, lum += width)
657             {
658                 if (quick_draw)
659                 {
660                     (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, lum, lum,
661                             lum, alpha, NULL);
662                 }
663                 else if (zoom)
664                 {
665                     gl_write_zoomed_color_span(ctx, (GLuint) width, x, y, zspan,
666                             lum, lum, lum, alpha, desty);
667                 }
668                 else
669                 {
670                     gl_write_color_span(ctx, (GLuint) width, x, y, zspan, lum,
671                             lum, lum, alpha, GL_BITMAP);
672                 }
673             }
674         }
675         UNDEFARRAY( alpha );
676     }
677     else
678     {
679         /* General solution */
680         GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
681         GLuint components;
682         GLboolean is_bgr;
683 
684         r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
685         is_bgr = GL_FALSE;
686         switch (format)
687         {
688         case GL_RED:
689             r_flag = GL_TRUE;
690             components = 1;
691             break;
692         case GL_GREEN:
693             g_flag = GL_TRUE;
694             components = 1;
695             break;
696         case GL_BLUE:
697             b_flag = GL_TRUE;
698             components = 1;
699             break;
700         case GL_ALPHA:
701             a_flag = GL_TRUE;
702             components = 1;
703             break;
704         case GL_RGB:
705             r_flag = g_flag = b_flag = GL_TRUE;
706             components = 3;
707             break;
708         case GL_BGR_EXT:
709             is_bgr = GL_TRUE;
710             r_flag = g_flag = b_flag = GL_TRUE;
711             components = 3;
712             break;
713         case GL_LUMINANCE:
714             l_flag = GL_TRUE;
715             components = 1;
716             break;
717         case GL_LUMINANCE_ALPHA:
718             l_flag = a_flag = GL_TRUE;
719             components = 2;
720             break;
721         case GL_RGBA:
722             r_flag = g_flag = b_flag = a_flag = GL_TRUE;
723             components = 4;
724             break;
725         case GL_BGRA_EXT:
726             is_bgr = GL_TRUE;
727             r_flag = g_flag = b_flag = a_flag = GL_TRUE;
728             components = 4;
729             break;
730         default:
731             gl_problem(ctx, "Bad type in draw_color_pixels");
732             return;
733         }
734 
735         /* process the image row by row */
736         for (i = 0; i < height; i++, y++)
737         {
738             DEFARRAY(GLfloat, rf, MAX_WIDTH);
739             DEFARRAY(GLfloat, gf, MAX_WIDTH);
740             DEFARRAY(GLfloat, bf, MAX_WIDTH);
741             DEFARRAY(GLfloat, af, MAX_WIDTH);
742             DEFARRAY(GLubyte, red, MAX_WIDTH);
743             DEFARRAY(GLubyte, green, MAX_WIDTH);
744             DEFARRAY(GLubyte, blue, MAX_WIDTH);
745             DEFARRAY(GLubyte, alpha, MAX_WIDTH);
746 
747             /* convert to floats */
748             switch (type)
749             {
750             case GL_UNSIGNED_BYTE:
751             {
752                 GLubyte *src = (GLubyte *) pixels + i * width * components;
753                 for (j = 0; j < width; j++)
754                 {
755                     if (l_flag)
756                     {
757                         rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++);
758                     }
759                     else if (is_bgr)
760                     {
761                         bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
762                         gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
763                         rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
764                     }
765                     else
766                     {
767                         rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
768                         gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
769                         bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
770                     }
771                     af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0;
772                 }
773             }
774                 break;
775             case GL_BYTE:
776             {
777                 GLbyte *src = (GLbyte *) pixels + i * width * components;
778                 for (j = 0; j < width; j++)
779                 {
780                     if (l_flag)
781                     {
782                         rf[j] = gf[j] = bf[j] = BYTE_TO_FLOAT(*src++);
783                     }
784                     else if (is_bgr)
785                     {
786                         bf[j] = b_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
787                         gf[j] = g_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
788                         rf[j] = r_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
789                     }
790                     else
791                     {
792                         rf[j] = r_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
793                         gf[j] = g_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
794                         bf[j] = b_flag ? BYTE_TO_FLOAT(*src++) : 0.0;
795                     }
796                     af[j] = a_flag ? BYTE_TO_FLOAT(*src++) : 1.0;
797                 }
798             }
799                 break;
800             case GL_BITMAP:
801                 /* special case */
802                 break;
803             case GL_UNSIGNED_SHORT:
804             {
805                 GLushort *src = (GLushort *) pixels + i * width * components;
806                 for (j = 0; j < width; j++)
807                 {
808                     if (l_flag)
809                     {
810                         rf[j] = gf[j] = bf[j] = USHORT_TO_FLOAT(*src++);
811                     }
812                     else if (is_bgr)
813                     {
814                         bf[j] = b_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
815                         gf[j] = g_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
816                         rf[j] = r_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
817                     }
818                     else
819                     {
820                         rf[j] = r_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
821                         gf[j] = g_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
822                         bf[j] = b_flag ? USHORT_TO_FLOAT(*src++) : 0.0;
823                     }
824                     af[j] = a_flag ? USHORT_TO_FLOAT(*src++) : 1.0;
825                 }
826             }
827                 break;
828             case GL_SHORT:
829             {
830                 GLshort *src = (GLshort *) pixels + i * width * components;
831                 for (j = 0; j < width; j++)
832                 {
833                     if (l_flag)
834                     {
835                         rf[j] = gf[j] = bf[j] = SHORT_TO_FLOAT(*src++);
836                     }
837                     else if (is_bgr)
838                     {
839                         bf[j] = b_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
840                         gf[j] = g_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
841                         rf[j] = r_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
842                     }
843                     else
844                     {
845                         rf[j] = r_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
846                         gf[j] = g_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
847                         bf[j] = b_flag ? SHORT_TO_FLOAT(*src++) : 0.0;
848                     }
849                     af[j] = a_flag ? SHORT_TO_FLOAT(*src++) : 1.0;
850                 }
851             }
852                 break;
853             case GL_UNSIGNED_INT:
854             {
855                 GLuint *src = (GLuint *) pixels + i * width * components;
856                 for (j = 0; j < width; j++)
857                 {
858                     if (l_flag)
859                     {
860                         rf[j] = gf[j] = bf[j] = UINT_TO_FLOAT(*src++);
861                     }
862                     else if (is_bgr)
863                     {
864                         bf[j] = b_flag ? UINT_TO_FLOAT(*src++) : 0.0;
865                         gf[j] = g_flag ? UINT_TO_FLOAT(*src++) : 0.0;
866                         rf[j] = r_flag ? UINT_TO_FLOAT(*src++) : 0.0;
867                     }
868                     else
869                     {
870                         rf[j] = r_flag ? UINT_TO_FLOAT(*src++) : 0.0;
871                         gf[j] = g_flag ? UINT_TO_FLOAT(*src++) : 0.0;
872                         bf[j] = b_flag ? UINT_TO_FLOAT(*src++) : 0.0;
873                     }
874                     af[j] = a_flag ? UINT_TO_FLOAT(*src++) : 1.0;
875                 }
876             }
877                 break;
878             case GL_INT:
879             {
880                 GLint *src = (GLint *) pixels + i * width * components;
881                 for (j = 0; j < width; j++)
882                 {
883                     if (l_flag)
884                     {
885                         rf[j] = gf[j] = bf[j] = INT_TO_FLOAT(*src++);
886                     }
887                     else if (is_bgr)
888                     {
889                         bf[j] = b_flag ? INT_TO_FLOAT(*src++) : 0.0;
890                         gf[j] = g_flag ? INT_TO_FLOAT(*src++) : 0.0;
891                         rf[j] = r_flag ? INT_TO_FLOAT(*src++) : 0.0;
892                     }
893                     else
894                     {
895                         rf[j] = r_flag ? INT_TO_FLOAT(*src++) : 0.0;
896                         gf[j] = g_flag ? INT_TO_FLOAT(*src++) : 0.0;
897                         bf[j] = b_flag ? INT_TO_FLOAT(*src++) : 0.0;
898                     }
899                     af[j] = a_flag ? INT_TO_FLOAT(*src++) : 1.0;
900                 }
901             }
902                 break;
903             case GL_FLOAT:
904             {
905                 GLfloat *src = (GLfloat *) pixels + i * width * components;
906                 for (j = 0; j < width; j++)
907                 {
908                     if (l_flag)
909                     {
910                         rf[j] = gf[j] = bf[j] = *src++;
911                     }
912                     else if (is_bgr)
913                     {
914                         bf[j] = b_flag ? *src++ : 0.0;
915                         gf[j] = g_flag ? *src++ : 0.0;
916                         rf[j] = r_flag ? *src++ : 0.0;
917                     }
918                     else
919                     {
920                         rf[j] = r_flag ? *src++ : 0.0;
921                         gf[j] = g_flag ? *src++ : 0.0;
922                         bf[j] = b_flag ? *src++ : 0.0;
923                     }
924                     af[j] = a_flag ? *src++ : 1.0;
925                 }
926             }
927                 break;
928             default:
929                 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels");
930                 return;
931             }
932 
933             /* apply scale and bias */
934             if (scale_or_bias)
935             {
936                 for (j = 0; j < width; j++)
937                 {
938                     GLfloat r, g, b, a;
939                     r = rf[j] * ctx->Pixel.RedScale + ctx->Pixel.RedBias;
940                     g = gf[j] * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
941                     b = bf[j] * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias;
942                     a = af[j] * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
943                     rf[j] = CLAMP(r, 0.0, 1.0);
944                     gf[j] = CLAMP(g, 0.0, 1.0);
945                     bf[j] = CLAMP(b, 0.0, 1.0);
946                     af[j] = CLAMP(a, 0.0, 1.0);
947                 }
948             }
949 
950             /* apply pixel mappings */
951             if (ctx->Pixel.MapColorFlag)
952             {
953                 GLfloat rscale = ctx->Pixel.MapRtoRsize - 1;
954                 GLfloat gscale = ctx->Pixel.MapGtoGsize - 1;
955                 GLfloat bscale = ctx->Pixel.MapBtoBsize - 1;
956                 GLfloat ascale = ctx->Pixel.MapAtoAsize - 1;
957                 for (j = 0; j < width; j++)
958                 {
959                     rf[j] = ctx->Pixel.MapRtoR[(GLint) (rf[j] * rscale)];
960                     gf[j] = ctx->Pixel.MapGtoG[(GLint) (gf[j] * gscale)];
961                     bf[j] = ctx->Pixel.MapBtoB[(GLint) (bf[j] * bscale)];
962                     af[j] = ctx->Pixel.MapAtoA[(GLint) (af[j] * ascale)];
963                 }
964             }
965 
966             /* convert to integers */
967             for (j = 0; j < width; j++)
968             {
969                 red[j] = (GLint) (rf[j] * ctx->Visual->RedScale);
970                 green[j] = (GLint) (gf[j] * ctx->Visual->GreenScale);
971                 blue[j] = (GLint) (bf[j] * ctx->Visual->BlueScale);
972                 alpha[j] = (GLint) (af[j] * ctx->Visual->AlphaScale);
973             }
974 
975             /* write to frame buffer */
976             if (quick_draw)
977             {
978                 (*ctx->Driver.WriteColorSpan)(ctx, width, x, y, red, green,
979                         blue, alpha, NULL);
980             }
981             else if (zoom)
982             {
983                 gl_write_zoomed_color_span(ctx, width, x, y, zspan, red, green,
984                         blue, alpha, desty);
985             }
986             else
987             {
988                 gl_write_color_span(ctx, (GLuint) width, x, y, zspan, red,
989                         green, blue, alpha, GL_BITMAP);
990             }
991 
992             UNDEFARRAY(rf);
993             UNDEFARRAY(gf);
994             UNDEFARRAY(bf);
995             UNDEFARRAY(af);
996             UNDEFARRAY(red);
997             UNDEFARRAY(green);
998             UNDEFARRAY(blue);
999             UNDEFARRAY(alpha);
1000         }
1001     }
1002 
1003 }
1004 
1005 
1006 
1007 /*
1008  * Do a glDrawPixels( w, h, GL_RGB, GL_UNSIGNED_BYTE, pixels ) optimized
1009  * for the case of no pixel mapping, no scale, no bias, no zoom, default
1010  * storage mode, no raster ops, and no pixel clipping.
1011  * Return:  GL_TRUE if success
1012  *          GL_FALSE if conditions weren't met for optimized drawing
1013  */
1014 static GLboolean quickdraw_rgb( GLcontext* ctx, GLsizei width, GLsizei height,
1015                                 const void *pixels )
1016 {
1017    DEFARRAY( GLubyte, red, MAX_WIDTH );
1018    DEFARRAY( GLubyte, green, MAX_WIDTH );
1019    DEFARRAY( GLubyte, blue, MAX_WIDTH );
1020    DEFARRAY( GLubyte, alpha, MAX_WIDTH );
1021    GLint i, j;
1022    GLint x, y;
1023    GLint bytes_per_row;
1024    GLboolean result;
1025 
1026    bytes_per_row = width * 3 + (width % ctx->Unpack.Alignment);
1027 
1028    if (!ctx->Current.RasterPosValid) {
1029       /* This is success, actually. */
1030       result = GL_TRUE;
1031    }
1032    else {
1033       x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
1034       y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
1035 
1036       if (x<0 || y<0
1037           || x+width>ctx->Buffer->Width || y+height>ctx->Buffer->Height) {
1038          result = GL_FALSE;  /* can't handle this situation */
1039       }
1040       else {
1041          /* constant alpha */
1042          for (j=0;j<width;j++) {
1043             alpha[j] = (GLint) ctx->Visual->AlphaScale;
1044          }
1045 
1046          /* write directly to device driver */
1047          for (i=0;i<height;i++) {
1048             /* each row of pixel data starts at 4-byte boundary */
1049             GLubyte *src = (GLubyte *) pixels + i * bytes_per_row;
1050             for (j=0;j<width;j++) {
1051                red[j]   = *src++;
1052                green[j] = *src++;
1053                blue[j]  = *src++;
1054             }
1055             (*ctx->Driver.WriteColorSpan)( ctx, width, x, y+i,
1056                                            red, green, blue, alpha, NULL);
1057          }
1058          result = GL_TRUE;
1059       }
1060    }
1061 
1062    UNDEFARRAY( red );
1063    UNDEFARRAY( green );
1064    UNDEFARRAY( blue );
1065    UNDEFARRAY( alpha );
1066 
1067    return result;
1068 }
1069 
1070 
1071 
1072 /*
1073  * Implements general glDrawPixels operation.
1074  */
1075 static void drawpixels( GLcontext* ctx, GLsizei width, GLsizei height,
1076                         GLenum format, GLenum type, const GLvoid *pixels )
1077 {
1078    if (INSIDE_BEGIN_END(ctx)) {
1079       gl_error( ctx, GL_INVALID_OPERATION, "glDrawPixels" );
1080       return;
1081    }
1082 
1083    if (ctx->RenderMode==GL_RENDER) {
1084       if (!ctx->Current.RasterPosValid) {
1085 	 return;
1086       }
1087       switch (format) {
1088 	 case GL_COLOR_INDEX:
1089             draw_index_pixels( ctx, width, height, type, pixels );
1090 	    break;
1091 	 case GL_STENCIL_INDEX:
1092 	    draw_stencil_pixels( ctx, width, height, type, pixels );
1093 	    break;
1094 	 case GL_DEPTH_COMPONENT:
1095 	    draw_depth_pixels( ctx, width, height, type, pixels );
1096 	    break;
1097 	 case GL_RED:
1098 	 case GL_GREEN:
1099 	 case GL_BLUE:
1100 	 case GL_ALPHA:
1101 	 case GL_RGB:
1102 	 case GL_BGR_EXT:
1103 	 case GL_LUMINANCE:
1104 	 case GL_LUMINANCE_ALPHA:
1105 	 case GL_RGBA:
1106 	 case GL_BGRA_EXT:
1107             draw_color_pixels( ctx, width, height, format, type, pixels );
1108 	    break;
1109 	 default:
1110 	    gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" );
1111       }
1112    }
1113    else if (ctx->RenderMode==GL_FEEDBACK) {
1114       if (ctx->Current.RasterPosValid) {
1115          GLfloat color[4], texcoord[4], invq;
1116          color[0] = ctx->Current.ByteColor[0] * ctx->Visual->InvRedScale;
1117          color[1] = ctx->Current.ByteColor[1] * ctx->Visual->InvGreenScale;
1118          color[2] = ctx->Current.ByteColor[2] * ctx->Visual->InvBlueScale;
1119          color[3] = ctx->Current.ByteColor[3] * ctx->Visual->InvAlphaScale;
1120          invq = 1.0F / ctx->Current.TexCoord[3];
1121          texcoord[0] = ctx->Current.TexCoord[0] * invq;
1122          texcoord[1] = ctx->Current.TexCoord[1] * invq;
1123          texcoord[2] = ctx->Current.TexCoord[2] * invq;
1124          texcoord[3] = ctx->Current.TexCoord[3];
1125          FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
1126          gl_feedback_vertex( ctx, ctx->Current.RasterPos[0],
1127                              ctx->Current.RasterPos[1],
1128                              ctx->Current.RasterPos[2],
1129                              ctx->Current.RasterPos[3],
1130                              color, ctx->Current.Index, texcoord );
1131       }
1132    }
1133    else if (ctx->RenderMode==GL_SELECT) {
1134       if (ctx->Current.RasterPosValid) {
1135          gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
1136       }
1137    }
1138 }
1139 
1140 
1141 
1142 /*
1143  * Compile OR Execute a glDrawPixels!
1144  */
1145 void gl_DrawPixels( GLcontext* ctx, GLsizei width, GLsizei height,
1146                     GLenum format, GLenum type, const GLvoid *pixels )
1147 {
1148    GLvoid *image;
1149 
1150    if (width<0 || height<0) {
1151       gl_error( ctx, GL_INVALID_VALUE, "glDrawPixels" );
1152       return;
1153    }
1154 
1155    if (ctx->NewState) {
1156       gl_update_state(ctx);
1157    }
1158 
1159    /* Let the device driver take a crack at glDrawPixels */
1160    if (!ctx->CompileFlag && ctx->Driver.DrawPixels) {
1161       GLint x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
1162       GLint y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
1163       if ((*ctx->Driver.DrawPixels)( ctx, x, y, width, height,
1164                                       format, type, GL_FALSE, pixels )) {
1165          /* Device driver did the job */
1166          return;
1167       }
1168    }
1169 
1170    if (format==GL_RGB && type==GL_UNSIGNED_BYTE && ctx->FastDrawPixels
1171        && !ctx->CompileFlag && ctx->RenderMode==GL_RENDER
1172        && ctx->RasterMask==0 && ctx->CallDepth==0) {
1173       /* optimized path */
1174       if (quickdraw_rgb( ctx, width, height, pixels )) {
1175          /* success */
1176          return;
1177       }
1178    }
1179 
1180    /* take the general path */
1181 
1182    /* THIS IS A REAL HACK - FIX IN MESA 2.5
1183     * If we're inside glCallList then we don't have to unpack the pixels again.
1184     */
1185    if (ctx->CallDepth == 0) {
1186       image = gl_unpack_pixels( ctx, width, height, format, type, pixels );
1187       if (!image) {
1188          gl_error( ctx, GL_OUT_OF_MEMORY, "glDrawPixels" );
1189          return;
1190       }
1191    }
1192    else {
1193       image = (GLvoid *) pixels;
1194    }
1195 
1196    if (ctx->CompileFlag) {
1197       gl_save_DrawPixels( ctx, width, height, format, type, image );
1198    }
1199    if (ctx->ExecuteFlag) {
1200       drawpixels( ctx, width, height, format, type, image );
1201       if (!ctx->CompileFlag) {
1202          /* may discard unpacked image now */
1203          if (image!=pixels)
1204             free( image );
1205       }
1206    }
1207 }
1208