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