Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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