home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / swrast / s_drawpix.cpp < prev    next >
C/C++ Source or Header  |  2002-12-18  |  35KB  |  988 lines

  1. /* $Id: s_drawpix.c,v 1.42 2002/12/18 15:02:19 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. #include "glheader.h"
  29. #include "context.h"
  30. #include "convolve.h"
  31. #include "image.h"
  32. #include "macros.h"
  33. #include "imports.h"
  34. #include "mmath.h"
  35. #include "pixel.h"
  36.  
  37. #include "s_context.h"
  38. #include "s_drawpix.h"
  39. #include "s_pixeltex.h"
  40. #include "s_span.h"
  41. #include "s_stencil.h"
  42. #include "s_zoom.h"
  43.  
  44.  
  45.  
  46. /*
  47.  * Given the dest position, size and skipPixels and skipRows values
  48.  * for a glDrawPixels command, perform clipping of the image bounds
  49.  * so the result lies withing the context's buffer bounds.
  50.  * Return:  GL_TRUE if image is ready for drawing
  51.  *          GL_FALSE if image was completely clipped away (draw nothing)
  52.  */
  53. GLboolean
  54. _mesa_clip_pixelrect(const GLcontext *ctx,
  55.                      GLint *destX, GLint *destY,
  56.                      GLsizei *width, GLsizei *height,
  57.                      GLint *skipPixels, GLint *skipRows)
  58. {
  59.    const GLframebuffer *buffer = ctx->DrawBuffer;
  60.  
  61.    /* left clipping */
  62.    if (*destX < buffer->_Xmin) {
  63.       *skipPixels += (buffer->_Xmin - *destX);
  64.       *width -= (buffer->_Xmin - *destX);
  65.       *destX = buffer->_Xmin;
  66.    }
  67.    /* right clipping */
  68.    if (*destX + *width > buffer->_Xmax)
  69.       *width -= (*destX + *width - buffer->_Xmax);
  70.  
  71.    if (*width <= 0)
  72.       return GL_FALSE;
  73.  
  74.    /* bottom clipping */
  75.    if (*destY < buffer->_Ymin) {
  76.       *skipRows += (buffer->_Ymin - *destY);
  77.       *height -= (buffer->_Ymin - *destY);
  78.       *destY = buffer->_Ymin;
  79.    }
  80.    /* top clipping */
  81.    if (*destY + *height > buffer->_Ymax)
  82.       *height -= (*destY + *height - buffer->_Ymax);
  83.  
  84.    if (*height <= 0)
  85.       return GL_TRUE;
  86.  
  87.    return GL_TRUE;
  88. }
  89.  
  90.  
  91.  
  92. /*
  93.  * Try to do a fast and simple RGB(a) glDrawPixels.
  94.  * Return:  GL_TRUE if success, GL_FALSE if slow path must be used instead
  95.  */
  96. static GLboolean
  97. fast_draw_pixels(GLcontext *ctx, GLint x, GLint y,
  98.                  GLsizei width, GLsizei height,
  99.                  GLenum format, GLenum type, const GLvoid *pixels)
  100. {
  101.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  102.    const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
  103.    struct sw_span span;
  104.  
  105.    INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
  106.  
  107.    if (!ctx->Current.RasterPosValid) {
  108.       return GL_TRUE;      /* no-op */
  109.    }
  110.  
  111.    if (ctx->Depth.Test)
  112.       _mesa_span_default_z(ctx, &span);
  113.    if (ctx->Fog.Enabled)
  114.       _mesa_span_default_fog(ctx, &span);
  115.    if (ctx->Texture._EnabledUnits)
  116.       _mesa_span_default_texcoords(ctx, &span);
  117.  
  118.    if ((SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) == 0
  119.        && ctx->Texture._EnabledUnits == 0
  120.        && unpack->Alignment == 1
  121.        && !unpack->SwapBytes
  122.        && !unpack->LsbFirst) {
  123.  
  124.       GLint destX = x;
  125.       GLint destY = y;
  126.       GLint drawWidth = width;           /* actual width drawn */
  127.       GLint drawHeight = height;         /* actual height drawn */
  128.       GLint skipPixels = unpack->SkipPixels;
  129.       GLint skipRows = unpack->SkipRows;
  130.       GLint rowLength;
  131.       GLdepth zSpan[MAX_WIDTH];  /* only used when zooming */
  132.       GLint zoomY0 = 0;
  133.  
  134.       if (unpack->RowLength > 0)
  135.          rowLength = unpack->RowLength;
  136.       else
  137.          rowLength = width;
  138.  
  139.       /* If we're not using pixel zoom then do all clipping calculations
  140.        * now.  Otherwise, we'll let the _mesa_write_zoomed_*_span() functions
  141.        * handle the clipping.
  142.        */
  143.       if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  144.          /* horizontal clipping */
  145.          if (destX < ctx->DrawBuffer->_Xmin) {
  146.             skipPixels += (ctx->DrawBuffer->_Xmin - destX);
  147.             drawWidth  -= (ctx->DrawBuffer->_Xmin - destX);
  148.             destX = ctx->DrawBuffer->_Xmin;
  149.          }
  150.          if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
  151.             drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
  152.          if (drawWidth <= 0)
  153.             return GL_TRUE;
  154.  
  155.          /* vertical clipping */
  156.          if (destY < ctx->DrawBuffer->_Ymin) {
  157.             skipRows   += (ctx->DrawBuffer->_Ymin - destY);
  158.             drawHeight -= (ctx->DrawBuffer->_Ymin - destY);
  159.             destY = ctx->DrawBuffer->_Ymin;
  160.          }
  161.          if (destY + drawHeight > ctx->DrawBuffer->_Ymax)
  162.             drawHeight -= (destY + drawHeight - ctx->DrawBuffer->_Ymax);
  163.          if (drawHeight <= 0)
  164.             return GL_TRUE;
  165.       }
  166.       else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
  167.          /* upside-down image */
  168.          /* horizontal clipping */
  169.          if (destX < ctx->DrawBuffer->_Xmin) {
  170.             skipPixels += (ctx->DrawBuffer->_Xmin - destX);
  171.             drawWidth  -= (ctx->DrawBuffer->_Xmin - destX);
  172.             destX = ctx->DrawBuffer->_Xmin;
  173.          }
  174.          if (destX + drawWidth > ctx->DrawBuffer->_Xmax)
  175.             drawWidth -= (destX + drawWidth - ctx->DrawBuffer->_Xmax);
  176.          if (drawWidth <= 0)
  177.             return GL_TRUE;
  178.  
  179.          /* vertical clipping */
  180.          if (destY > ctx->DrawBuffer->_Ymax) {
  181.             skipRows   += (destY - ctx->DrawBuffer->_Ymax);
  182.             drawHeight -= (destY - ctx->DrawBuffer->_Ymax);
  183.             destY = ctx->DrawBuffer->_Ymax;
  184.          }
  185.          if (destY - drawHeight < ctx->DrawBuffer->_Ymin)
  186.             drawHeight -= (ctx->DrawBuffer->_Ymin - (destY - drawHeight));
  187.          if (drawHeight <= 0)
  188.             return GL_TRUE;
  189.       }
  190.       else {
  191.          /* setup array of fragment Z value to pass to zoom function */
  192.          GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->DepthMaxF);
  193.          GLint i;
  194.          if (drawWidth > MAX_WIDTH)
  195.             return GL_FALSE; /* fall back to general case path */
  196.          for (i=0; i<drawWidth; i++)
  197.             zSpan[i] = z;
  198.  
  199.          /* save Y value of first row */
  200.          zoomY0 = IROUND(ctx->Current.RasterPos[1]);
  201.       }
  202.  
  203.  
  204.       /*
  205.        * Ready to draw!
  206.        * The window region at (destX, destY) of size (drawWidth, drawHeight)
  207.        * will be written to.
  208.        * We'll take pixel data from buffer pointed to by "pixels" but we'll
  209.        * skip "skipRows" rows and skip "skipPixels" pixels/row.
  210.        */
  211.  
  212.       if (format == GL_RGBA && type == CHAN_TYPE
  213.           && ctx->_ImageTransferState==0) {
  214.          if (ctx->Visual.rgbMode) {
  215.             GLchan *src = (GLchan *) pixels
  216.                + (skipRows * rowLength + skipPixels) * 4;
  217.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  218.                /* no zooming */
  219.                GLint row;
  220.                for (row=0; row<drawHeight; row++) {
  221.                   (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
  222.                                               (CONST GLchan (*)[4]) src, NULL);
  223.                   src += rowLength * 4;
  224.                   destY++;
  225.                }
  226.             }
  227.             else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
  228.                /* upside-down */
  229.                GLint row;
  230.                for (row=0; row<drawHeight; row++) {
  231.                   destY--;
  232.                   (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
  233.                                               (CONST GLchan (*)[4]) src, NULL);
  234.                   src += rowLength * 4;
  235.                }
  236.             }
  237.             else {
  238.                /* with zooming */
  239.                GLint row;
  240.                for (row=0; row<drawHeight; row++) {
  241.                   span.x = destX;
  242.                   span.y = destY;
  243.                   span.end = drawWidth;
  244.                   _mesa_write_zoomed_rgba_span(ctx, &span,
  245.                                         (CONST GLchan (*)[4]) src, zoomY0, 0);
  246.                   src += rowLength * 4;
  247.                   destY++;
  248.                }
  249.             }
  250.          }
  251.          return GL_TRUE;
  252.       }
  253.       else if (format == GL_RGB && type == CHAN_TYPE
  254.                && ctx->_ImageTransferState == 0) {
  255.          if (ctx->Visual.rgbMode) {
  256.             GLchan *src = (GLchan *) pixels
  257.                + (skipRows * rowLength + skipPixels) * 3;
  258.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  259.                GLint row;
  260.                for (row=0; row<drawHeight; row++) {
  261.                   (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
  262.                                               (CONST GLchan (*)[3]) src, NULL);
  263.                   src += rowLength * 3;
  264.                   destY++;
  265.                }
  266.             }
  267.             else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
  268.                /* upside-down */
  269.                GLint row;
  270.                for (row=0; row<drawHeight; row++) {
  271.                   destY--;
  272.                   (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
  273.                                               (CONST GLchan (*)[3]) src, NULL);
  274.                   src += rowLength * 3;
  275.                }
  276.             }
  277.             else {
  278.                /* with zooming */
  279.                GLint row;
  280.                for (row=0; row<drawHeight; row++) {
  281.                   span.x = destX;
  282.                   span.y = destY;
  283.                   span.end = drawWidth;
  284.                   _mesa_write_zoomed_rgb_span(ctx, &span, 
  285.                                          (CONST GLchan (*)[3]) src, zoomY0, 0);
  286.                   src += rowLength * 3;
  287.                   destY++;
  288.                }
  289.             }
  290.          }
  291.          return GL_TRUE;
  292.       }
  293.       else if (format == GL_LUMINANCE && type == CHAN_TYPE
  294.                && ctx->_ImageTransferState==0) {
  295.          if (ctx->Visual.rgbMode) {
  296.             GLchan *src = (GLchan *) pixels
  297.                + (skipRows * rowLength + skipPixels);
  298.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  299.                /* no zooming */
  300.                GLint row;
  301.                ASSERT(drawWidth < MAX_WIDTH);
  302.                for (row=0; row<drawHeight; row++) {
  303.                   GLint i;
  304.           for (i=0;i<drawWidth;i++) {
  305.                      span.array->rgb[i][0] = src[i];
  306.                      span.array->rgb[i][1] = src[i];
  307.                      span.array->rgb[i][2] = src[i];
  308.           }
  309.                   (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
  310.                                   (CONST GLchan (*)[3]) span.array->rgb, NULL);
  311.                   src += rowLength;
  312.                   destY++;
  313.                }
  314.             }
  315.             else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
  316.                /* upside-down */
  317.                GLint row;
  318.                ASSERT(drawWidth < MAX_WIDTH);
  319.                for (row=0; row<drawHeight; row++) {
  320.                   GLint i;
  321.                   for (i=0;i<drawWidth;i++) {
  322.                      span.array->rgb[i][0] = src[i];
  323.                      span.array->rgb[i][1] = src[i];
  324.                      span.array->rgb[i][2] = src[i];
  325.                   }
  326.                   destY--;
  327.                   (*swrast->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
  328.                                   (CONST GLchan (*)[3]) span.array->rgb, NULL);
  329.                   src += rowLength;
  330.                }
  331.             }
  332.             else {
  333.                /* with zooming */
  334.                GLint row;
  335.                ASSERT(drawWidth < MAX_WIDTH);
  336.                for (row=0; row<drawHeight; row++) {
  337.                   GLint i;
  338.           for (i=0;i<drawWidth;i++) {
  339.                      span.array->rgb[i][0] = src[i];
  340.                      span.array->rgb[i][1] = src[i];
  341.                      span.array->rgb[i][2] = src[i];
  342.           }
  343.                   span.x = destX;
  344.                   span.y = destY;
  345.                   span.end = drawWidth;
  346.                   _mesa_write_zoomed_rgb_span(ctx, &span,
  347.                              (CONST GLchan (*)[3]) span.array->rgb, zoomY0, 0);
  348.                   src += rowLength;
  349.                   destY++;
  350.                }
  351.             }
  352.          }
  353.          return GL_TRUE;
  354.       }
  355.       else if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE
  356.                && ctx->_ImageTransferState == 0) {
  357.          if (ctx->Visual.rgbMode) {
  358.             GLchan *src = (GLchan *) pixels
  359.                + (skipRows * rowLength + skipPixels)*2;
  360.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  361.                /* no zooming */
  362.                GLint row;
  363.                ASSERT(drawWidth < MAX_WIDTH);
  364.                for (row=0; row<drawHeight; row++) {
  365.                   GLint i;
  366.                   GLchan *ptr = src;
  367.           for (i=0;i<drawWidth;i++) {
  368.                      span.array->rgba[i][0] = *ptr;
  369.                      span.array->rgba[i][1] = *ptr;
  370.                      span.array->rgba[i][2] = *ptr++;
  371.                      span.array->rgba[i][3] = *ptr++;
  372.           }
  373.                   (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
  374.                                  (CONST GLchan (*)[4]) span.array->rgba, NULL);
  375.                   src += rowLength*2;
  376.                   destY++;
  377.                }
  378.             }
  379.             else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
  380.                /* upside-down */
  381.                GLint row;
  382.                ASSERT(drawWidth < MAX_WIDTH);
  383.                for (row=0; row<drawHeight; row++) {
  384.                   GLint i;
  385.                   GLchan *ptr = src;
  386.                   for (i=0;i<drawWidth;i++) {
  387.                      span.array->rgba[i][0] = *ptr;
  388.                      span.array->rgba[i][1] = *ptr;
  389.                      span.array->rgba[i][2] = *ptr++;
  390.                      span.array->rgba[i][3] = *ptr++;
  391.                   }
  392.                   destY--;
  393.                   (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
  394.                                  (CONST GLchan (*)[4]) span.array->rgba, NULL);
  395.                   src += rowLength*2;
  396.                }
  397.             }
  398.             else {
  399.                /* with zooming */
  400.                GLint row;
  401.                ASSERT(drawWidth < MAX_WIDTH);
  402.                for (row=0; row<drawHeight; row++) {
  403.                   GLchan *ptr = src;
  404.                   GLint i;
  405.           for (i=0;i<drawWidth;i++) {
  406.                      span.array->rgba[i][0] = *ptr;
  407.                      span.array->rgba[i][1] = *ptr;
  408.                      span.array->rgba[i][2] = *ptr++;
  409.                      span.array->rgba[i][3] = *ptr++;
  410.           }
  411.                   span.x = destX;
  412.                   span.y = destY;
  413.                   span.end = drawWidth;
  414.                   _mesa_write_zoomed_rgba_span(ctx, &span,
  415.                             (CONST GLchan (*)[4]) span.array->rgba, zoomY0, 0);
  416.                   src += rowLength*2;
  417.                   destY++;
  418.                }
  419.             }
  420.          }
  421.          return GL_TRUE;
  422.       }
  423.       else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
  424.          GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
  425.          if (ctx->Visual.rgbMode) {
  426.             /* convert CI data to RGBA */
  427.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  428.                /* no zooming */
  429.                GLint row;
  430.                for (row=0; row<drawHeight; row++) {
  431.                   ASSERT(drawWidth < MAX_WIDTH);
  432.                   _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
  433.                   (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
  434.                                  (const GLchan (*)[4]) span.array->rgba, NULL);
  435.                   src += rowLength;
  436.                   destY++;
  437.                }
  438.                return GL_TRUE;
  439.             }
  440.             else if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==-1.0F) {
  441.                /* upside-down */
  442.                GLint row;
  443.                for (row=0; row<drawHeight; row++) {
  444.                   ASSERT(drawWidth < MAX_WIDTH);
  445.                   _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
  446.                   destY--;
  447.                   (*swrast->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
  448.                                  (CONST GLchan (*)[4]) span.array->rgba, NULL);
  449.                   src += rowLength;
  450.                }
  451.                return GL_TRUE;
  452.             }
  453.             else {
  454.                /* with zooming */
  455.                GLint row;
  456.                for (row=0; row<drawHeight; row++) {
  457.                   ASSERT(drawWidth < MAX_WIDTH);
  458.                   _mesa_map_ci8_to_rgba(ctx, drawWidth, src, span.array->rgba);
  459.                   span.x = destX;
  460.                   span.y = destY;
  461.                   span.end = drawWidth;
  462.                   _mesa_write_zoomed_rgba_span(ctx, &span,
  463.                             (CONST GLchan (*)[4]) span.array->rgba, zoomY0, 0);
  464.                   src += rowLength;
  465.                   destY++;
  466.                }
  467.                return GL_TRUE;
  468.             }
  469.          }
  470.          else if (ctx->_ImageTransferState==0) {
  471.             /* write CI data to CI frame buffer */
  472.             GLint row;
  473.             if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  474.                /* no zooming */
  475.                for (row=0; row<drawHeight; row++) {
  476.                   (*swrast->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
  477.                                               src, NULL);
  478.                   src += rowLength;
  479.                   destY++;
  480.                }
  481.                return GL_TRUE;
  482.             }
  483.             else {
  484.                /* with zooming */
  485.                return GL_FALSE;
  486.             }
  487.          }
  488.       }
  489.       else {
  490.          /* can't handle this pixel format and/or data type here */
  491.          return GL_FALSE;
  492.       }
  493.    }
  494.  
  495.    /* can't do a simple draw, have to use slow path */
  496.    return GL_FALSE;
  497. }
  498.  
  499.  
  500.  
  501. /*
  502.  * Draw color index image.
  503.  */
  504. static void
  505. draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
  506.                    GLsizei width, GLsizei height,
  507.                    GLenum type, const GLvoid *pixels )
  508. {
  509.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
  510.    GLint row, skipPixels;
  511.    struct sw_span span;
  512.  
  513.    INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_INDEX);
  514.  
  515.    if (ctx->Depth.Test)
  516.       _mesa_span_default_z(ctx, &span);
  517.    if (ctx->Fog.Enabled)
  518.       _mesa_span_default_fog(ctx, &span);
  519.  
  520.    /*
  521.     * General solution
  522.     */
  523.    skipPixels = 0;
  524.    while (skipPixels < width) {
  525.       span.x = x + (zoom ? 0 : skipPixels);
  526.       span.y = y;
  527.       span.end = (width - skipPixels > MAX_WIDTH)
  528.                ? MAX_WIDTH : (width - skipPixels);
  529.       ASSERT(span.end <= MAX_WIDTH);
  530.       for (row = 0; row < height; row++, span.y++) {
  531.          const GLvoid *source = _mesa_image_address(&ctx->Unpack, pixels,
  532.                                                     width, height,
  533.                                                     GL_COLOR_INDEX, type,
  534.                                                     0, row, skipPixels);
  535.          _mesa_unpack_index_span(ctx, span.end, GL_UNSIGNED_INT,
  536.                                  span.array->index, type, source, &ctx->Unpack,
  537.                                  ctx->_ImageTransferState);
  538.          if (zoom)
  539.             _mesa_write_zoomed_index_span(ctx, &span, y, skipPixels);
  540.          else
  541.             _mesa_write_index_span(ctx, &span);
  542.       }
  543.       skipPixels += span.end;
  544.    }
  545. }
  546.  
  547.  
  548.  
  549. /*
  550.  * Draw stencil image.
  551.  */
  552. static void
  553. draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
  554.                      GLsizei width, GLsizei height,
  555.                      GLenum type, const GLvoid *pixels )
  556. {
  557.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
  558.    const GLint desty = y;
  559.    GLint row, skipPixels;
  560.  
  561.    if (type != GL_BYTE &&
  562.        type != GL_UNSIGNED_BYTE &&
  563.        type != GL_SHORT &&
  564.        type != GL_UNSIGNED_SHORT &&
  565.        type != GL_INT &&
  566.        type != GL_UNSIGNED_INT &&
  567.        type != GL_FLOAT &&
  568.        type != GL_BITMAP) {
  569.       _mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)");
  570.       return;
  571.    }
  572.  
  573.    if (ctx->Visual.stencilBits == 0) {
  574.       _mesa_error( ctx, GL_INVALID_OPERATION, "glDrawPixels(no stencil buffer)");
  575.       return;
  576.    }
  577.  
  578.    /* if width > MAX_WIDTH, have to process image in chunks */
  579.    skipPixels = 0;
  580.    while (skipPixels < width) {
  581.       GLint spanX = x;
  582.       GLint spanY = y;
  583.       GLint spanWidth = (width - skipPixels > MAX_WIDTH)
  584.                       ? MAX_WIDTH : (width - skipPixels);
  585.  
  586.       for (row = 0; row < height; row++, spanY++) {
  587.          GLstencil values[MAX_WIDTH];
  588.          GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
  589.                          ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
  590.          const GLvoid *source = _mesa_image_address(&ctx->Unpack, pixels,
  591.                                                     width, height,
  592.                                                     GL_COLOR_INDEX, type,
  593.                                                     0, row, skipPixels);
  594.          _mesa_unpack_index_span(ctx, spanWidth, destType, values,
  595.                                  type, source, &ctx->Unpack,
  596.                                  ctx->_ImageTransferState);
  597.          if (ctx->_ImageTransferState & IMAGE_SHIFT_OFFSET_BIT) {
  598.             _mesa_shift_and_offset_stencil(ctx, spanWidth, values);
  599.          }
  600.          if (ctx->Pixel.MapStencilFlag) {
  601.             _mesa_map_stencil(ctx, spanWidth, values);
  602.          }
  603.  
  604.          if (zoom) {
  605.             _mesa_write_zoomed_stencil_span(ctx, (GLuint) spanWidth,
  606.                                             spanX, spanY, values, desty, 0);
  607.          }
  608.          else {
  609.             _mesa_write_stencil_span(ctx, (GLuint) spanWidth,
  610.                                      spanX, spanY, values);
  611.          }
  612.       }
  613.       skipPixels += spanWidth;
  614.    }
  615. }
  616.  
  617.  
  618. /*
  619.  * Draw depth image.
  620.  */
  621. static void
  622. draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
  623.                    GLsizei width, GLsizei height,
  624.                    GLenum type, const GLvoid *pixels )
  625. {
  626.    const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
  627.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
  628.    const GLint desty = y;
  629.    struct sw_span span;
  630.  
  631.    INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_Z);
  632.  
  633.    if (type != GL_BYTE
  634.        && type != GL_UNSIGNED_BYTE
  635.        && type != GL_SHORT
  636.        && type != GL_UNSIGNED_SHORT
  637.        && type != GL_INT
  638.        && type != GL_UNSIGNED_INT
  639.        && type != GL_FLOAT) {
  640.       _mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)");
  641.       return;
  642.    }
  643.  
  644.    _mesa_span_default_color(ctx, &span);
  645.  
  646.    if (ctx->Fog.Enabled)
  647.       _mesa_span_default_fog(ctx, &span);
  648.    if (ctx->Texture._EnabledUnits)
  649.       _mesa_span_default_texcoords(ctx, &span);
  650.  
  651.    if (type == GL_UNSIGNED_SHORT && ctx->Visual.depthBits == 16
  652.        && !bias_or_scale && !zoom && ctx->Visual.rgbMode
  653.        && width < MAX_WIDTH) {
  654.       /* Special case: directly write 16-bit depth values */
  655.       GLint row;
  656.       span.x = x;
  657.       span.y = y;
  658.       span.end = width;
  659.       for (row = 0; row < height; row++, span.y++) {
  660.          const GLushort *zptr = (const GLushort *)
  661.             _mesa_image_address(&ctx->Unpack, pixels, width, height,
  662.                                 GL_DEPTH_COMPONENT, type, 0, row, 0);
  663.          GLint i;
  664.          for (i = 0; i < width; i++)
  665.             span.array->z[i] = zptr[i];
  666.          _mesa_write_rgba_span(ctx, &span);
  667.       }
  668.    }
  669.    else if (type == GL_UNSIGNED_INT && ctx->Visual.depthBits == 32
  670.             && !bias_or_scale && !zoom && ctx->Visual.rgbMode
  671.             && width < MAX_WIDTH) {
  672.       /* Special case: directly write 32-bit depth values */
  673.       GLint row;
  674.       span.x = x;
  675.       span.y = y;
  676.       span.end = width;
  677.       for (row = 0; row < height; row++, span.y++) {
  678.          const GLuint *zptr = (const GLuint *)
  679.             _mesa_image_address(&ctx->Unpack, pixels, width, height,
  680.                                 GL_DEPTH_COMPONENT, type, 0, row, 0);
  681.          MEMCPY(span.array->z, zptr, width * sizeof(GLdepth));
  682.          _mesa_write_rgba_span(ctx, &span);
  683.       }
  684.    }
  685.    else {
  686.       /* General case */
  687.       GLint row, skipPixels = 0;
  688.  
  689.       /* in case width > MAX_WIDTH do the copy in chunks */
  690.       while (skipPixels < width) {
  691.          span.x = x + (zoom ? 0 : skipPixels);
  692.          span.y = y;
  693.          span.end = (width - skipPixels > MAX_WIDTH)
  694.                   ? MAX_WIDTH : (width - skipPixels);
  695.          ASSERT(span.end <= MAX_WIDTH);
  696.          for (row = 0; row < height; row++, span.y++) {
  697.             GLfloat floatSpan[MAX_WIDTH];
  698.             const GLvoid *src = _mesa_image_address(&ctx->Unpack,
  699.                                                     pixels, width, height,
  700.                                                     GL_DEPTH_COMPONENT, type,
  701.                                                     0, row, skipPixels);
  702.             _mesa_unpack_depth_span(ctx, span.end, floatSpan, type,
  703.                                     src, &ctx->Unpack);
  704.             /* clamp depth values to [0,1] and convert from floats to ints */
  705.             {
  706.                const GLfloat zs = ctx->DepthMaxF;
  707.                GLint i;
  708.                for (i = 0; i < span.end; i++) {
  709.                   span.array->z[i] = (GLdepth) (floatSpan[i] * zs + 0.5F);
  710.                }
  711.             }
  712.             if (ctx->Visual.rgbMode) {
  713.                if (zoom) {
  714.                   _mesa_write_zoomed_rgba_span(ctx, &span,
  715.                                      (const GLchan (*)[4]) span.array->rgba,
  716.                                      desty, skipPixels);
  717.                }
  718.                else
  719.                   _mesa_write_rgba_span(ctx, &span);
  720.             }
  721.             else {
  722.                if (zoom)
  723.                   _mesa_write_zoomed_index_span(ctx, &span, desty, 0);
  724.                else
  725.                   _mesa_write_index_span(ctx, &span);
  726.             }
  727.          }
  728.          skipPixels += span.end;
  729.       }
  730.    }
  731. }
  732.  
  733.  
  734.  
  735. /*
  736.  * Draw RGBA image.
  737.  */
  738. static void
  739. draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
  740.                   GLsizei width, GLsizei height,
  741.                   GLenum format, GLenum type, const GLvoid *pixels )
  742. {
  743.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  744.    const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
  745.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
  746.    const GLint desty = y;
  747.    GLboolean quickDraw;
  748.    GLfloat *convImage = NULL;
  749.    GLuint transferOps = ctx->_ImageTransferState;
  750.    struct sw_span span;
  751.  
  752.    INIT_SPAN(span, GL_BITMAP, 0, 0, SPAN_RGBA);
  753.  
  754.    if (!_mesa_is_legal_format_and_type(format, type)) {
  755.       _mesa_error(ctx, GL_INVALID_ENUM, "glDrawPixels(format or type)");
  756.       return;
  757.    }
  758.  
  759.    /* Try an optimized glDrawPixels first */
  760.    if (fast_draw_pixels(ctx, x, y, width, height, format, type, pixels))
  761.       return;
  762.  
  763.    if (ctx->Depth.Test)
  764.       _mesa_span_default_z(ctx, &span);
  765.    if (ctx->Fog.Enabled)
  766.       _mesa_span_default_fog(ctx, &span);
  767.    if (ctx->Texture._EnabledUnits)
  768.       _mesa_span_default_texcoords(ctx, &span);
  769.  
  770.    if (SWRAST_CONTEXT(ctx)->_RasterMask == 0 && !zoom && x >= 0 && y >= 0
  771.        && x + width <= (GLint) ctx->DrawBuffer->Width
  772.        && y + height <= (GLint) ctx->DrawBuffer->Height) {
  773.       quickDraw = GL_TRUE;
  774.    }
  775.    else {
  776.       quickDraw = GL_FALSE;
  777.    }
  778.  
  779.    if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) {
  780.       /* Convolution has to be handled specially.  We'll create an
  781.        * intermediate image, applying all pixel transfer operations
  782.        * up to convolution.  Then we'll convolve the image.  Then
  783.        * we'll proceed with the rest of the transfer operations and
  784.        * rasterize the image.
  785.        */
  786.       GLint row;
  787.       GLfloat *dest, *tmpImage;
  788.  
  789.       tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
  790.       if (!tmpImage) {
  791.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
  792.          return;
  793.       }
  794.       convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
  795.       if (!convImage) {
  796.          FREE(tmpImage);
  797.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels");
  798.          return;
  799.       }
  800.  
  801.       /* Unpack the image and apply transfer ops up to convolution */
  802.       dest = tmpImage;
  803.       for (row = 0; row < height; row++) {
  804.          const GLvoid *source = _mesa_image_address(unpack,
  805.                   pixels, width, height, format, type, 0, row, 0);
  806.          _mesa_unpack_float_color_span(ctx, width, GL_RGBA, (GLfloat *) dest,
  807.                                       format, type, source, unpack,
  808.                                       transferOps & IMAGE_PRE_CONVOLUTION_BITS,
  809.                                       GL_FALSE);
  810.          dest += width * 4;
  811.       }
  812.  
  813.       /* do convolution */
  814.       if (ctx->Pixel.Convolution2DEnabled) {
  815.          _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage);
  816.       }
  817.       else {
  818.          ASSERT(ctx->Pixel.Separable2DEnabled);
  819.          _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage);
  820.       }
  821.       FREE(tmpImage);
  822.  
  823.       /* continue transfer ops and draw the convolved image */
  824.       unpack = &_mesa_native_packing;
  825.       pixels = convImage;
  826.       format = GL_RGBA;
  827.       type = GL_FLOAT;
  828.       transferOps &= IMAGE_POST_CONVOLUTION_BITS;
  829.    }
  830.  
  831.    /*
  832.     * General solution
  833.     */
  834.    {
  835.       GLint row, skipPixels = 0;
  836.  
  837.       /* if the span is wider than MAX_WIDTH we have to do it in chunks */
  838.       while (skipPixels < width) {
  839.          span.x = x + (zoom ? 0 : skipPixels);
  840.          span.y = y;
  841.          span.end = (width - skipPixels > MAX_WIDTH)
  842.                   ? MAX_WIDTH : (width - skipPixels);
  843.          ASSERT(span.end <= MAX_WIDTH);
  844.  
  845.          for (row = 0; row < height; row++, span.y++) {
  846.             const GLvoid *source = _mesa_image_address(unpack,
  847.                      pixels, width, height, format, type, 0, row, skipPixels);
  848.  
  849.             _mesa_unpack_chan_color_span(ctx, span.end, GL_RGBA,
  850.                                          (GLchan *) span.array->rgba,
  851.                                          format, type, source, unpack,
  852.                                          transferOps);
  853.  
  854.             if ((ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) ||
  855.                 (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink))
  856.                continue;
  857.  
  858.             if (ctx->Pixel.PixelTextureEnabled && ctx->Texture._EnabledUnits) {
  859.                _swrast_pixel_texture(ctx, &span);
  860.             }
  861.  
  862.             if (quickDraw) {
  863.                (*swrast->Driver.WriteRGBASpan)(ctx, span.end, span.x, span.y,
  864.                                  (CONST GLchan (*)[4]) span.array->rgba, NULL);
  865.             }
  866.             else if (zoom) {
  867.                _mesa_write_zoomed_rgba_span(ctx, &span,
  868.                     (CONST GLchan (*)[4]) span.array->rgba, desty, skipPixels);
  869.             }
  870.             else {
  871.                _mesa_write_rgba_span(ctx, &span);
  872.             }
  873.          }
  874.          skipPixels += span.end;
  875.       }
  876.    }
  877.  
  878.    if (convImage) {
  879.       FREE(convImage);
  880.    }
  881. }
  882.  
  883.  
  884.  
  885. /*
  886.  * Execute glDrawPixels
  887.  */
  888. void
  889. _swrast_DrawPixels( GLcontext *ctx,
  890.             GLint x, GLint y,
  891.             GLsizei width, GLsizei height,
  892.             GLenum format, GLenum type,
  893.             const struct gl_pixelstore_attrib *unpack,
  894.             const GLvoid *pixels )
  895. {
  896.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  897.    (void) unpack;
  898.  
  899.    if (swrast->NewState)
  900.       _swrast_validate_derived( ctx );
  901.  
  902.    RENDER_START(swrast,ctx);
  903.  
  904.    switch (format) {
  905.    case GL_STENCIL_INDEX:
  906.       draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
  907.       break;
  908.    case GL_DEPTH_COMPONENT:
  909.       draw_depth_pixels( ctx, x, y, width, height, type, pixels );
  910.       break;
  911.    case GL_COLOR_INDEX:
  912.       if (ctx->Visual.rgbMode)
  913.      draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
  914.       else
  915.      draw_index_pixels(ctx, x, y, width, height, type, pixels);
  916.       break;
  917.    case GL_RED:
  918.    case GL_GREEN:
  919.    case GL_BLUE:
  920.    case GL_ALPHA:
  921.    case GL_LUMINANCE:
  922.    case GL_LUMINANCE_ALPHA:
  923.    case GL_RGB:
  924.    case GL_BGR:
  925.    case GL_RGBA:
  926.    case GL_BGRA:
  927.    case GL_ABGR_EXT:
  928.       draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels);
  929.       break;
  930.    default:
  931.       _mesa_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" );
  932.    }
  933.  
  934.    RENDER_FINISH(swrast,ctx);
  935. }
  936.  
  937.  
  938.  
  939. #if 0  /* experimental */
  940. /*
  941.  * Execute glDrawDepthPixelsMESA().
  942.  */
  943. void
  944. _swrast_DrawDepthPixelsMESA( GLcontext *ctx,
  945.                              GLint x, GLint y,
  946.                              GLsizei width, GLsizei height,
  947.                              GLenum colorFormat, GLenum colorType,
  948.                              const GLvoid *colors,
  949.                              GLenum depthType, const GLvoid *depths,
  950.                              const struct gl_pixelstore_attrib *unpack )
  951. {
  952.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  953.    (void) unpack;
  954.  
  955.    if (swrast->NewState)
  956.       _swrast_validate_derived( ctx );
  957.  
  958.    RENDER_START(swrast,ctx);
  959.  
  960.    switch (colorFormat) {
  961.    case GL_COLOR_INDEX:
  962.       if (ctx->Visual.rgbMode)
  963.      draw_rgba_pixels(ctx, x,y, width, height, colorFormat, colorType, colors);
  964.       else
  965.      draw_index_pixels(ctx, x, y, width, height, colorType, colors);
  966.       break;
  967.    case GL_RED:
  968.    case GL_GREEN:
  969.    case GL_BLUE:
  970.    case GL_ALPHA:
  971.    case GL_LUMINANCE:
  972.    case GL_LUMINANCE_ALPHA:
  973.    case GL_RGB:
  974.    case GL_BGR:
  975.    case GL_RGBA:
  976.    case GL_BGRA:
  977.    case GL_ABGR_EXT:
  978.       draw_rgba_pixels(ctx, x, y, width, height, colorFormat, colorType, colors);
  979.       break;
  980.    default:
  981.       _mesa_error( ctx, GL_INVALID_ENUM,
  982.                    "glDrawDepthPixelsMESA(colorFormat)" );
  983.    }
  984.  
  985.    RENDER_FINISH(swrast,ctx);
  986. }
  987. #endif
  988.