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