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