s_drawpix.c revision 4bcda856982cc428cba555367001f4db721a9aaf
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.1
4 *
5 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26#include "main/glheader.h"
27#include "main/bufferobj.h"
28#include "main/condrender.h"
29#include "main/context.h"
30#include "main/image.h"
31#include "main/imports.h"
32#include "main/macros.h"
33#include "main/pack.h"
34#include "main/pbo.h"
35#include "main/pixeltransfer.h"
36#include "main/state.h"
37
38#include "s_context.h"
39#include "s_span.h"
40#include "s_stencil.h"
41#include "s_zoom.h"
42
43
44
45/**
46 * Try to do a fast and simple RGB(a) glDrawPixels.
47 * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
48 */
49static GLboolean
50fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y,
51                      GLsizei width, GLsizei height,
52                      GLenum format, GLenum type,
53                      const struct gl_pixelstore_attrib *userUnpack,
54                      const GLvoid *pixels)
55{
56   const GLint imgX = x, imgY = y;
57   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
58   GLenum rbType;
59   SWcontext *swrast = SWRAST_CONTEXT(ctx);
60   SWspan span;
61   GLboolean simpleZoom;
62   GLint yStep;  /* +1 or -1 */
63   struct gl_pixelstore_attrib unpack;
64   GLint destX, destY, drawWidth, drawHeight; /* post clipping */
65
66   if (!rb)
67      return GL_TRUE; /* no-op */
68
69   rbType = rb->DataType;
70
71   if ((swrast->_RasterMask & ~CLIP_BIT) ||
72       ctx->Texture._EnabledCoordUnits ||
73       userUnpack->SwapBytes ||
74       ctx->_ImageTransferState) {
75      /* can't handle any of those conditions */
76      return GL_FALSE;
77   }
78
79   INIT_SPAN(span, GL_BITMAP);
80   span.arrayMask = SPAN_RGBA;
81   span.arrayAttribs = FRAG_BIT_COL0;
82   _swrast_span_default_attribs(ctx, &span);
83
84   /* copy input params since clipping may change them */
85   unpack = *userUnpack;
86   destX = x;
87   destY = y;
88   drawWidth = width;
89   drawHeight = height;
90
91   /* check for simple zooming and clipping */
92   if (ctx->Pixel.ZoomX == 1.0F &&
93       (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F)) {
94      if (!_mesa_clip_drawpixels(ctx, &destX, &destY,
95                                 &drawWidth, &drawHeight, &unpack)) {
96         /* image was completely clipped: no-op, all done */
97         return GL_TRUE;
98      }
99      simpleZoom = GL_TRUE;
100      yStep = (GLint) ctx->Pixel.ZoomY;
101      ASSERT(yStep == 1 || yStep == -1);
102   }
103   else {
104      /* non-simple zooming */
105      simpleZoom = GL_FALSE;
106      yStep = 1;
107      if (unpack.RowLength == 0)
108         unpack.RowLength = width;
109   }
110
111   /*
112    * Ready to draw!
113    */
114
115   if (format == GL_RGBA && type == rbType) {
116      const GLubyte *src
117         = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
118                                                   height, format, type, 0, 0);
119      const GLint srcStride = _mesa_image_row_stride(&unpack, width,
120                                                     format, type);
121      if (simpleZoom) {
122         GLint row;
123         for (row = 0; row < drawHeight; row++) {
124            rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL);
125            src += srcStride;
126            destY += yStep;
127         }
128      }
129      else {
130         /* with zooming */
131         GLint row;
132         for (row = 0; row < drawHeight; row++) {
133            span.x = destX;
134            span.y = destY + row;
135            span.end = drawWidth;
136            span.array->ChanType = rbType;
137            _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src);
138            src += srcStride;
139         }
140         span.array->ChanType = CHAN_TYPE;
141      }
142      return GL_TRUE;
143   }
144
145   if (format == GL_RGB && type == rbType) {
146      const GLubyte *src
147         = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
148                                                   height, format, type, 0, 0);
149      const GLint srcStride = _mesa_image_row_stride(&unpack, width,
150                                                     format, type);
151      if (simpleZoom) {
152         GLint row;
153         for (row = 0; row < drawHeight; row++) {
154            rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL);
155            src += srcStride;
156            destY += yStep;
157         }
158      }
159      else {
160         /* with zooming */
161         GLint row;
162         for (row = 0; row < drawHeight; row++) {
163            span.x = destX;
164            span.y = destY;
165            span.end = drawWidth;
166            span.array->ChanType = rbType;
167            _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src);
168            src += srcStride;
169            destY++;
170         }
171         span.array->ChanType = CHAN_TYPE;
172      }
173      return GL_TRUE;
174   }
175
176   /* Remaining cases haven't been tested with alignment != 1 */
177   if (userUnpack->Alignment != 1)
178      return GL_FALSE;
179
180   if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) {
181      const GLchan *src = (const GLchan *) pixels
182         + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels);
183      if (simpleZoom) {
184         /* no zooming */
185         GLint row;
186         ASSERT(drawWidth <= MAX_WIDTH);
187         for (row = 0; row < drawHeight; row++) {
188            GLchan rgb[MAX_WIDTH][3];
189            GLint i;
190            for (i = 0;i<drawWidth;i++) {
191               rgb[i][0] = src[i];
192               rgb[i][1] = src[i];
193               rgb[i][2] = src[i];
194            }
195            rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL);
196            src += unpack.RowLength;
197            destY += yStep;
198         }
199      }
200      else {
201         /* with zooming */
202         GLint row;
203         ASSERT(drawWidth <= MAX_WIDTH);
204         for (row = 0; row < drawHeight; row++) {
205            GLchan rgb[MAX_WIDTH][3];
206            GLint i;
207            for (i = 0;i<drawWidth;i++) {
208               rgb[i][0] = src[i];
209               rgb[i][1] = src[i];
210               rgb[i][2] = src[i];
211            }
212            span.x = destX;
213            span.y = destY;
214            span.end = drawWidth;
215            _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, rgb);
216            src += unpack.RowLength;
217            destY++;
218         }
219      }
220      return GL_TRUE;
221   }
222
223   if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE && rbType == CHAN_TYPE) {
224      const GLchan *src = (const GLchan *) pixels
225         + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels)*2;
226      if (simpleZoom) {
227         GLint row;
228         ASSERT(drawWidth <= MAX_WIDTH);
229         for (row = 0; row < drawHeight; row++) {
230            GLint i;
231            const GLchan *ptr = src;
232            for (i = 0;i<drawWidth;i++) {
233               span.array->rgba[i][0] = *ptr;
234               span.array->rgba[i][1] = *ptr;
235               span.array->rgba[i][2] = *ptr++;
236               span.array->rgba[i][3] = *ptr++;
237            }
238            rb->PutRow(ctx, rb, drawWidth, destX, destY,
239                       span.array->rgba, NULL);
240            src += unpack.RowLength*2;
241            destY += yStep;
242         }
243      }
244      else {
245         /* with zooming */
246         GLint row;
247         ASSERT(drawWidth <= MAX_WIDTH);
248         for (row = 0; row < drawHeight; row++) {
249            const GLchan *ptr = src;
250            GLint i;
251            for (i = 0;i<drawWidth;i++) {
252               span.array->rgba[i][0] = *ptr;
253               span.array->rgba[i][1] = *ptr;
254               span.array->rgba[i][2] = *ptr++;
255               span.array->rgba[i][3] = *ptr++;
256            }
257            span.x = destX;
258            span.y = destY;
259            span.end = drawWidth;
260            _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
261                                           span.array->rgba);
262            src += unpack.RowLength*2;
263            destY++;
264         }
265      }
266      return GL_TRUE;
267   }
268
269   if (format == GL_COLOR_INDEX && type == GL_UNSIGNED_BYTE) {
270      const GLubyte *src = (const GLubyte *) pixels
271         + unpack.SkipRows * unpack.RowLength + unpack.SkipPixels;
272      if (rbType == GL_UNSIGNED_BYTE) {
273         /* convert ubyte/CI data to ubyte/RGBA */
274         if (simpleZoom) {
275            GLint row;
276            for (row = 0; row < drawHeight; row++) {
277               ASSERT(drawWidth <= MAX_WIDTH);
278               _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
279                                      span.array->rgba8);
280               rb->PutRow(ctx, rb, drawWidth, destX, destY,
281                          span.array->rgba8, NULL);
282               src += unpack.RowLength;
283               destY += yStep;
284            }
285         }
286         else {
287            /* ubyte/CI to ubyte/RGBA with zooming */
288            GLint row;
289            for (row = 0; row < drawHeight; row++) {
290               ASSERT(drawWidth <= MAX_WIDTH);
291               _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
292                                      span.array->rgba8);
293               span.x = destX;
294               span.y = destY;
295               span.end = drawWidth;
296               _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
297                                              span.array->rgba8);
298               src += unpack.RowLength;
299               destY++;
300            }
301         }
302         return GL_TRUE;
303      }
304   }
305
306   /* can't handle this pixel format and/or data type */
307   return GL_FALSE;
308}
309
310
311
312/*
313 * Draw stencil image.
314 */
315static void
316draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y,
317                     GLsizei width, GLsizei height,
318                     GLenum type,
319                     const struct gl_pixelstore_attrib *unpack,
320                     const GLvoid *pixels )
321{
322   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
323   GLint skipPixels;
324
325   /* if width > MAX_WIDTH, have to process image in chunks */
326   skipPixels = 0;
327   while (skipPixels < width) {
328      const GLint spanX = x + skipPixels;
329      const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
330      GLint row;
331      for (row = 0; row < height; row++) {
332         const GLint spanY = y + row;
333         GLstencil values[MAX_WIDTH];
334         GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
335                         ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
336         const GLvoid *source = _mesa_image_address2d(unpack, pixels,
337                                                      width, height,
338                                                      GL_STENCIL_INDEX, type,
339                                                      row, skipPixels);
340         _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
341                                   type, source, unpack,
342                                   ctx->_ImageTransferState);
343         if (zoom) {
344            _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
345                                              spanX, spanY, values);
346         }
347         else {
348            _swrast_write_stencil_span(ctx, spanWidth, spanX, spanY, values);
349         }
350      }
351      skipPixels += spanWidth;
352   }
353}
354
355
356/*
357 * Draw depth image.
358 */
359static void
360draw_depth_pixels( struct gl_context *ctx, GLint x, GLint y,
361                   GLsizei width, GLsizei height,
362                   GLenum type,
363                   const struct gl_pixelstore_attrib *unpack,
364                   const GLvoid *pixels )
365{
366   const GLboolean scaleOrBias
367      = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
368   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
369   SWspan span;
370
371   INIT_SPAN(span, GL_BITMAP);
372   span.arrayMask = SPAN_Z;
373   _swrast_span_default_attribs(ctx, &span);
374
375   if (type == GL_UNSIGNED_SHORT
376       && ctx->DrawBuffer->Visual.depthBits == 16
377       && !scaleOrBias
378       && !zoom
379       && width <= MAX_WIDTH
380       && !unpack->SwapBytes) {
381      /* Special case: directly write 16-bit depth values */
382      GLint row;
383      for (row = 0; row < height; row++) {
384         const GLushort *zSrc = (const GLushort *)
385            _mesa_image_address2d(unpack, pixels, width, height,
386                                  GL_DEPTH_COMPONENT, type, row, 0);
387         GLint i;
388         for (i = 0; i < width; i++)
389            span.array->z[i] = zSrc[i];
390         span.x = x;
391         span.y = y + row;
392         span.end = width;
393         _swrast_write_rgba_span(ctx, &span);
394      }
395   }
396   else if (type == GL_UNSIGNED_INT
397            && !scaleOrBias
398            && !zoom
399            && width <= MAX_WIDTH
400            && !unpack->SwapBytes) {
401      /* Special case: shift 32-bit values down to Visual.depthBits */
402      const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits;
403      GLint row;
404      for (row = 0; row < height; row++) {
405         const GLuint *zSrc = (const GLuint *)
406            _mesa_image_address2d(unpack, pixels, width, height,
407                                  GL_DEPTH_COMPONENT, type, row, 0);
408         if (shift == 0) {
409            memcpy(span.array->z, zSrc, width * sizeof(GLuint));
410         }
411         else {
412            GLint col;
413            for (col = 0; col < width; col++)
414               span.array->z[col] = zSrc[col] >> shift;
415         }
416         span.x = x;
417         span.y = y + row;
418         span.end = width;
419         _swrast_write_rgba_span(ctx, &span);
420      }
421   }
422   else {
423      /* General case */
424      const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
425      GLint skipPixels = 0;
426
427      /* in case width > MAX_WIDTH do the copy in chunks */
428      while (skipPixels < width) {
429         const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
430         GLint row;
431         ASSERT(span.end <= MAX_WIDTH);
432         for (row = 0; row < height; row++) {
433            const GLvoid *zSrc = _mesa_image_address2d(unpack,
434                                                      pixels, width, height,
435                                                      GL_DEPTH_COMPONENT, type,
436                                                      row, skipPixels);
437
438            /* Set these for each row since the _swrast_write_* function may
439             * change them while clipping.
440             */
441            span.x = x + skipPixels;
442            span.y = y + row;
443            span.end = spanWidth;
444
445            _mesa_unpack_depth_span(ctx, spanWidth,
446                                    GL_UNSIGNED_INT, span.array->z, depthMax,
447                                    type, zSrc, unpack);
448            if (zoom) {
449               _swrast_write_zoomed_depth_span(ctx, x, y, &span);
450            }
451            else {
452               _swrast_write_rgba_span(ctx, &span);
453            }
454         }
455         skipPixels += spanWidth;
456      }
457   }
458}
459
460
461
462/**
463 * Draw RGBA image.
464 */
465static void
466draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y,
467                  GLsizei width, GLsizei height,
468                  GLenum format, GLenum type,
469                  const struct gl_pixelstore_attrib *unpack,
470                  const GLvoid *pixels )
471{
472   const GLint imgX = x, imgY = y;
473   const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
474   GLfloat *convImage = NULL;
475   GLbitfield transferOps = ctx->_ImageTransferState;
476   SWspan span;
477
478   /* Try an optimized glDrawPixels first */
479   if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type,
480                             unpack, pixels)) {
481      return;
482   }
483
484   INIT_SPAN(span, GL_BITMAP);
485   _swrast_span_default_attribs(ctx, &span);
486   span.arrayMask = SPAN_RGBA;
487   span.arrayAttribs = FRAG_BIT_COL0; /* we're fill in COL0 attrib values */
488
489   if (ctx->DrawBuffer->_NumColorDrawBuffers > 0 &&
490       ctx->DrawBuffer->_ColorDrawBuffers[0]->DataType != GL_FLOAT &&
491       ctx->Color.ClampFragmentColor != GL_FALSE) {
492      /* need to clamp colors before applying fragment ops */
493      transferOps |= IMAGE_CLAMP_BIT;
494   }
495
496   /*
497    * General solution
498    */
499   {
500      const GLbitfield interpMask = span.interpMask;
501      const GLbitfield arrayMask = span.arrayMask;
502      const GLint srcStride
503         = _mesa_image_row_stride(unpack, width, format, type);
504      GLint skipPixels = 0;
505      /* use span array for temp color storage */
506      GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0];
507
508      /* if the span is wider than MAX_WIDTH we have to do it in chunks */
509      while (skipPixels < width) {
510         const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
511         const GLubyte *source
512            = (const GLubyte *) _mesa_image_address2d(unpack, pixels,
513                                                      width, height, format,
514                                                      type, 0, skipPixels);
515         GLint row;
516
517         for (row = 0; row < height; row++) {
518            /* get image row as float/RGBA */
519            _mesa_unpack_color_span_float(ctx, spanWidth, GL_RGBA, rgba,
520                                     format, type, source, unpack,
521                                     transferOps);
522	    /* Set these for each row since the _swrast_write_* functions
523	     * may change them while clipping/rendering.
524	     */
525	    span.array->ChanType = GL_FLOAT;
526	    span.x = x + skipPixels;
527	    span.y = y + row;
528	    span.end = spanWidth;
529	    span.arrayMask = arrayMask;
530	    span.interpMask = interpMask;
531	    if (zoom) {
532	       _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
533	    }
534	    else {
535	       _swrast_write_rgba_span(ctx, &span);
536	    }
537
538            source += srcStride;
539         } /* for row */
540
541         skipPixels += spanWidth;
542      } /* while skipPixels < width */
543
544      /* XXX this is ugly/temporary, to undo above change */
545      span.array->ChanType = CHAN_TYPE;
546   }
547
548   if (convImage) {
549      free(convImage);
550   }
551}
552
553
554/**
555 * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
556 * The only per-pixel operations that apply are depth scale/bias,
557 * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
558 * and pixel zoom.
559 * Also, only the depth buffer and stencil buffers are touched, not the
560 * color buffer(s).
561 */
562static void
563draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
564                          GLsizei width, GLsizei height, GLenum type,
565                          const struct gl_pixelstore_attrib *unpack,
566                          const GLvoid *pixels)
567{
568   const GLint imgX = x, imgY = y;
569   const GLboolean scaleOrBias
570      = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
571   const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
572   const GLuint stencilMask = ctx->Stencil.WriteMask[0];
573   const GLuint stencilType = (STENCIL_BITS == 8) ?
574      GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
575   const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
576   struct gl_renderbuffer *depthRb, *stencilRb;
577   struct gl_pixelstore_attrib clippedUnpack = *unpack;
578
579   if (!zoom) {
580      if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
581                                 &clippedUnpack)) {
582         /* totally clipped */
583         return;
584      }
585   }
586
587   depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
588   stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
589   ASSERT(depthRb);
590   ASSERT(stencilRb);
591
592   if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
593       depthRb->Format == MESA_FORMAT_Z24_S8 &&
594       type == GL_UNSIGNED_INT_24_8 &&
595       depthRb == stencilRb &&
596       !scaleOrBias &&
597       !zoom &&
598       ctx->Depth.Mask &&
599       (stencilMask & 0xff) == 0xff) {
600      /* This is the ideal case.
601       * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer.
602       * Plus, no pixel transfer ops, zooming, or masking needed.
603       */
604      GLint i;
605      for (i = 0; i < height; i++) {
606         const GLuint *src = (const GLuint *)
607            _mesa_image_address2d(&clippedUnpack, pixels, width, height,
608                                  GL_DEPTH_STENCIL_EXT, type, i, 0);
609         depthRb->PutRow(ctx, depthRb, width, x, y + i, src, NULL);
610      }
611   }
612   else {
613      /* sub-optimal cases:
614       * Separate depth/stencil buffers, or pixel transfer ops required.
615       */
616      /* XXX need to handle very wide images (skippixels) */
617      GLint i;
618
619      depthRb = ctx->DrawBuffer->_DepthBuffer;
620      stencilRb = ctx->DrawBuffer->_StencilBuffer;
621
622      for (i = 0; i < height; i++) {
623         const GLuint *depthStencilSrc = (const GLuint *)
624            _mesa_image_address2d(&clippedUnpack, pixels, width, height,
625                                  GL_DEPTH_STENCIL_EXT, type, i, 0);
626
627         if (ctx->Depth.Mask) {
628            if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24) {
629               /* fast path 24-bit zbuffer */
630               GLuint zValues[MAX_WIDTH];
631               GLint j;
632               ASSERT(depthRb->DataType == GL_UNSIGNED_INT);
633               for (j = 0; j < width; j++) {
634                  zValues[j] = depthStencilSrc[j] >> 8;
635               }
636               if (zoom)
637                  _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
638                                              x, y + i, zValues);
639               else
640                  depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
641            }
642            else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16) {
643               /* fast path 16-bit zbuffer */
644               GLushort zValues[MAX_WIDTH];
645               GLint j;
646               ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT);
647               for (j = 0; j < width; j++) {
648                  zValues[j] = depthStencilSrc[j] >> 16;
649               }
650               if (zoom)
651                  _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
652                                              x, y + i, zValues);
653               else
654                  depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
655            }
656            else {
657               /* general case */
658               GLuint zValues[MAX_WIDTH];  /* 16 or 32-bit Z value storage */
659               _mesa_unpack_depth_span(ctx, width,
660                                       depthRb->DataType, zValues, depthMax,
661                                       type, depthStencilSrc, &clippedUnpack);
662               if (zoom) {
663                  _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
664                                              y + i, zValues);
665               }
666               else {
667                  depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
668               }
669            }
670         }
671
672         if (stencilMask != 0x0) {
673            GLstencil stencilValues[MAX_WIDTH];
674            /* get stencil values, with shift/offset/mapping */
675            _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues,
676                                      type, depthStencilSrc, &clippedUnpack,
677                                      ctx->_ImageTransferState);
678            if (zoom)
679               _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width,
680                                                  x, y + i, stencilValues);
681            else
682               _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues);
683         }
684      }
685   }
686}
687
688
689/**
690 * Execute software-based glDrawPixels.
691 * By time we get here, all error checking will have been done.
692 */
693void
694_swrast_DrawPixels( struct gl_context *ctx,
695		    GLint x, GLint y,
696		    GLsizei width, GLsizei height,
697		    GLenum format, GLenum type,
698		    const struct gl_pixelstore_attrib *unpack,
699		    const GLvoid *pixels )
700{
701   SWcontext *swrast = SWRAST_CONTEXT(ctx);
702   GLboolean save_vp_override = ctx->VertexProgram._Overriden;
703
704   if (!_mesa_check_conditional_render(ctx))
705      return; /* don't draw */
706
707   /* We are creating fragments directly, without going through vertex
708    * programs.
709    *
710    * This override flag tells the fragment processing code that its input
711    * comes from a non-standard source, and it may therefore not rely on
712    * optimizations that assume e.g. constant color if there is no color
713    * vertex array.
714    */
715   _mesa_set_vp_override(ctx, GL_TRUE);
716
717   swrast_render_start(ctx);
718
719   if (ctx->NewState)
720      _mesa_update_state(ctx);
721
722   if (swrast->NewState)
723      _swrast_validate_derived( ctx );
724
725   pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
726   if (!pixels) {
727      swrast_render_finish(ctx);
728      _mesa_set_vp_override(ctx, save_vp_override);
729      return;
730   }
731
732   /*
733    * By time we get here, all error checking should have been done.
734    */
735   switch (format) {
736   case GL_STENCIL_INDEX:
737      draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
738      break;
739   case GL_DEPTH_COMPONENT:
740      draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
741      break;
742   case GL_DEPTH_STENCIL_EXT:
743      draw_depth_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels);
744      break;
745   default:
746      /* all other formats should be color formats */
747      draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
748   }
749
750   swrast_render_finish(ctx);
751   _mesa_set_vp_override(ctx, save_vp_override);
752
753   _mesa_unmap_pbo_source(ctx, unpack);
754}
755