OSDN Git Service

Merge branch 'mesa_7_7_branch'
[android-x86/external-mesa.git] / src / mesa / swrast / s_drawpix.c
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/convolve.h"
31 #include "main/image.h"
32 #include "main/macros.h"
33 #include "main/imports.h"
34 #include "main/pixel.h"
35 #include "main/state.h"
36
37 #include "s_context.h"
38 #include "s_span.h"
39 #include "s_stencil.h"
40 #include "s_zoom.h"
41
42
43
44 /**
45  * Try to do a fast and simple RGB(a) glDrawPixels.
46  * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
47  */
48 static GLboolean
49 fast_draw_rgba_pixels(GLcontext *ctx, GLint x, GLint y,
50                       GLsizei width, GLsizei height,
51                       GLenum format, GLenum type,
52                       const struct gl_pixelstore_attrib *userUnpack,
53                       const GLvoid *pixels)
54 {
55    const GLint imgX = x, imgY = y;
56    struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
57    GLenum rbType;
58    SWcontext *swrast = SWRAST_CONTEXT(ctx);
59    SWspan span;
60    GLboolean simpleZoom;
61    GLint yStep;  /* +1 or -1 */
62    struct gl_pixelstore_attrib unpack;
63    GLint destX, destY, drawWidth, drawHeight; /* post clipping */
64
65    if (!rb)
66       return GL_TRUE; /* no-op */
67
68    rbType = rb->DataType;
69
70    if ((swrast->_RasterMask & ~CLIP_BIT) ||
71        ctx->Texture._EnabledCoordUnits ||
72        userUnpack->SwapBytes ||
73        ctx->_ImageTransferState) {
74       /* can't handle any of those conditions */
75       return GL_FALSE;
76    }
77
78    INIT_SPAN(span, GL_BITMAP);
79    span.arrayMask = SPAN_RGBA;
80    span.arrayAttribs = FRAG_BIT_COL0;
81    _swrast_span_default_attribs(ctx, &span);
82
83    /* copy input params since clipping may change them */
84    unpack = *userUnpack;
85    destX = x;
86    destY = y;
87    drawWidth = width;
88    drawHeight = height;
89
90    /* check for simple zooming and clipping */
91    if (ctx->Pixel.ZoomX == 1.0F &&
92        (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F)) {
93       if (!_mesa_clip_drawpixels(ctx, &destX, &destY,
94                                  &drawWidth, &drawHeight, &unpack)) {
95          /* image was completely clipped: no-op, all done */
96          return GL_TRUE;
97       }
98       simpleZoom = GL_TRUE;
99       yStep = (GLint) ctx->Pixel.ZoomY;
100       ASSERT(yStep == 1 || yStep == -1);
101    }
102    else {
103       /* non-simple zooming */
104       simpleZoom = GL_FALSE;
105       yStep = 1;
106       if (unpack.RowLength == 0)
107          unpack.RowLength = width;
108    }
109
110    /*
111     * Ready to draw!
112     */
113
114    if (format == GL_RGBA && type == rbType) {
115       const GLubyte *src
116          = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
117                                                    height, format, type, 0, 0);
118       const GLint srcStride = _mesa_image_row_stride(&unpack, width,
119                                                      format, type);
120       if (simpleZoom) {
121          GLint row;
122          for (row = 0; row < drawHeight; row++) {
123             rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL);
124             src += srcStride;
125             destY += yStep;
126          }
127       }
128       else {
129          /* with zooming */
130          GLint row;
131          for (row = 0; row < drawHeight; row++) {
132             span.x = destX;
133             span.y = destY + row;
134             span.end = drawWidth;
135             span.array->ChanType = rbType;
136             _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src);
137             src += srcStride;
138          }
139          span.array->ChanType = CHAN_TYPE;
140       }
141       return GL_TRUE;
142    }
143
144    if (format == GL_RGB && type == rbType) {
145       const GLubyte *src
146          = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width,
147                                                    height, format, type, 0, 0);
148       const GLint srcStride = _mesa_image_row_stride(&unpack, width,
149                                                      format, type);
150       if (simpleZoom) {
151          GLint row;
152          for (row = 0; row < drawHeight; row++) {
153             rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL);
154             src += srcStride;
155             destY += yStep;
156          }
157       }
158       else {
159          /* with zooming */
160          GLint row;
161          for (row = 0; row < drawHeight; row++) {
162             span.x = destX;
163             span.y = destY;
164             span.end = drawWidth;
165             span.array->ChanType = rbType;
166             _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src);
167             src += srcStride;
168             destY++;
169          }
170          span.array->ChanType = CHAN_TYPE;
171       }
172       return GL_TRUE;
173    }
174
175    /* Remaining cases haven't been tested with alignment != 1 */
176    if (userUnpack->Alignment != 1)
177       return GL_FALSE;
178
179    if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) {
180       const GLchan *src = (const GLchan *) pixels
181          + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels);
182       if (simpleZoom) {
183          /* no zooming */
184          GLint row;
185          ASSERT(drawWidth <= MAX_WIDTH);
186          for (row = 0; row < drawHeight; row++) {
187             GLchan rgb[MAX_WIDTH][3];
188             GLint i;
189             for (i = 0;i<drawWidth;i++) {
190                rgb[i][0] = src[i];
191                rgb[i][1] = src[i];
192                rgb[i][2] = src[i];
193             }
194             rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL);
195             src += unpack.RowLength;
196             destY += yStep;
197          }
198       }
199       else {
200          /* with zooming */
201          GLint row;
202          ASSERT(drawWidth <= MAX_WIDTH);
203          for (row = 0; row < drawHeight; row++) {
204             GLchan rgb[MAX_WIDTH][3];
205             GLint i;
206             for (i = 0;i<drawWidth;i++) {
207                rgb[i][0] = src[i];
208                rgb[i][1] = src[i];
209                rgb[i][2] = src[i];
210             }
211             span.x = destX;
212             span.y = destY;
213             span.end = drawWidth;
214             _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, rgb);
215             src += unpack.RowLength;
216             destY++;
217          }
218       }
219       return GL_TRUE;
220    }
221
222    if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE && rbType == CHAN_TYPE) {
223       const GLchan *src = (const GLchan *) pixels
224          + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels)*2;
225       if (simpleZoom) {
226          GLint row;
227          ASSERT(drawWidth <= MAX_WIDTH);
228          for (row = 0; row < drawHeight; row++) {
229             GLint i;
230             const GLchan *ptr = src;
231             for (i = 0;i<drawWidth;i++) {
232                span.array->rgba[i][0] = *ptr;
233                span.array->rgba[i][1] = *ptr;
234                span.array->rgba[i][2] = *ptr++;
235                span.array->rgba[i][3] = *ptr++;
236             }
237             rb->PutRow(ctx, rb, drawWidth, destX, destY,
238                        span.array->rgba, NULL);
239             src += unpack.RowLength*2;
240             destY += yStep;
241          }
242       }
243       else {
244          /* with zooming */
245          GLint row;
246          ASSERT(drawWidth <= MAX_WIDTH);
247          for (row = 0; row < drawHeight; row++) {
248             const GLchan *ptr = src;
249             GLint i;
250             for (i = 0;i<drawWidth;i++) {
251                span.array->rgba[i][0] = *ptr;
252                span.array->rgba[i][1] = *ptr;
253                span.array->rgba[i][2] = *ptr++;
254                span.array->rgba[i][3] = *ptr++;
255             }
256             span.x = destX;
257             span.y = destY;
258             span.end = drawWidth;
259             _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
260                                            span.array->rgba);
261             src += unpack.RowLength*2;
262             destY++;
263          }
264       }
265       return GL_TRUE;
266    }
267
268    if (format == GL_COLOR_INDEX && type == GL_UNSIGNED_BYTE) {
269       const GLubyte *src = (const GLubyte *) pixels
270          + unpack.SkipRows * unpack.RowLength + unpack.SkipPixels;
271       if (ctx->Visual.rgbMode && rbType == GL_UNSIGNED_BYTE) {
272          /* convert ubyte/CI data to ubyte/RGBA */
273          if (simpleZoom) {
274             GLint row;
275             for (row = 0; row < drawHeight; row++) {
276                ASSERT(drawWidth <= MAX_WIDTH);
277                _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
278                                       span.array->rgba8);
279                rb->PutRow(ctx, rb, drawWidth, destX, destY,
280                           span.array->rgba8, NULL);
281                src += unpack.RowLength;
282                destY += yStep;
283             }
284          }
285          else {
286             /* ubyte/CI to ubyte/RGBA with zooming */
287             GLint row;
288             for (row = 0; row < drawHeight; row++) {
289                ASSERT(drawWidth <= MAX_WIDTH);
290                _mesa_map_ci8_to_rgba8(ctx, drawWidth, src,
291                                       span.array->rgba8);
292                span.x = destX;
293                span.y = destY;
294                span.end = drawWidth;
295                _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span,
296                                               span.array->rgba8);
297                src += unpack.RowLength;
298                destY++;
299             }
300          }
301          return GL_TRUE;
302       }
303       else if (!ctx->Visual.rgbMode && rbType == GL_UNSIGNED_INT) {
304          /* write CI data to CI frame buffer */
305          GLint row;
306          if (simpleZoom) {
307             for (row = 0; row < drawHeight; row++) {
308                GLuint index32[MAX_WIDTH];
309                GLint col;
310                for (col = 0; col < drawWidth; col++)
311                   index32[col] = src[col];
312                rb->PutRow(ctx, rb, drawWidth, destX, destY, index32, NULL);
313                src += unpack.RowLength;
314                destY += yStep;
315             }
316             return GL_TRUE;
317          }
318       }
319    }
320
321    /* can't handle this pixel format and/or data type */
322    return GL_FALSE;
323 }
324
325
326
327 /*
328  * Draw color index image.
329  */
330 static void
331 draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
332                    GLsizei width, GLsizei height,
333                    GLenum type,
334                    const struct gl_pixelstore_attrib *unpack,
335                    const GLvoid *pixels )
336 {
337    const GLint imgX = x, imgY = y;
338    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
339    GLint row, skipPixels;
340    SWspan span;
341
342    INIT_SPAN(span, GL_BITMAP);
343    span.arrayMask = SPAN_INDEX;
344    _swrast_span_default_attribs(ctx, &span);
345
346    /*
347     * General solution
348     */
349    skipPixels = 0;
350    while (skipPixels < width) {
351       const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
352       ASSERT(spanWidth <= MAX_WIDTH);
353       for (row = 0; row < height; row++) {
354          const GLvoid *source = _mesa_image_address2d(unpack, pixels,
355                                                       width, height,
356                                                       GL_COLOR_INDEX, type,
357                                                       row, skipPixels);
358          _mesa_unpack_index_span(ctx, spanWidth, GL_UNSIGNED_INT,
359                                  span.array->index, type, source, unpack,
360                                  ctx->_ImageTransferState);
361
362          /* These may get changed during writing/clipping */
363          span.x = x + skipPixels;
364          span.y = y + row;
365          span.end = spanWidth;
366          
367          if (zoom)
368             _swrast_write_zoomed_index_span(ctx, imgX, imgY, &span);
369          else
370             _swrast_write_index_span(ctx, &span);
371       }
372       skipPixels += spanWidth;
373    }
374 }
375
376
377
378 /*
379  * Draw stencil image.
380  */
381 static void
382 draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
383                      GLsizei width, GLsizei height,
384                      GLenum type,
385                      const struct gl_pixelstore_attrib *unpack,
386                      const GLvoid *pixels )
387 {
388    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
389    GLint skipPixels;
390
391    /* if width > MAX_WIDTH, have to process image in chunks */
392    skipPixels = 0;
393    while (skipPixels < width) {
394       const GLint spanX = x + skipPixels;
395       const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
396       GLint row;
397       for (row = 0; row < height; row++) {
398          const GLint spanY = y + row;
399          GLstencil values[MAX_WIDTH];
400          GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
401                          ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
402          const GLvoid *source = _mesa_image_address2d(unpack, pixels,
403                                                       width, height,
404                                                       GL_COLOR_INDEX, type,
405                                                       row, skipPixels);
406          _mesa_unpack_stencil_span(ctx, spanWidth, destType, values,
407                                    type, source, unpack,
408                                    ctx->_ImageTransferState);
409          if (zoom) {
410             _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth,
411                                               spanX, spanY, values);
412          }
413          else {
414             _swrast_write_stencil_span(ctx, spanWidth, spanX, spanY, values);
415          }
416       }
417       skipPixels += spanWidth;
418    }
419 }
420
421
422 /*
423  * Draw depth image.
424  */
425 static void
426 draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
427                    GLsizei width, GLsizei height,
428                    GLenum type,
429                    const struct gl_pixelstore_attrib *unpack,
430                    const GLvoid *pixels )
431 {
432    const GLboolean scaleOrBias
433       = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
434    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
435    SWspan span;
436
437    INIT_SPAN(span, GL_BITMAP);
438    span.arrayMask = SPAN_Z;
439    _swrast_span_default_attribs(ctx, &span);
440
441    if (type == GL_UNSIGNED_SHORT
442        && ctx->DrawBuffer->Visual.depthBits == 16
443        && !scaleOrBias
444        && !zoom
445        && ctx->Visual.rgbMode
446        && width <= MAX_WIDTH
447        && !unpack->SwapBytes) {
448       /* Special case: directly write 16-bit depth values */
449       GLint row;
450       for (row = 0; row < height; row++) {
451          const GLushort *zSrc = (const GLushort *)
452             _mesa_image_address2d(unpack, pixels, width, height,
453                                   GL_DEPTH_COMPONENT, type, row, 0);
454          GLint i;
455          for (i = 0; i < width; i++)
456             span.array->z[i] = zSrc[i];
457          span.x = x;
458          span.y = y + row;
459          span.end = width;
460          _swrast_write_rgba_span(ctx, &span);
461       }
462    }
463    else if (type == GL_UNSIGNED_INT
464             && !scaleOrBias
465             && !zoom
466             && ctx->Visual.rgbMode
467             && width <= MAX_WIDTH
468             && !unpack->SwapBytes) {
469       /* Special case: shift 32-bit values down to Visual.depthBits */
470       const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits;
471       GLint row;
472       for (row = 0; row < height; row++) {
473          const GLuint *zSrc = (const GLuint *)
474             _mesa_image_address2d(unpack, pixels, width, height,
475                                   GL_DEPTH_COMPONENT, type, row, 0);
476          if (shift == 0) {
477             _mesa_memcpy(span.array->z, zSrc, width * sizeof(GLuint));
478          }
479          else {
480             GLint col;
481             for (col = 0; col < width; col++)
482                span.array->z[col] = zSrc[col] >> shift;
483          }
484          span.x = x;
485          span.y = y + row;
486          span.end = width;
487          _swrast_write_rgba_span(ctx, &span);
488       }
489    }
490    else {
491       /* General case */
492       const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
493       GLint skipPixels = 0;
494
495       /* in case width > MAX_WIDTH do the copy in chunks */
496       while (skipPixels < width) {
497          const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
498          GLint row;
499          ASSERT(span.end <= MAX_WIDTH);
500          for (row = 0; row < height; row++) {
501             const GLvoid *zSrc = _mesa_image_address2d(unpack,
502                                                       pixels, width, height,
503                                                       GL_DEPTH_COMPONENT, type,
504                                                       row, skipPixels);
505
506             /* Set these for each row since the _swrast_write_* function may
507              * change them while clipping.
508              */
509             span.x = x + skipPixels;
510             span.y = y + row;
511             span.end = spanWidth;
512
513             _mesa_unpack_depth_span(ctx, spanWidth,
514                                     GL_UNSIGNED_INT, span.array->z, depthMax,
515                                     type, zSrc, unpack);
516             if (zoom) {
517                _swrast_write_zoomed_depth_span(ctx, x, y, &span);
518             }
519             else if (ctx->Visual.rgbMode) {
520                _swrast_write_rgba_span(ctx, &span);
521             }
522             else {
523                _swrast_write_index_span(ctx, &span);
524             }
525          }
526          skipPixels += spanWidth;
527       }
528    }
529 }
530
531
532
533 /**
534  * Draw RGBA image.
535  */
536 static void
537 draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
538                   GLsizei width, GLsizei height,
539                   GLenum format, GLenum type,
540                   const struct gl_pixelstore_attrib *unpack,
541                   const GLvoid *pixels )
542 {
543    const GLint imgX = x, imgY = y;
544    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
545    GLfloat *convImage = NULL;
546    GLbitfield transferOps = ctx->_ImageTransferState;
547    SWspan span;
548
549    /* Try an optimized glDrawPixels first */
550    if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type,
551                              unpack, pixels)) {
552       return;
553    }
554
555    INIT_SPAN(span, GL_BITMAP);
556    _swrast_span_default_attribs(ctx, &span);
557    span.arrayMask = SPAN_RGBA;
558    span.arrayAttribs = FRAG_BIT_COL0; /* we're fill in COL0 attrib values */
559
560    if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
561       /* Convolution has to be handled specially.  We'll create an
562        * intermediate image, applying all pixel transfer operations
563        * up to convolution.  Then we'll convolve the image.  Then
564        * we'll proceed with the rest of the transfer operations and
565        * rasterize the image.
566        */
567       GLint row;
568       GLfloat *dest, *tmpImage;
569
570       tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
571       if (!tmpImage) {
572          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
573          return;
574       }
575       convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
576       if (!convImage) {
577          _mesa_free(tmpImage);
578          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
579          return;
580       }
581
582       /* Unpack the image and apply transfer ops up to convolution */
583       dest = tmpImage;
584       for (row = 0; row < height; row++) {
585          const GLvoid *source = _mesa_image_address2d(unpack,
586                                   pixels, width, height, format, type, row, 0);
587          _mesa_unpack_color_span_float(ctx, width, GL_RGBA, (GLfloat *) dest,
588                                      format, type, source, unpack,
589                                      transferOps & IMAGE_PRE_CONVOLUTION_BITS);
590          dest += width * 4;
591       }
592
593       /* do convolution */
594       if (ctx->Pixel.Convolution2DEnabled) {
595          _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
596       }
597       else {
598          ASSERT(ctx->Pixel.Separable2DEnabled);
599          _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
600       }
601       _mesa_free(tmpImage);
602
603       /* continue transfer ops and draw the convolved image */
604       unpack = &ctx->DefaultPacking;
605       pixels = convImage;
606       format = GL_RGBA;
607       type = GL_FLOAT;
608       transferOps &= IMAGE_POST_CONVOLUTION_BITS;
609    }
610    else if (ctx->Pixel.Convolution1DEnabled) {
611       /* we only want to apply 1D convolution to glTexImage1D */
612       transferOps &= ~(IMAGE_CONVOLUTION_BIT |
613                        IMAGE_POST_CONVOLUTION_SCALE_BIAS);
614    }
615
616    if (ctx->DrawBuffer->_NumColorDrawBuffers > 0 &&
617        ctx->DrawBuffer->_ColorDrawBuffers[0]->DataType != GL_FLOAT &&
618        ctx->Color.ClampFragmentColor != GL_FALSE) {
619       /* need to clamp colors before applying fragment ops */
620       transferOps |= IMAGE_CLAMP_BIT;
621    }
622
623    /*
624     * General solution
625     */
626    {
627       const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink)
628          || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink);
629       const GLbitfield interpMask = span.interpMask;
630       const GLbitfield arrayMask = span.arrayMask;
631       const GLint srcStride
632          = _mesa_image_row_stride(unpack, width, format, type);
633       GLint skipPixels = 0;
634       /* use span array for temp color storage */
635       GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0];
636
637       /* if the span is wider than MAX_WIDTH we have to do it in chunks */
638       while (skipPixels < width) {
639          const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
640          const GLubyte *source
641             = (const GLubyte *) _mesa_image_address2d(unpack, pixels,
642                                                       width, height, format,
643                                                       type, 0, skipPixels);
644          GLint row;
645
646          for (row = 0; row < height; row++) {
647             /* get image row as float/RGBA */
648             _mesa_unpack_color_span_float(ctx, spanWidth, GL_RGBA, rgba,
649                                      format, type, source, unpack,
650                                      transferOps);
651             /* draw the span */
652             if (!sink) {
653                /* Set these for each row since the _swrast_write_* functions
654                 * may change them while clipping/rendering.
655                 */
656                span.array->ChanType = GL_FLOAT;
657                span.x = x + skipPixels;
658                span.y = y + row;
659                span.end = spanWidth;
660                span.arrayMask = arrayMask;
661                span.interpMask = interpMask;
662                if (zoom) {
663                   _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba);
664                }
665                else {
666                   _swrast_write_rgba_span(ctx, &span);
667                }
668             }
669
670             source += srcStride;
671          } /* for row */
672
673          skipPixels += spanWidth;
674       } /* while skipPixels < width */
675
676       /* XXX this is ugly/temporary, to undo above change */
677       span.array->ChanType = CHAN_TYPE;
678    }
679
680    if (convImage) {
681       _mesa_free(convImage);
682    }
683 }
684
685
686 /**
687  * This is a bit different from drawing GL_DEPTH_COMPONENT pixels.
688  * The only per-pixel operations that apply are depth scale/bias,
689  * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK,
690  * and pixel zoom.
691  * Also, only the depth buffer and stencil buffers are touched, not the
692  * color buffer(s).
693  */
694 static void
695 draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
696                           GLsizei width, GLsizei height, GLenum type,
697                           const struct gl_pixelstore_attrib *unpack,
698                           const GLvoid *pixels)
699 {
700    const GLint imgX = x, imgY = y;
701    const GLboolean scaleOrBias
702       = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
703    const GLuint depthMax = ctx->DrawBuffer->_DepthMax;
704    const GLuint stencilMask = ctx->Stencil.WriteMask[0];
705    const GLuint stencilType = (STENCIL_BITS == 8) ? 
706       GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
707    const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
708    struct gl_renderbuffer *depthRb, *stencilRb;
709    struct gl_pixelstore_attrib clippedUnpack = *unpack;
710
711    if (!zoom) {
712       if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
713                                  &clippedUnpack)) {
714          /* totally clipped */
715          return;
716       }
717    }
718    
719    depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
720    stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
721    ASSERT(depthRb);
722    ASSERT(stencilRb);
723
724    if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
725        stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT &&
726        depthRb == stencilRb &&
727        !scaleOrBias &&
728        !zoom &&
729        ctx->Depth.Mask &&
730        (stencilMask & 0xff) == 0xff) {
731       /* This is the ideal case.
732        * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer.
733        * Plus, no pixel transfer ops, zooming, or masking needed.
734        */
735       GLint i;
736       for (i = 0; i < height; i++) {
737          const GLuint *src = (const GLuint *) 
738             _mesa_image_address2d(&clippedUnpack, pixels, width, height,
739                                   GL_DEPTH_STENCIL_EXT, type, i, 0);
740          depthRb->PutRow(ctx, depthRb, width, x, y + i, src, NULL);
741       }
742    }
743    else {
744       /* sub-optimal cases:
745        * Separate depth/stencil buffers, or pixel transfer ops required.
746        */
747       /* XXX need to handle very wide images (skippixels) */
748       GLint i;
749
750       depthRb = ctx->DrawBuffer->_DepthBuffer;
751       stencilRb = ctx->DrawBuffer->_StencilBuffer;
752
753       for (i = 0; i < height; i++) {
754          const GLuint *depthStencilSrc = (const GLuint *)
755             _mesa_image_address2d(&clippedUnpack, pixels, width, height,
756                                   GL_DEPTH_STENCIL_EXT, type, i, 0);
757
758          if (ctx->Depth.Mask) {
759             if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24) {
760                /* fast path 24-bit zbuffer */
761                GLuint zValues[MAX_WIDTH];
762                GLint j;
763                ASSERT(depthRb->DataType == GL_UNSIGNED_INT);
764                for (j = 0; j < width; j++) {
765                   zValues[j] = depthStencilSrc[j] >> 8;
766                }
767                if (zoom)
768                   _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
769                                               x, y + i, zValues);
770                else
771                   depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
772             }
773             else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16) {
774                /* fast path 16-bit zbuffer */
775                GLushort zValues[MAX_WIDTH];
776                GLint j;
777                ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT);
778                for (j = 0; j < width; j++) {
779                   zValues[j] = depthStencilSrc[j] >> 16;
780                }
781                if (zoom)
782                   _swrast_write_zoomed_z_span(ctx, imgX, imgY, width,
783                                               x, y + i, zValues);
784                else
785                   depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
786             }
787             else {
788                /* general case */
789                GLuint zValues[MAX_WIDTH];  /* 16 or 32-bit Z value storage */
790                _mesa_unpack_depth_span(ctx, width,
791                                        depthRb->DataType, zValues, depthMax,
792                                        type, depthStencilSrc, &clippedUnpack);
793                if (zoom) {
794                   _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x,
795                                               y + i, zValues);
796                }
797                else {
798                   depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL);
799                }
800             }
801          }
802
803          if (stencilMask != 0x0) {
804             GLstencil stencilValues[MAX_WIDTH];
805             /* get stencil values, with shift/offset/mapping */
806             _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues,
807                                       type, depthStencilSrc, &clippedUnpack,
808                                       ctx->_ImageTransferState);
809             if (zoom)
810                _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width,
811                                                   x, y + i, stencilValues);
812             else
813                _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues);
814          }
815       }
816    }
817 }
818
819
820 /**
821  * Execute software-based glDrawPixels.
822  * By time we get here, all error checking will have been done.
823  */
824 void
825 _swrast_DrawPixels( GLcontext *ctx,
826                     GLint x, GLint y,
827                     GLsizei width, GLsizei height,
828                     GLenum format, GLenum type,
829                     const struct gl_pixelstore_attrib *unpack,
830                     const GLvoid *pixels )
831 {
832    SWcontext *swrast = SWRAST_CONTEXT(ctx);
833    GLboolean save_vp_override = ctx->VertexProgram._Overriden;
834
835    if (!_mesa_check_conditional_render(ctx))
836       return; /* don't draw */
837
838    /* We are creating fragments directly, without going through vertex
839     * programs.
840     *
841     * This override flag tells the fragment processing code that its input
842     * comes from a non-standard source, and it may therefore not rely on
843     * optimizations that assume e.g. constant color if there is no color
844     * vertex array.
845     */
846    _mesa_set_vp_override(ctx, GL_TRUE);
847
848    swrast_render_start(ctx);
849
850    if (ctx->NewState)
851       _mesa_update_state(ctx);
852
853    if (swrast->NewState)
854       _swrast_validate_derived( ctx );
855
856     pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
857     if (!pixels) {
858        swrast_render_finish(ctx);
859        _mesa_set_vp_override(ctx, save_vp_override);
860        return;
861     }
862
863    switch (format) {
864    case GL_STENCIL_INDEX:
865       draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels );
866       break;
867    case GL_DEPTH_COMPONENT:
868       draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels );
869       break;
870    case GL_COLOR_INDEX:
871       if (ctx->Visual.rgbMode)
872          draw_rgba_pixels(ctx, x,y, width, height, format, type, unpack, pixels);
873       else
874          draw_index_pixels(ctx, x, y, width, height, type, unpack, pixels);
875       break;
876    case GL_RED:
877    case GL_GREEN:
878    case GL_BLUE:
879    case GL_ALPHA:
880    case GL_LUMINANCE:
881    case GL_LUMINANCE_ALPHA:
882    case GL_RGB:
883    case GL_BGR:
884    case GL_RGBA:
885    case GL_BGRA:
886    case GL_ABGR_EXT:
887       draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels);
888       break;
889    case GL_DEPTH_STENCIL_EXT:
890       draw_depth_stencil_pixels(ctx, x, y, width, height,
891                                 type, unpack, pixels);
892       break;
893    default:
894       _mesa_problem(ctx, "unexpected format in _swrast_DrawPixels");
895       /* don't return yet, clean-up */
896    }
897
898    swrast_render_finish(ctx);
899    _mesa_set_vp_override(ctx, save_vp_override);
900
901    _mesa_unmap_pbo_source(ctx, unpack);
902 }