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