OSDN Git Service

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