drawpix.c revision 2b2e925ea4a5652b0ab73b1efbce345a42663842
1/* $Id: drawpix.c,v 1.17 2000/04/07 16:27:26 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.3
6 *
7 * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28#ifdef PC_HEADER
29#include "all.h"
30#else
31#include "glheader.h"
32#include "context.h"
33#include "drawpix.h"
34#include "feedback.h"
35#include "image.h"
36#include "macros.h"
37#include "mem.h"
38#include "mmath.h"
39#include "pixel.h"
40#include "pixeltex.h"
41#include "span.h"
42#include "state.h"
43#include "stencil.h"
44#include "texture.h"
45#include "types.h"
46#include "zoom.h"
47#endif
48
49
50
51/*
52 * Given the dest position, size and skipPixels and skipRows values
53 * for a glDrawPixels command, perform clipping of the image bounds
54 * so the result lies withing the context's buffer bounds.
55 * Return:  GL_TRUE if image is ready for drawing
56 *          GL_FALSE if image was completely clipped away (draw nothing)
57 */
58GLboolean
59_mesa_clip_pixelrect(const GLcontext *ctx,
60                     GLint *destX, GLint *destY,
61                     GLsizei *width, GLsizei *height,
62                     GLint *skipPixels, GLint *skipRows)
63{
64   const GLframebuffer *buffer = ctx->DrawBuffer;
65
66   /* left clipping */
67   if (*destX < buffer->Xmin) {
68      *skipPixels += (buffer->Xmin - *destX);
69      *width -= (buffer->Xmin - *destX);
70      *destX = buffer->Xmin;
71   }
72   /* right clipping */
73   if (*destX + *width > buffer->Xmax)
74      *width -= (*destX + *width - buffer->Xmax - 1);
75
76   if (*width <= 0)
77      return GL_FALSE;
78
79   /* bottom clipping */
80   if (*destY < buffer->Ymin) {
81      *skipRows += (buffer->Ymin - *destY);
82      *height -= (buffer->Ymin - *destY);
83      *destY = buffer->Ymin;
84   }
85   /* top clipping */
86   if (*destY + *height > buffer->Ymax)
87      *height -= (*destY + *height - buffer->Ymax - 1);
88
89   if (*height <= 0)
90      return GL_TRUE;
91
92   return GL_TRUE;
93}
94
95
96
97/*
98 * Try to do a fast and simple RGB(a) glDrawPixels.
99 * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
100 */
101static GLboolean
102simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
103                   GLsizei width, GLsizei height, GLenum format, GLenum type,
104                   const GLvoid *pixels )
105{
106   const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
107   GLubyte rgb[MAX_WIDTH][3];
108   GLubyte rgba[MAX_WIDTH][4];
109
110   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels",
111						  GL_FALSE);
112
113
114   if (!ctx->Current.RasterPosValid) {
115      /* no-op */
116      return GL_TRUE;
117   }
118
119   if (ctx->NewState) {
120      gl_update_state(ctx);
121   }
122
123   if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
124       && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0
125       && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0
126       && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0
127       && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0
128       && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0
129       && ctx->Pixel.MapColorFlag==0
130       && ctx->Texture.ReallyEnabled == 0
131       && unpack->Alignment==1
132       && !unpack->SwapBytes
133       && !unpack->LsbFirst) {
134
135      GLint destX = x;
136      GLint destY = y;
137      GLint drawWidth = width;           /* actual width drawn */
138      GLint drawHeight = height;         /* actual height drawn */
139      GLint skipPixels = unpack->SkipPixels;
140      GLint skipRows = unpack->SkipRows;
141      GLint rowLength;
142      GLdepth zSpan[MAX_WIDTH];  /* only used when zooming */
143      GLint zoomY0;
144
145      if (unpack->RowLength > 0)
146         rowLength = unpack->RowLength;
147      else
148         rowLength = width;
149
150      /* If we're not using pixel zoom then do all clipping calculations
151       * now.  Otherwise, we'll let the gl_write_zoomed_*_span() functions
152       * handle the clipping.
153       */
154      if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
155         /* horizontal clipping */
156         if (destX < ctx->DrawBuffer->Xmin) {
157            skipPixels += (ctx->DrawBuffer->Xmin - destX);
158            drawWidth  -= (ctx->DrawBuffer->Xmin - destX);
159            destX = ctx->DrawBuffer->Xmin;
160         }
161         if (destX + drawWidth > ctx->DrawBuffer->Xmax)
162            drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax - 1);
163         if (drawWidth <= 0)
164            return GL_TRUE;
165
166         /* vertical clipping */
167         if (destY < ctx->DrawBuffer->Ymin) {
168            skipRows   += (ctx->DrawBuffer->Ymin - destY);
169            drawHeight -= (ctx->DrawBuffer->Ymin - destY);
170            destY = ctx->DrawBuffer->Ymin;
171         }
172         if (destY + drawHeight > ctx->DrawBuffer->Ymax)
173            drawHeight -= (destY + drawHeight - ctx->DrawBuffer->Ymax - 1);
174         if (drawHeight <= 0)
175            return GL_TRUE;
176
177         zoomY0 = 0;  /* not used - silence compiler warning */
178      }
179      else {
180         /* setup array of fragment Z value to pass to zoom function */
181         GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
182         GLint i;
183         assert(drawWidth < MAX_WIDTH);
184         for (i=0; i<drawWidth; i++)
185            zSpan[i] = z;
186
187         /* save Y value of first row */
188         zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
189      }
190
191
192      /*
193       * Ready to draw!
194       * The window region at (destX, destY) of size (drawWidth, drawHeight)
195       * will be written to.
196       * We'll take pixel data from buffer pointed to by "pixels" but we'll
197       * skip "skipRows" rows and skip "skipPixels" pixels/row.
198       */
199
200      if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
201         if (ctx->Visual->RGBAflag) {
202            GLubyte *src = (GLubyte *) pixels
203               + (skipRows * rowLength + skipPixels) * 4;
204            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
205               /* no zooming */
206               GLint row;
207               for (row=0; row<drawHeight; row++) {
208                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
209                                               (void *) src, NULL);
210                  src += rowLength * 4;
211                  destY++;
212               }
213            }
214            else {
215               /* with zooming */
216               GLint row;
217               for (row=0; row<drawHeight; row++) {
218                  gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
219                                            zSpan, (void *) src, zoomY0);
220                  src += rowLength * 4;
221                  destY++;
222               }
223            }
224         }
225         return GL_TRUE;
226      }
227      else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) {
228         if (ctx->Visual->RGBAflag) {
229            GLubyte *src = (GLubyte *) pixels
230               + (skipRows * rowLength + skipPixels) * 3;
231            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
232               GLint row;
233               for (row=0; row<drawHeight; row++) {
234                  (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
235                                              (void *) src, NULL);
236                  src += rowLength * 3;
237                  destY++;
238               }
239            }
240            else {
241               /* with zooming */
242               GLint row;
243               for (row=0; row<drawHeight; row++) {
244                  gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
245                                           zSpan, (void *) src, zoomY0);
246                  src += rowLength * 3;
247                  destY++;
248               }
249            }
250         }
251         return GL_TRUE;
252      }
253      else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) {
254         if (ctx->Visual->RGBAflag) {
255            GLubyte *src = (GLubyte *) pixels
256               + (skipRows * rowLength + skipPixels);
257            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
258               /* no zooming */
259               GLint row;
260               assert(drawWidth < MAX_WIDTH);
261               for (row=0; row<drawHeight; row++) {
262                  GLint i;
263		  for (i=0;i<drawWidth;i++) {
264                     rgb[i][0] = src[i];
265                     rgb[i][1] = src[i];
266                     rgb[i][2] = src[i];
267		  }
268                  (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
269                                              (void *) rgb, NULL);
270                  src += rowLength;
271                  destY++;
272               }
273            }
274            else {
275               /* with zooming */
276               GLint row;
277               assert(drawWidth < MAX_WIDTH);
278               for (row=0; row<drawHeight; row++) {
279                  GLint i;
280		  for (i=0;i<drawWidth;i++) {
281                     rgb[i][0] = src[i];
282                     rgb[i][1] = src[i];
283                     rgb[i][2] = src[i];
284		  }
285                  gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
286                                           zSpan, (void *) rgb, zoomY0);
287                  src += rowLength;
288                  destY++;
289               }
290            }
291         }
292         return GL_TRUE;
293      }
294      else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) {
295         if (ctx->Visual->RGBAflag) {
296            GLubyte *src = (GLubyte *) pixels
297               + (skipRows * rowLength + skipPixels)*2;
298            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
299               /* no zooming */
300               GLint row;
301               assert(drawWidth < MAX_WIDTH);
302               for (row=0; row<drawHeight; row++) {
303                  GLint i;
304                  GLubyte *ptr = src;
305		  for (i=0;i<drawWidth;i++) {
306                     rgba[i][0] = *ptr;
307                     rgba[i][1] = *ptr;
308                     rgba[i][2] = *ptr++;
309                     rgba[i][3] = *ptr++;
310		  }
311                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
312                                               (void *) rgba, NULL);
313                  src += rowLength*2;
314                  destY++;
315               }
316            }
317            else {
318               /* with zooming */
319               GLint row;
320               assert(drawWidth < MAX_WIDTH);
321               for (row=0; row<drawHeight; row++) {
322                  GLubyte *ptr = src;
323                  GLint i;
324		  for (i=0;i<drawWidth;i++) {
325                     rgba[i][0] = *ptr;
326                     rgba[i][1] = *ptr;
327                     rgba[i][2] = *ptr++;
328                     rgba[i][3] = *ptr++;
329		  }
330                  gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
331                                            zSpan, (void *) rgba, zoomY0);
332                  src += rowLength*2;
333                  destY++;
334               }
335            }
336         }
337         return GL_TRUE;
338      }
339      else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
340         GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
341         if (ctx->Visual->RGBAflag) {
342            /* convert CI data to RGBA */
343            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
344               /* no zooming */
345               GLint row;
346               for (row=0; row<drawHeight; row++) {
347                  assert(drawWidth < MAX_WIDTH);
348                  gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
349                  (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
350                                               (const GLubyte (*)[4])rgba,
351					       NULL);
352                  src += rowLength;
353                  destY++;
354               }
355               return GL_TRUE;
356            }
357            else {
358               /* with zooming */
359               GLint row;
360               for (row=0; row<drawHeight; row++) {
361                  assert(drawWidth < MAX_WIDTH);
362                  gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
363                  gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
364                                            zSpan, (void *) rgba, zoomY0);
365                  src += rowLength;
366                  destY++;
367               }
368               return GL_TRUE;
369            }
370         }
371         else {
372            /* write CI data to CI frame buffer */
373            GLint row;
374            if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
375               /* no zooming */
376               for (row=0; row<drawHeight; row++) {
377                  (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
378                                              src, NULL);
379                  src += rowLength;
380                  destY++;
381               }
382               return GL_TRUE;
383            }
384            else {
385               /* with zooming */
386               return GL_FALSE;
387            }
388         }
389      }
390      else {
391         /* can't handle this pixel format and/or data type here */
392         return GL_FALSE;
393      }
394   }
395
396   /* can't do a simple draw, have to use slow path */
397   return GL_FALSE;
398}
399
400
401
402/*
403 * Do glDrawPixels of index pixels.
404 */
405static void
406draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
407                   GLsizei width, GLsizei height,
408                   GLenum type, const GLvoid *pixels )
409{
410   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
411   const GLint desty = y;
412   GLint row, drawWidth;
413   GLdepth zspan[MAX_WIDTH];
414
415   drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
416
417   /* Fragment depth values */
418   if (ctx->Depth.Test || ctx->Fog.Enabled) {
419      GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
420      GLint i;
421      for (i = 0; i < drawWidth; i++) {
422	 zspan[i] = zval;
423      }
424   }
425
426   /*
427    * General solution
428    */
429   for (row = 0; row < height; row++, y++) {
430      GLuint indexes[MAX_WIDTH];
431      const GLvoid *source = _mesa_image_address(&ctx->Unpack,
432                    pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
433      _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes,
434                              type, source, &ctx->Unpack, GL_TRUE);
435      if (zoom) {
436         gl_write_zoomed_index_span(ctx, drawWidth, x, y, zspan, indexes, desty);
437      }
438      else {
439         gl_write_index_span(ctx, drawWidth, x, y, zspan, indexes, GL_BITMAP);
440      }
441   }
442}
443
444
445
446/*
447 * Do glDrawPixels of stencil image.  The image datatype may either
448 * be GLubyte or GLbitmap.
449 */
450static void
451draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
452                     GLsizei width, GLsizei height,
453                     GLenum type, const GLvoid *pixels )
454{
455   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
456   const GLint desty = y;
457   GLint row, drawWidth;
458
459   if (type != GL_BYTE &&
460       type != GL_UNSIGNED_BYTE &&
461       type != GL_SHORT &&
462       type != GL_UNSIGNED_SHORT &&
463       type != GL_INT &&
464       type != GL_UNSIGNED_INT &&
465       type != GL_FLOAT &&
466       type != GL_BITMAP) {
467      gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)");
468      return;
469   }
470
471   drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
472
473   for (row = 0; row < height; row++, y++) {
474      GLstencil values[MAX_WIDTH];
475      GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
476                      ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
477      const GLvoid *source = _mesa_image_address(&ctx->Unpack,
478                    pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
479      _mesa_unpack_index_span(ctx, drawWidth, destType, values,
480                              type, source, &ctx->Unpack, GL_TRUE);
481
482      if (zoom) {
483         gl_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y,
484                                       values, desty );
485      }
486      else {
487         gl_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
488      }
489   }
490}
491
492
493
494/*
495 * Do a glDrawPixels of depth values.
496 */
497static void
498draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
499                   GLsizei width, GLsizei height,
500                   GLenum type, const GLvoid *pixels )
501{
502   const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
503   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
504   const GLint desty = y;
505   GLubyte rgba[MAX_WIDTH][4];
506   GLuint ispan[MAX_WIDTH];
507   GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
508
509   if (type != GL_UNSIGNED_BYTE
510       && type != GL_UNSIGNED_BYTE
511       && type != GL_UNSIGNED_SHORT
512       && type != GL_UNSIGNED_SHORT
513       && type != GL_UNSIGNED_INT
514       && type != GL_UNSIGNED_INT
515       && type != GL_FLOAT) {
516      gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)");
517      return;
518   }
519
520   /* Colors or indexes */
521   if (ctx->Visual->RGBAflag) {
522      GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
523      GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
524      GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
525      GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
526      GLint i;
527      for (i = 0; i < drawWidth; i++) {
528         rgba[i][RCOMP] = r;
529         rgba[i][GCOMP] = g;
530         rgba[i][BCOMP] = b;
531         rgba[i][ACOMP] = a;
532      }
533   }
534   else {
535      GLint i;
536      for (i = 0; i < drawWidth; i++) {
537	 ispan[i] = ctx->Current.RasterIndex;
538      }
539   }
540
541   if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
542       && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
543      /* Special case: directly write 16-bit depth values */
544      GLint row;
545      for (row = 0; row < height; row++, y++) {
546         GLdepth zspan[MAX_WIDTH];
547         const GLushort *zptr = _mesa_image_address(&ctx->Unpack,
548                pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
549         GLint i;
550         for (i = 0; i < width; i++)
551            zspan[i] = zptr[i];
552         gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
553      }
554   }
555   else if (type==GL_UNSIGNED_INT && ctx->Visual->DepthBits == 32
556       && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
557      /* Special case: directly write 32-bit depth values */
558      GLint row;
559      for (row = 0; row < height; row++, y++) {
560         const GLuint *zptr = _mesa_image_address(&ctx->Unpack,
561                pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
562         gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
563      }
564   }
565   else {
566      /* General case */
567      GLint row;
568      for (row = 0; row < height; row++, y++) {
569         GLdepth zspan[MAX_WIDTH];
570         const GLvoid *src = _mesa_image_address(&ctx->Unpack,
571                pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
572         _mesa_unpack_depth_span( ctx, drawWidth, zspan, type, src,
573                                  &ctx->Unpack, GL_TRUE );
574         if (ctx->Visual->RGBAflag) {
575            if (zoom) {
576               gl_write_zoomed_rgba_span(ctx, width, x, y, zspan,
577                                         (const GLubyte (*)[4])rgba, desty);
578            }
579            else {
580               gl_write_rgba_span(ctx, width, x, y, zspan, rgba, GL_BITMAP);
581            }
582         }
583         else {
584            if (zoom) {
585               gl_write_zoomed_index_span(ctx, width, x, y, zspan,
586                                          ispan, GL_BITMAP);
587            }
588            else {
589               gl_write_index_span(ctx, width, x, y, zspan, ispan, GL_BITMAP);
590            }
591         }
592
593      }
594   }
595}
596
597
598/*
599 * Do glDrawPixels of RGBA pixels.
600 */
601static void
602draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
603                  GLsizei width, GLsizei height,
604                  GLenum format, GLenum type, const GLvoid *pixels )
605{
606   const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
607   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
608   const GLint desty = y;
609   GLdepth zspan[MAX_WIDTH];
610   GLboolean quickDraw;
611
612   /* Try an optimized glDrawPixels first */
613   if (simple_DrawPixels(ctx, x, y, width, height, format, type, pixels))
614      return;
615
616   /* Fragment depth values */
617   if (ctx->Depth.Test || ctx->Fog.Enabled) {
618      /* fill in array of z values */
619      GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
620      GLint i;
621      for (i=0;i<width;i++) {
622	 zspan[i] = z;
623      }
624   }
625
626
627   if (ctx->RasterMask == 0 && !zoom
628       && x >= 0 && y >= 0
629       && x + width <= ctx->DrawBuffer->Width
630       && y + height <= ctx->DrawBuffer->Height) {
631      quickDraw = GL_TRUE;
632   }
633   else {
634      quickDraw = GL_FALSE;
635   }
636
637   /*
638    * General solution
639    */
640   {
641      GLubyte rgba[MAX_WIDTH][4];
642      GLint row;
643      if (width > MAX_WIDTH)
644         width = MAX_WIDTH;
645      for (row = 0; row < height; row++, y++) {
646         const GLvoid *source = _mesa_image_address(unpack,
647                  pixels, width, height, format, type, 0, row, 0);
648         _mesa_unpack_ubyte_color_span(ctx, width, GL_RGBA, (void*) rgba,
649                   format, type, source, unpack, GL_TRUE);
650
651         if (ctx->Texture.ReallyEnabled && ctx->Pixel.PixelTextureEnabled) {
652            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], r[MAX_WIDTH], q[MAX_WIDTH];
653            GLuint unit;
654            /* XXX not sure how multitexture is supposed to work here */
655            for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++) {
656               _mesa_pixeltexgen(ctx, width, (const GLubyte (*)[4]) rgba,
657                                 s, t, r, q);
658               gl_texture_pixels(ctx, unit, width, s, t, r, NULL, rgba);
659            }
660         }
661
662         if (quickDraw) {
663            (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
664                                          (CONST GLubyte (*)[]) rgba, NULL);
665         }
666         else if (zoom) {
667            gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
668				       (CONST GLubyte (*)[]) rgba, desty );
669         }
670         else {
671            gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
672         }
673      }
674   }
675}
676
677
678
679/*
680 * Execute glDrawPixels
681 */
682void
683_mesa_DrawPixels( GLsizei width, GLsizei height,
684                  GLenum format, GLenum type, const GLvoid *pixels )
685{
686   GET_CURRENT_CONTEXT(ctx);
687   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels");
688
689   if (ctx->RenderMode==GL_RENDER) {
690      GLint x, y;
691      if (!pixels || !ctx->Current.RasterPosValid) {
692	 return;
693      }
694
695      x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
696      y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
697
698      ctx->OcclusionResult = GL_TRUE;
699
700      /* see if device driver can do the drawpix */
701      if (ctx->Driver.DrawPixels
702          && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
703                                       &ctx->Unpack, pixels)) {
704         return;
705      }
706
707      switch (format) {
708	 case GL_STENCIL_INDEX:
709	    draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
710	    break;
711	 case GL_DEPTH_COMPONENT:
712	    draw_depth_pixels( ctx, x, y, width, height, type, pixels );
713	    break;
714	 case GL_COLOR_INDEX:
715            if (ctx->Visual->RGBAflag)
716               draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
717            else
718               draw_index_pixels(ctx, x, y, width, height, type, pixels);
719	    break;
720	 case GL_RED:
721	 case GL_GREEN:
722	 case GL_BLUE:
723	 case GL_ALPHA:
724	 case GL_LUMINANCE:
725	 case GL_LUMINANCE_ALPHA:
726	 case GL_RGB:
727         case GL_BGR:
728	 case GL_RGBA:
729	 case GL_BGRA:
730	 case GL_ABGR_EXT:
731            draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels);
732	    break;
733	 default:
734	    gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" );
735            return;
736      }
737   }
738   else if (ctx->RenderMode==GL_FEEDBACK) {
739      if (ctx->Current.RasterPosValid) {
740         GLfloat color[4];
741	 GLfloat texcoord[4], invq;
742	 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor);
743         invq = 1.0F / ctx->Current.Texcoord[0][3];
744         texcoord[0] = ctx->Current.Texcoord[0][0] * invq;
745         texcoord[1] = ctx->Current.Texcoord[0][1] * invq;
746         texcoord[2] = ctx->Current.Texcoord[0][2] * invq;
747         texcoord[3] = ctx->Current.Texcoord[0][3];
748         FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
749         gl_feedback_vertex( ctx,
750                             ctx->Current.RasterPos,
751                             color, ctx->Current.Index, texcoord );
752      }
753   }
754   else if (ctx->RenderMode==GL_SELECT) {
755      if (ctx->Current.RasterPosValid) {
756         gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
757      }
758   }
759}
760
761