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