home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / span.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  30KB  |  1,057 lines

  1. /* $Id: span.c,v 1.4 1999/11/08 15:28:08 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  * 
  7.  * Copyright (C) 1999  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.  
  29.  
  30.  
  31. /*
  32.  * pixel span rasterization:
  33.  * These functions simulate the rasterization pipeline.
  34.  */
  35.  
  36.  
  37. #ifdef PC_HEADER
  38. #include "all.h"
  39. #else
  40. #ifndef XFree86Server
  41. #include <assert.h>
  42. #include <string.h>
  43. #else
  44. #include "GL/xf86glx.h"
  45. #endif
  46. #include "alpha.h"
  47. #include "alphabuf.h"
  48. #include "blend.h"
  49. #include "depth.h"
  50. #include "fog.h"
  51. #include "logic.h"
  52. #include "macros.h"
  53. #include "masking.h"
  54. #include "scissor.h"
  55. #include "span.h"
  56. #include "stencil.h"
  57. #include "texture.h"
  58. #include "types.h"
  59. #endif
  60.  
  61.  
  62.  
  63.  
  64. /*
  65.  * Apply the current polygon stipple pattern to a span of pixels.
  66.  */
  67. static void stipple_polygon_span( GLcontext *ctx,
  68.                                   GLuint n, GLint x, GLint y, GLubyte mask[] )
  69. {
  70.    register GLuint i, m, stipple, highbit=0x80000000;
  71.  
  72.    stipple = ctx->PolygonStipple[y % 32];
  73.    m = highbit >> (GLuint) (x % 32);
  74.  
  75.    for (i=0;i<n;i++) {
  76.       if ((m & stipple)==0) {
  77.      mask[i] = 0;
  78.       }
  79.       m = m >> 1;
  80.       if (m==0) {
  81.      m = 0x80000000;
  82.       }
  83.    }
  84. }
  85.  
  86.  
  87.  
  88. /*
  89.  * Clip a pixel span to the current buffer/window boundaries.
  90.  * Return:  0 = all pixels clipped
  91.  *          1 = at least one pixel is visible
  92.  */
  93. static GLuint clip_span( GLcontext *ctx,
  94.                          GLint n, GLint x, GLint y, GLubyte mask[] )
  95. {
  96.    GLint i;
  97.  
  98.    /* Clip to top and bottom */
  99.    if (y<0 || y>=ctx->Buffer->Height) {
  100.       return 0;
  101.    }
  102.  
  103.    /* Clip to left and right */
  104.    if (x>=0 && x+n<=ctx->Buffer->Width) {
  105.       /* no clipping needed */
  106.       return 1;
  107.    }
  108.    else if (x+n<=0) {
  109.       /* completely off left side */
  110.       return 0;
  111.    }
  112.    else if (x>=ctx->Buffer->Width) {
  113.       /* completely off right side */
  114.       return 0;
  115.    }
  116.    else {
  117.       /* clip-test each pixel, this could be done better */
  118.       for (i=0;i<n;i++) {
  119.          if (x+i<0 || x+i>=ctx->Buffer->Width) {
  120.             mask[i] = 0;
  121.          }
  122.       }
  123.       return 1;
  124.    }
  125. }
  126.  
  127.  
  128.  
  129. /*
  130.  * Draw to more than one color buffer (or none).
  131.  */
  132. static void multi_write_index_span( GLcontext *ctx, GLuint n,
  133.                                     GLint x, GLint y, const GLuint indexes[],
  134.                                     const GLubyte mask[] )
  135. {
  136.    GLuint bufferBit;
  137.  
  138.    if (ctx->Color.DrawBuffer == GL_NONE)
  139.       return;
  140.  
  141.    /* loop over four possible dest color buffers */
  142.    for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
  143.       if (bufferBit & ctx->Color.DrawDestMask) {
  144.          GLuint indexTmp[MAX_WIDTH];
  145.          ASSERT(n < MAX_WIDTH);
  146.  
  147.          if (bufferBit == FRONT_LEFT_BIT)
  148.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_LEFT);
  149.          else if (bufferBit == FRONT_RIGHT_BIT)
  150.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_RIGHT);
  151.          else if (bufferBit == BACK_LEFT_BIT)
  152.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK_LEFT);
  153.          else
  154.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK_RIGHT);
  155.  
  156.          /* make copy of incoming indexes */
  157.          MEMCPY( indexTmp, indexes, n * sizeof(GLuint) );
  158.          if (ctx->Color.SWLogicOpEnabled) {
  159.             gl_logicop_ci_span( ctx, n, x, y, indexTmp, mask );
  160.          }
  161.          if (ctx->Color.SWmasking) {
  162.             gl_mask_index_span( ctx, n, x, y, indexTmp );
  163.          }
  164.          (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, indexTmp, mask );
  165.       }
  166.    }
  167.  
  168.    /* restore default dest buffer */
  169.    (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer);
  170. }
  171.  
  172.  
  173.  
  174. /*
  175.  * Write a horizontal span of color index pixels to the frame buffer.
  176.  * Stenciling, Depth-testing, etc. are done as needed.
  177.  * Input:  n - number of pixels in the span
  178.  *         x, y - location of leftmost pixel in the span
  179.  *         z - array of [n] z-values
  180.  *         index - array of [n] color indexes
  181.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
  182.  */
  183. void gl_write_index_span( GLcontext *ctx,
  184.                           GLuint n, GLint x, GLint y, const GLdepth z[],
  185.               GLuint indexIn[], GLenum primitive )
  186. {
  187.    GLubyte mask[MAX_WIDTH];
  188.    GLuint indexBackup[MAX_WIDTH];
  189.    GLuint *index;  /* points to indexIn or indexBackup */
  190.  
  191.    /* init mask to 1's (all pixels are to be written) */
  192.    MEMSET(mask, 1, n);
  193.  
  194.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  195.       if (clip_span(ctx,n,x,y,mask)==0) {
  196.      return;
  197.       }
  198.    }
  199.  
  200.    if ((primitive==GL_BITMAP && ctx->MutablePixels)
  201.        || (ctx->RasterMask & MULTI_DRAW_BIT)) {
  202.       /* Make copy of color indexes */
  203.       MEMCPY( indexBackup, indexIn, n * sizeof(GLuint) );
  204.       index = indexBackup;
  205.    }
  206.    else {
  207.       index = indexIn;
  208.    }
  209.  
  210.    /* Per-pixel fog */
  211.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode == FOG_FRAGMENT)) {
  212.       gl_fog_ci_pixels( ctx, n, z, index );
  213.    }
  214.  
  215.    /* Do the scissor test */
  216.    if (ctx->Scissor.Enabled) {
  217.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  218.      return;
  219.       }
  220.    }
  221.  
  222.    /* Polygon Stippling */
  223.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  224.       stipple_polygon_span( ctx, n, x, y, mask );
  225.    }
  226.  
  227.    if (ctx->Stencil.Enabled) {
  228.       /* first stencil test */
  229.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  230.      return;
  231.       }
  232.       /* depth buffering w/ stencil */
  233.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  234.    }
  235.    else if (ctx->Depth.Test) {
  236.       /* regular depth testing */
  237.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  238.    }
  239.  
  240.    if (ctx->RasterMask & MULTI_DRAW_BIT) {
  241.       /* draw to zero or two or more buffers */
  242.       multi_write_index_span( ctx, n, x, y, index, mask );
  243.    }
  244.    else {
  245.       /* normal situation: draw to exactly one buffer */
  246.       if (ctx->Color.SWLogicOpEnabled) {
  247.          gl_logicop_ci_span( ctx, n, x, y, index, mask );
  248.       }
  249.       if (ctx->Color.SWmasking) {
  250.          gl_mask_index_span( ctx, n, x, y, index );
  251.       }
  252.  
  253.       /* write pixels */
  254.       (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, index, mask );
  255.    }
  256. }
  257.  
  258.  
  259.  
  260.  
  261. void gl_write_monoindex_span( GLcontext *ctx,
  262.                               GLuint n, GLint x, GLint y, const GLdepth z[],
  263.                   GLuint index, GLenum primitive )
  264. {
  265.    GLubyte mask[MAX_WIDTH];
  266.    GLuint i;
  267.  
  268.    /* init mask to 1's (all pixels are to be written) */
  269.    MEMSET(mask, 1, n);
  270.  
  271.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  272.       if (clip_span( ctx, n, x, y, mask)==0) {
  273.      return;
  274.       }
  275.    }
  276.  
  277.    /* Do the scissor test */
  278.    if (ctx->Scissor.Enabled) {
  279.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  280.      return;
  281.       }
  282.    }
  283.  
  284.    /* Polygon Stippling */
  285.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  286.       stipple_polygon_span( ctx, n, x, y, mask );
  287.    }
  288.  
  289.    if (ctx->Stencil.Enabled) {
  290.       /* first stencil test */
  291.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  292.      return;
  293.       }
  294.       /* depth buffering w/ stencil */
  295.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  296.    }
  297.    else if (ctx->Depth.Test) {
  298.       /* regular depth testing */
  299.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  300.    }
  301.  
  302.    if (ctx->Color.DrawBuffer == GL_NONE) {
  303.       /* write no pixels */
  304.       return;
  305.    }
  306.  
  307.    if ((ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT))
  308.         || ctx->Color.SWLogicOpEnabled || ctx->Color.SWmasking) {
  309.       /* different index per pixel */
  310.       GLuint indexes[MAX_WIDTH];
  311.       for (i=0;i<n;i++) {
  312.      indexes[i] = index;
  313.       }
  314.  
  315.       if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  316.      gl_fog_ci_pixels( ctx, n, z, indexes );
  317.       }
  318.  
  319.       if (ctx->Color.SWLogicOpEnabled) {
  320.      gl_logicop_ci_span( ctx, n, x, y, indexes, mask );
  321.       }
  322.  
  323.       if (ctx->Color.SWmasking) {
  324.          gl_mask_index_span( ctx, n, x, y, indexes );
  325.       }
  326.  
  327.       if (ctx->RasterMask & MULTI_DRAW_BIT) {
  328.          /* draw to zero or two or more buffers */
  329.          multi_write_index_span( ctx, n, x, y, indexes, mask );
  330.       }
  331.       else {
  332.          /* normal situation: draw to exactly one buffer */
  333.          if (ctx->Color.SWLogicOpEnabled) {
  334.             gl_logicop_ci_span( ctx, n, x, y, indexes, mask );
  335.          }
  336.          if (ctx->Color.SWmasking) {
  337.             gl_mask_index_span( ctx, n, x, y, indexes );
  338.          }
  339.          (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, indexes, mask );
  340.       }
  341.    }
  342.    else {
  343.       /* same color index for all pixels */
  344.       ASSERT(!ctx->Color.SWLogicOpEnabled);
  345.       ASSERT(!ctx->Color.SWmasking);
  346.       if (ctx->RasterMask & MULTI_DRAW_BIT) {
  347.          /* draw to zero or two or more buffers */
  348.          GLuint indexes[MAX_WIDTH];
  349.          for (i=0;i<n;i++)
  350.             indexes[i] = index;
  351.          multi_write_index_span( ctx, n, x, y, indexes, mask );
  352.       }
  353.       else {
  354.          /* normal situation: draw to exactly one buffer */
  355.          (*ctx->Driver.WriteMonoCISpan)( ctx, n, x, y, mask );
  356.       }
  357.    }
  358. }
  359.  
  360.  
  361.  
  362. /*
  363.  * Draw to more than one RGBA color buffer (or none).
  364.  */
  365. static void multi_write_rgba_span( GLcontext *ctx, GLuint n,
  366.                                    GLint x, GLint y, CONST GLubyte rgba[][4],
  367.                                    const GLubyte mask[] )
  368. {
  369.    GLuint bufferBit;
  370.  
  371.    if (ctx->Color.DrawBuffer == GL_NONE)
  372.       return;
  373.  
  374.    /* loop over four possible dest color buffers */
  375.    for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
  376.       if (bufferBit & ctx->Color.DrawDestMask) {
  377.          GLubyte rgbaTmp[MAX_WIDTH][4];
  378.          ASSERT(n < MAX_WIDTH);
  379.  
  380.          if (bufferBit == FRONT_LEFT_BIT) {
  381.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_LEFT);
  382.             ctx->Buffer->Alpha = ctx->Buffer->FrontLeftAlpha;
  383.          }
  384.          else if (bufferBit == FRONT_RIGHT_BIT) {
  385.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT_RIGHT);
  386.             ctx->Buffer->Alpha = ctx->Buffer->FrontRightAlpha;
  387.          }
  388.          else if (bufferBit == BACK_LEFT_BIT) {
  389.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK_LEFT);
  390.             ctx->Buffer->Alpha = ctx->Buffer->BackLeftAlpha;
  391.          }
  392.          else {
  393.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK_RIGHT);
  394.             ctx->Buffer->Alpha = ctx->Buffer->BackRightAlpha;
  395.          }
  396.  
  397.          /* make copy of incoming colors */
  398.          MEMCPY( rgbaTmp, rgba, 4 * n * sizeof(GLubyte) );
  399.  
  400.          if (ctx->Color.SWLogicOpEnabled) {
  401.             gl_logicop_rgba_span( ctx, n, x, y, rgbaTmp, mask );
  402.          }
  403.          else if (ctx->Color.BlendEnabled) {
  404.             gl_blend_span( ctx, n, x, y, rgbaTmp, mask );
  405.          }
  406.          if (ctx->Color.SWmasking) {
  407.             gl_mask_rgba_span( ctx, n, x, y, rgbaTmp );
  408.          }
  409.  
  410.          (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, 
  411.                        (const GLubyte (*)[4]) rgbaTmp, mask );
  412.          if (ctx->RasterMask & ALPHABUF_BIT) {
  413.             gl_write_alpha_span( ctx, n, x, y, 
  414.                  (const GLubyte (*)[4])rgbaTmp, mask );
  415.          }
  416.       }
  417.    }
  418.  
  419.    /* restore default dest buffer */
  420.    (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
  421. }
  422.  
  423.  
  424.  
  425. void gl_write_rgba_span( GLcontext *ctx,
  426.                          GLuint n, GLint x, GLint y, const GLdepth z[],
  427.                          GLubyte rgbaIn[][4],
  428.                          GLenum primitive )
  429. {
  430.    GLubyte mask[MAX_WIDTH];
  431.    GLboolean write_all = GL_TRUE;
  432.    GLubyte rgbaBackup[MAX_WIDTH][4];
  433.    GLubyte (*rgba)[4];
  434.    const GLubyte *Null = 0;
  435.  
  436.    /* init mask to 1's (all pixels are to be written) */
  437.    MEMSET(mask, 1, n);
  438.  
  439.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  440.       if (clip_span( ctx,n,x,y,mask)==0) {
  441.      return;
  442.       }
  443.       write_all = GL_FALSE;
  444.    }
  445.  
  446.    if ((primitive==GL_BITMAP && ctx->MutablePixels)
  447.        || (ctx->RasterMask & MULTI_DRAW_BIT)) {
  448.       /* must make a copy of the colors since they may be modified */
  449.       MEMCPY( rgbaBackup, rgbaIn, 4 * n * sizeof(GLubyte) );
  450.       rgba = rgbaBackup;
  451.    }
  452.    else {
  453.       rgba = rgbaIn;
  454.    }
  455.  
  456.    /* Per-pixel fog */
  457.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  458.       gl_fog_rgba_pixels( ctx, n, z, rgba );
  459.    }
  460.  
  461.    /* Do the scissor test */
  462.    if (ctx->Scissor.Enabled) {
  463.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  464.      return;
  465.       }
  466.       write_all = GL_FALSE;
  467.    }
  468.  
  469.    /* Polygon Stippling */
  470.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  471.       stipple_polygon_span( ctx, n, x, y, mask );
  472.       write_all = GL_FALSE;
  473.    }
  474.  
  475.    /* Do the alpha test */
  476.    if (ctx->Color.AlphaEnabled) {
  477.       if (gl_alpha_test( ctx, n, (const GLubyte (*)[4]) rgba, mask )==0) {
  478.      return;
  479.       }
  480.       write_all = GL_FALSE;
  481.    }
  482.  
  483.    if (ctx->Stencil.Enabled) {
  484.       /* first stencil test */
  485.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  486.      return;
  487.       }
  488.       /* depth buffering w/ stencil */
  489.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  490.       write_all = GL_FALSE;
  491.    }
  492.    else if (ctx->Depth.Test) {
  493.       /* regular depth testing */
  494.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  495.       if (m==0) {
  496.          return;
  497.       }
  498.       if (m<n) {
  499.          write_all = GL_FALSE;
  500.       }
  501.    }
  502.  
  503.    if (ctx->RasterMask & MULTI_DRAW_BIT) {
  504.       multi_write_rgba_span( ctx, n, x, y,
  505.                  (const GLubyte (*)[4]) rgba, 
  506.                  write_all ? Null : mask );
  507.    }
  508.    else {
  509.       /* normal: write to exactly one buffer */
  510.       /* logic op or blending */
  511.       if (ctx->Color.SWLogicOpEnabled) {
  512.          gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  513.       }
  514.       else if (ctx->Color.BlendEnabled) {
  515.          gl_blend_span( ctx, n, x, y, rgba, mask );
  516.       }
  517.  
  518.       /* Color component masking */
  519.       if (ctx->Color.SWmasking) {
  520.          gl_mask_rgba_span( ctx, n, x, y, rgba );
  521.       }
  522.  
  523.       /* write pixels */
  524.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, 
  525.                     (const GLubyte (*)[4]) rgba, 
  526.                     write_all ? Null : mask );
  527.  
  528.       if (ctx->RasterMask & ALPHABUF_BIT) {
  529.          gl_write_alpha_span( ctx, n, x, y, 
  530.                   (const GLubyte (*)[4]) rgba, 
  531.                   write_all ? Null : mask );
  532.       }
  533.  
  534.    }
  535. }
  536.  
  537.  
  538.  
  539. /*
  540.  * Write a horizontal span of color pixels to the frame buffer.
  541.  * The color is initially constant for the whole span.
  542.  * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
  543.  * Input:  n - number of pixels in the span
  544.  *         x, y - location of leftmost pixel in the span
  545.  *         z - array of [n] z-values
  546.  *         r, g, b, a - the color of the pixels
  547.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  548.  */
  549. void gl_write_monocolor_span( GLcontext *ctx,
  550.                               GLuint n, GLint x, GLint y, const GLdepth z[],
  551.                   const GLubyte color[4],
  552.                               GLenum primitive )
  553. {
  554.    GLuint i;
  555.    GLubyte mask[MAX_WIDTH];
  556.    GLboolean write_all = GL_TRUE;
  557.    GLubyte rgba[MAX_WIDTH][4];
  558.    const GLubyte *Null = 0;
  559.  
  560.    /* init mask to 1's (all pixels are to be written) */
  561.    MEMSET(mask, 1, n);
  562.  
  563.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  564.       if (clip_span( ctx,n,x,y,mask)==0) {
  565.      return;
  566.       }
  567.       write_all = GL_FALSE;
  568.    }
  569.  
  570.    /* Do the scissor test */
  571.    if (ctx->Scissor.Enabled) {
  572.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  573.      return;
  574.       }
  575.       write_all = GL_FALSE;
  576.    }
  577.  
  578.    /* Polygon Stippling */
  579.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  580.       stipple_polygon_span( ctx, n, x, y, mask );
  581.       write_all = GL_FALSE;
  582.    }
  583.  
  584.    /* Do the alpha test */
  585.    if (ctx->Color.AlphaEnabled) {
  586.       for (i=0;i<n;i++) {
  587.          rgba[i][ACOMP] = color[ACOMP];
  588.       }
  589.       if (gl_alpha_test( ctx, n, (const GLubyte (*)[4])rgba, mask )==0) {
  590.      return;
  591.       }
  592.       write_all = GL_FALSE;
  593.    }
  594.  
  595.    if (ctx->Stencil.Enabled) {
  596.       /* first stencil test */
  597.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  598.      return;
  599.       }
  600.       /* depth buffering w/ stencil */
  601.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  602.       write_all = GL_FALSE;
  603.    }
  604.    else if (ctx->Depth.Test) {
  605.       /* regular depth testing */
  606.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  607.       if (m==0) {
  608.          return;
  609.       }
  610.       if (m<n) {
  611.          write_all = GL_FALSE;
  612.       }
  613.    }
  614.  
  615.    if (ctx->Color.DrawBuffer == GL_NONE) {
  616.       /* write no pixels */
  617.       return;
  618.    }
  619.  
  620.    if (ctx->Color.BlendEnabled || ctx->Color.SWLogicOpEnabled
  621.        || ctx->Color.SWmasking) {
  622.       /* assign same color to each pixel */
  623.       for (i=0;i<n;i++) {
  624.      if (mask[i]) {
  625.             COPY_4UBV(rgba[i], color);
  626.      }
  627.       }
  628.  
  629.       if (ctx->RasterMask & MULTI_DRAW_BIT) {
  630.          multi_write_rgba_span( ctx, n, x, y, (const GLubyte (*)[4]) rgba,
  631.                 mask );
  632.       }
  633.       else {
  634.          /* normal: write to exactly one buffer */
  635.          if (ctx->Color.SWLogicOpEnabled) {
  636.             gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  637.          }
  638.          else if (ctx->Color.BlendEnabled) {
  639.             gl_blend_span( ctx, n, x, y, rgba, mask );
  640.          }
  641.  
  642.          /* Color component masking */
  643.          if (ctx->Color.SWmasking) {
  644.             gl_mask_rgba_span( ctx, n, x, y, rgba );
  645.          }
  646.  
  647.          /* write pixels */
  648.          (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, 
  649.                        (const GLubyte (*)[4]) rgba, 
  650.                        write_all ? Null : mask );
  651.          if (ctx->RasterMask & ALPHABUF_BIT) {
  652.             gl_write_alpha_span( ctx, n, x, y, 
  653.                  (const GLubyte (*)[4]) rgba, 
  654.                  write_all ? Null : mask );
  655.          }
  656.       }
  657.    }
  658.    else {
  659.       /* same color for all pixels */
  660.       ASSERT(!ctx->Color.BlendEnabled);
  661.       ASSERT(!ctx->Color.SWLogicOpEnabled);
  662.       ASSERT(!ctx->Color.SWmasking);
  663.  
  664.       if (ctx->RasterMask & MULTI_DRAW_BIT) {
  665.          for (i=0;i<n;i++) {
  666.             if (mask[i]) {
  667.                COPY_4UBV(rgba[i], color);
  668.             }
  669.          }
  670.          multi_write_rgba_span( ctx, n, x, y, 
  671.                 (const GLubyte (*)[4]) rgba, 
  672.                 mask );
  673.       }
  674.       else {
  675.          (*ctx->Driver.WriteMonoRGBASpan)( ctx, n, x, y, mask );
  676.          if (ctx->RasterMask & ALPHABUF_BIT) {
  677.             gl_write_mono_alpha_span( ctx, n, x, y, (GLubyte) color[ACOMP],
  678.                                       write_all ? Null : mask );
  679.          }
  680.       }
  681.    }
  682. }
  683.  
  684.  
  685.  
  686. /*
  687.  * Add specular color to base color.  This is used only when
  688.  * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
  689.  */
  690. static void add_colors(GLuint n, GLubyte rgba[][4], CONST GLubyte specular[][4] )
  691. {
  692.    GLuint i;
  693.    for (i=0; i<n; i++) {
  694.       GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
  695.       GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
  696.       GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
  697.       rgba[i][RCOMP] = (GLubyte) MIN2(r, 255);
  698.       rgba[i][GCOMP] = (GLubyte) MIN2(g, 255);
  699.       rgba[i][BCOMP] = (GLubyte) MIN2(b, 255);
  700.    }
  701. }
  702.  
  703.  
  704. /*
  705.  * Write a horizontal span of textured pixels to the frame buffer.
  706.  * The color of each pixel is different.
  707.  * Alpha-testing, stenciling, depth-testing, and blending are done
  708.  * as needed.
  709.  * Input:  n - number of pixels in the span
  710.  *         x, y - location of leftmost pixel in the span
  711.  *         z - array of [n] z-values
  712.  *         s, t - array of (s,t) texture coordinates for each pixel
  713.  *         lambda - array of texture lambda values
  714.  *         rgba - array of [n] color components
  715.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  716.  */
  717. void gl_write_texture_span( GLcontext *ctx,
  718.                             GLuint n, GLint x, GLint y, const GLdepth z[],
  719.                 const GLfloat s[], const GLfloat t[],
  720.                             const GLfloat u[], GLfloat lambda[],
  721.                 GLubyte rgbaIn[][4], CONST GLubyte spec[][4],
  722.                 GLenum primitive )
  723. {
  724.    GLubyte mask[MAX_WIDTH];
  725.    GLboolean write_all = GL_TRUE;
  726.    GLubyte rgbaBackup[MAX_WIDTH][4];
  727.    GLubyte (*rgba)[4];   /* points to either rgbaIn or rgbaBackup */
  728.    const GLubyte *Null = 0;
  729.  
  730.    /* init mask to 1's (all pixels are to be written) */
  731.    MEMSET(mask, 1, n);
  732.  
  733.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  734.       if (clip_span(ctx, n, x, y, mask)==0) {
  735.      return;
  736.       }
  737.       write_all = GL_FALSE;
  738.    }
  739.  
  740.  
  741.    if (primitive==GL_BITMAP || (ctx->RasterMask & MULTI_DRAW_BIT)) {
  742.       /* must make a copy of the colors since they may be modified */
  743.       MEMCPY(rgbaBackup, rgbaIn, 4 * sizeof(GLubyte));
  744.       rgba = rgbaBackup;
  745.    }
  746.    else {
  747.       rgba = rgbaIn;
  748.    }
  749.  
  750.    /* Texture */
  751.    ASSERT(ctx->Texture.Enabled);
  752.    gl_texture_pixels( ctx, 0, n, s, t, u, lambda, rgba );
  753.  
  754.    /* Add base and specular colors */
  755.    if (spec && ctx->Light.Enabled
  756.        && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
  757.       add_colors( n, rgba, spec );   /* rgba = rgba + spec */
  758.  
  759.    /* Per-pixel fog */
  760.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  761.       gl_fog_rgba_pixels( ctx, n, z, rgba );
  762.    }
  763.  
  764.    /* Do the scissor test */
  765.    if (ctx->Scissor.Enabled) {
  766.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  767.      return;
  768.       }
  769.       write_all = GL_FALSE;
  770.    }
  771.  
  772.    /* Polygon Stippling */
  773.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  774.       stipple_polygon_span( ctx, n, x, y, mask );
  775.       write_all = GL_FALSE;
  776.    }
  777.  
  778.    /* Do the alpha test */
  779.    if (ctx->Color.AlphaEnabled) {
  780.       if (gl_alpha_test( ctx, n, (const GLubyte (*)[4]) rgba, mask )==0) {
  781.      return;
  782.       }
  783.       write_all = GL_FALSE;
  784.    }
  785.  
  786.    if (ctx->Stencil.Enabled) {
  787.       /* first stencil test */
  788.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  789.      return;
  790.       }
  791.       /* depth buffering w/ stencil */
  792.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  793.       write_all = GL_FALSE;
  794.    }
  795.    else if (ctx->Depth.Test) {
  796.       /* regular depth testing */
  797.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  798.       if (m==0) {
  799.          return;
  800.       }
  801.       if (m<n) {
  802.          write_all = GL_FALSE;
  803.       }
  804.    }
  805.  
  806.    if (ctx->RasterMask & MULTI_DRAW_BIT) {
  807.       multi_write_rgba_span( ctx, n, x, y, (const GLubyte (*)[4])rgba, 
  808.                  write_all ? Null : mask );
  809.    }
  810.    else {
  811.       /* normal: write to exactly one buffer */
  812.       if (ctx->Color.SWLogicOpEnabled) {
  813.          gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  814.       }
  815.       else  if (ctx->Color.BlendEnabled) {
  816.          gl_blend_span( ctx, n, x, y, rgba, mask );
  817.       }
  818.       if (ctx->Color.SWmasking) {
  819.          gl_mask_rgba_span( ctx, n, x, y, rgba );
  820.       }
  821.  
  822.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLubyte (*)[4])rgba,
  823.                     write_all ? Null : mask );
  824.       if (ctx->RasterMask & ALPHABUF_BIT) {
  825.          gl_write_alpha_span( ctx, n, x, y, (const GLubyte (*)[4]) rgba, 
  826.                   write_all ? Null : mask );
  827.       }
  828.    }
  829. }
  830.  
  831.  
  832.  
  833. /*
  834.  * As above but perform multiple stages of texture application.
  835.  * Input:  texUnits - number of texture units to apply
  836.  */
  837. void gl_write_multitexture_span( GLcontext *ctx, GLuint texUnits,
  838.                                  GLuint n, GLint x, GLint y,
  839.                                  const GLdepth z[],
  840.                                  CONST GLfloat s[][MAX_WIDTH],
  841.                                  CONST GLfloat t[][MAX_WIDTH],
  842.                                  CONST GLfloat u[][MAX_WIDTH],
  843.                                  GLfloat lambda[][MAX_WIDTH],
  844.                                  GLubyte rgbaIn[][4], CONST GLubyte spec[][4],
  845.                                  GLenum primitive )
  846. {
  847.    GLubyte mask[MAX_WIDTH];
  848.    GLboolean write_all = GL_TRUE;
  849.    GLubyte rgbaBackup[MAX_WIDTH][4];
  850.    GLubyte (*rgba)[4];   /* points to either rgbaIn or rgbaBackup */
  851.    GLuint i;
  852.    const GLubyte *Null = 0;
  853.  
  854.    /* init mask to 1's (all pixels are to be written) */
  855.    MEMSET(mask, 1, n);
  856.  
  857.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  858.       if (clip_span(ctx, n, x, y, mask)==0) {
  859.      return;
  860.       }
  861.       write_all = GL_FALSE;
  862.    }
  863.  
  864.  
  865.    if (primitive==GL_BITMAP || (ctx->RasterMask & MULTI_DRAW_BIT)) {
  866.       /* must make a copy of the colors since they may be modified */
  867.       MEMCPY(rgbaBackup, rgbaIn, 4 * sizeof(GLubyte));
  868.       rgba = rgbaBackup;
  869.    }
  870.    else {
  871.       rgba = rgbaIn;
  872.    }
  873.  
  874.    /* Texture */
  875.    ASSERT(ctx->Texture.Enabled);
  876.    ASSERT(texUnits <= MAX_TEXTURE_UNITS);
  877.    for (i=0;i<texUnits;i++) {
  878.       gl_texture_pixels( ctx, i, n, s[i], t[i], u[i], lambda[i], rgba );
  879.    }
  880.  
  881.    /* Add base and specular colors */
  882.    if (spec && ctx->Light.Enabled
  883.        && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
  884.       add_colors( n, rgba, spec );   /* rgba = rgba + spec */
  885.  
  886.    /* Per-pixel fog */
  887.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  888.       gl_fog_rgba_pixels( ctx, n, z, rgba );
  889.    }
  890.  
  891.    /* Do the scissor test */
  892.    if (ctx->Scissor.Enabled) {
  893.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  894.      return;
  895.       }
  896.       write_all = GL_FALSE;
  897.    }
  898.  
  899.    /* Polygon Stippling */
  900.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  901.       stipple_polygon_span( ctx, n, x, y, mask );
  902.       write_all = GL_FALSE;
  903.    }
  904.  
  905.    /* Do the alpha test */
  906.    if (ctx->Color.AlphaEnabled) {
  907.       if (gl_alpha_test( ctx, n, (const GLubyte (*)[4])rgba, mask )==0) {
  908.      return;
  909.       }
  910.       write_all = GL_FALSE;
  911.    }
  912.  
  913.    if (ctx->Stencil.Enabled) {
  914.       /* first stencil test */
  915.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  916.      return;
  917.       }
  918.       /* depth buffering w/ stencil */
  919.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  920.       write_all = GL_FALSE;
  921.    }
  922.    else if (ctx->Depth.Test) {
  923.       /* regular depth testing */
  924.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  925.       if (m==0) {
  926.          return;
  927.       }
  928.       if (m<n) {
  929.          write_all = GL_FALSE;
  930.       }
  931.    }
  932.  
  933.    if (ctx->RasterMask & MULTI_DRAW_BIT) {
  934.       multi_write_rgba_span( ctx, n, x, y, (const GLubyte (*)[4]) rgba, write_all ? Null : mask );
  935.    }
  936.    else {
  937.       /* normal: write to exactly one buffer */
  938.  
  939.       if (ctx->Color.SWLogicOpEnabled) {
  940.          gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  941.       }
  942.       else  if (ctx->Color.BlendEnabled) {
  943.          gl_blend_span( ctx, n, x, y, rgba, mask );
  944.       }
  945.       if (ctx->Color.SWmasking) {
  946.          gl_mask_rgba_span( ctx, n, x, y, rgba );
  947.       }
  948.  
  949.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, (const GLubyte (*)[4])rgba, write_all ? Null : mask );
  950.       if (ctx->RasterMask & ALPHABUF_BIT) {
  951.          gl_write_alpha_span( ctx, n, x, y, (const GLubyte (*)[4])rgba,
  952.                   write_all ? Null : mask );
  953.       }
  954.    }
  955. }
  956.  
  957.  
  958.  
  959. /*
  960.  * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
  961.  * reading ouside the buffer's boundaries.
  962.  */
  963. void gl_read_rgba_span( GLcontext *ctx,
  964.                         GLuint n, GLint x, GLint y,
  965.                         GLubyte rgba[][4] )
  966. {
  967.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  968.       /* completely above, below, or right */
  969.       MEMSET( rgba, 0, 4 * n * sizeof(GLubyte)); /*XXX maybe leave undefined?*/
  970.    }
  971.    else {
  972.       GLint skip, length;
  973.       if (x < 0) {
  974.          /* left edge clippping */
  975.          skip = -x;
  976.          length = (GLint) n - skip;
  977.          if (length < 0) {
  978.             /* completely left of window */
  979.             return;
  980.          }
  981.          if (length > ctx->Buffer->Width) {
  982.             length = ctx->Buffer->Width;
  983.          }
  984.       }
  985.       else if ((GLint) (x + n) > ctx->Buffer->Width) {
  986.          /* right edge clipping */
  987.          skip = 0;
  988.          length = ctx->Buffer->Width - x;
  989.          if (length < 0) {
  990.             /* completely to right of window */
  991.             return;
  992.          }
  993.       }
  994.       else {
  995.          /* no clipping */
  996.          skip = 0;
  997.          length = (GLint) n;
  998.       }
  999.  
  1000.       (*ctx->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
  1001.       if (ctx->Visual->SoftwareAlpha) {
  1002.          gl_read_alpha_span( ctx, length, x + skip, y, rgba + skip );
  1003.       }
  1004.    }
  1005. }
  1006.  
  1007.  
  1008.  
  1009.  
  1010. /*
  1011.  * Read CI pixels from frame buffer.  Clipping will be done to prevent
  1012.  * reading ouside the buffer's boundaries.
  1013.  */
  1014. void gl_read_index_span( GLcontext *ctx,
  1015.                          GLuint n, GLint x, GLint y, GLuint indx[] )
  1016. {
  1017.    register GLuint i;
  1018.  
  1019.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  1020.       /* completely above, below, or right */
  1021.       for (i=0;i<n;i++) {
  1022.      indx[i] = 0;
  1023.       }
  1024.    }
  1025.    else {
  1026.       GLint skip, length;
  1027.       if (x < 0) {
  1028.          /* left edge clippping */
  1029.          skip = -x;
  1030.          length = (GLint) n - skip;
  1031.          if (length < 0) {
  1032.             /* completely left of window */
  1033.             return;
  1034.          }
  1035.          if (length > ctx->Buffer->Width) {
  1036.             length = ctx->Buffer->Width;
  1037.          }
  1038.       }
  1039.       else if ((GLint) (x + n) > ctx->Buffer->Width) {
  1040.          /* right edge clipping */
  1041.          skip = 0;
  1042.          length = ctx->Buffer->Width - x;
  1043.          if (length < 0) {
  1044.             /* completely to right of window */
  1045.             return;
  1046.          }
  1047.       }
  1048.       else {
  1049.          /* no clipping */
  1050.          skip = 0;
  1051.          length = (GLint) n;
  1052.       }
  1053.  
  1054.       (*ctx->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
  1055.    }
  1056. }
  1057.