home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / span.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  24.2 KB  |  911 lines

  1. /* $Id: span.c,v 1.12 1997/08/14 01:12:37 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.4
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: span.c,v $
  26.  * Revision 1.12  1997/08/14 01:12:37  brianp
  27.  * replaced a few for loops with MEMSET calls
  28.  *
  29.  * Revision 1.11  1997/07/24 01:21:56  brianp
  30.  * changed precompiled header symbol from PCH to PC_HEADER
  31.  *
  32.  * Revision 1.10  1997/05/28 03:26:29  brianp
  33.  * added precompiled header (PCH) support
  34.  *
  35.  * Revision 1.9  1997/05/03 00:51:30  brianp
  36.  * new texturing function call: gl_texture_pixels()
  37.  *
  38.  * Revision 1.8  1997/04/16 23:54:11  brianp
  39.  * do per-pixel fog if texturing is enabled
  40.  *
  41.  * Revision 1.7  1997/02/09 19:53:43  brianp
  42.  * now use TEXTURE_xD enable constants
  43.  *
  44.  * Revision 1.6  1997/02/09 18:43:34  brianp
  45.  * added GL_EXT_texture3D support
  46.  *
  47.  * Revision 1.5  1997/01/28 22:17:44  brianp
  48.  * new RGBA mode logic op support
  49.  *
  50.  * Revision 1.4  1996/09/25 03:22:05  brianp
  51.  * added NO_DRAW_BIT support
  52.  *
  53.  * Revision 1.3  1996/09/15 14:18:55  brianp
  54.  * now use GLframebuffer and GLvisual
  55.  *
  56.  * Revision 1.2  1996/09/15 01:48:58  brianp
  57.  * removed #define NULL 0
  58.  *
  59.  * Revision 1.1  1996/09/13 01:38:16  brianp
  60.  * Initial revision
  61.  *
  62.  */
  63.  
  64.  
  65. /*
  66.  * pixel span rasterization:
  67.  * These functions simulate the rasterization pipeline.
  68.  */
  69.  
  70.  
  71. #ifdef PC_HEADER
  72. #include "all.h"
  73. #else
  74. #include <string.h>
  75. #include "alpha.h"
  76. #include "alphabuf.h"
  77. #include "blend.h"
  78. #include "depth.h"
  79. #include "fog.h"
  80. #include "logic.h"
  81. #include "macros.h"
  82. #include "masking.h"
  83. #include "scissor.h"
  84. #include "span.h"
  85. #include "stencil.h"
  86. #include "texture.h"
  87. #include "types.h"
  88. #endif
  89.  
  90.  
  91.  
  92.  
  93. /*
  94.  * Apply the current polygon stipple pattern to a span of pixels.
  95.  */
  96. static void stipple_polygon_span( GLcontext *ctx,
  97.                   GLuint n, GLint x, GLint y, GLubyte mask[] )
  98. {
  99.    register GLuint i, m, stipple, highbit=0x80000000;
  100.  
  101.    stipple = ctx->PolygonStipple[y % 32];
  102.    m = highbit >> (GLuint) (x % 32);
  103.  
  104.    for (i=0;i<n;i++) {
  105.       if ((m & stipple)==0) {
  106.      mask[i] = 0;
  107.       }
  108.       m = m >> 1;
  109.       if (m==0) {
  110.      m = 0x80000000;
  111.       }
  112.    }
  113. }
  114.  
  115.  
  116.  
  117. /*
  118.  * Clip a pixel span to the current buffer/window boundaries.
  119.  * Return:  0 = all pixels clipped
  120.  *          1 = at least one pixel is visible
  121.  */
  122. static GLuint clip_span( GLcontext *ctx,
  123.              GLint n, GLint x, GLint y, GLubyte mask[] )
  124. {
  125.    GLint i;
  126.  
  127.    /* Clip to top and bottom */
  128.    if (y<0 || y>=ctx->Buffer->Height) {
  129.       return 0;
  130.    }
  131.  
  132.    /* Clip to left and right */
  133.    if (x>=0 && x+n<=ctx->Buffer->Width) {
  134.       /* no clipping needed */
  135.       return 1;
  136.    }
  137.    else if (x+n<=0) {
  138.       /* completely off left side */
  139.       return 0;
  140.    }
  141.    else if (x>=ctx->Buffer->Width) {
  142.       /* completely off right side */
  143.       return 0;
  144.    }
  145.    else {
  146.       /* clip-test each pixel, this could be done better */
  147.       for (i=0;i<n;i++) {
  148.      if (x+i<0 || x+i>=ctx->Buffer->Width) {
  149.         mask[i] = 0;
  150.      }
  151.       }
  152.       return 1;
  153.    }
  154. }
  155.  
  156.  
  157.  
  158. /*
  159.  * Write a horizontal span of color index pixels to the frame buffer.
  160.  * Stenciling, Depth-testing, etc. are done as needed.
  161.  * Input:  n - number of pixels in the span
  162.  *         x, y - location of leftmost pixel in the span
  163.  *         z - array of [n] z-values
  164.  *         index - array of [n] color indexes
  165.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
  166.  */
  167. void gl_write_index_span( GLcontext *ctx,
  168.               GLuint n, GLint x, GLint y, GLdepth z[],
  169.               GLuint index[], GLenum primitive )
  170. {
  171.    GLubyte mask[MAX_WIDTH];
  172.    GLuint index_save[MAX_WIDTH];
  173.  
  174.    /* init mask to 1's (all pixels are to be written) */
  175.    MEMSET(mask, 1, n);
  176.  
  177.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  178.       if (clip_span(ctx,n,x,y,mask)==0) {
  179.      return;
  180.       }
  181.    }
  182.  
  183.    /* Per-pixel fog */
  184.    if (ctx->Fog.Enabled
  185.        && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  186.       gl_fog_index_pixels( ctx, n, z, index );
  187.    }
  188.  
  189.    /* Do the scissor test */
  190.    if (ctx->Scissor.Enabled) {
  191.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  192.      return;
  193.       }
  194.    }
  195.  
  196.    /* Polygon Stippling */
  197.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  198.       stipple_polygon_span( ctx, n, x, y, mask );
  199.    }
  200.  
  201.    if (ctx->Stencil.Enabled) {
  202.       /* first stencil test */
  203.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  204.      return;
  205.       }
  206.       /* depth buffering w/ stencil */
  207.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  208.    }
  209.    else if (ctx->Depth.Test) {
  210.       /* regular depth testing */
  211.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  212.    }
  213.  
  214.    if (ctx->RasterMask & NO_DRAW_BIT) {
  215.       /* write no pixels */
  216.       return;
  217.    }
  218.  
  219.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  220.       /* Save a copy of the indexes since LogicOp and IndexMask
  221.        * may change them
  222.        */
  223.       MEMCPY( index_save, index, n * sizeof(GLuint) );
  224.    }
  225.  
  226.    if (ctx->Color.SWLogicOpEnabled) {
  227.       gl_logicop_ci_span( ctx, n, x, y, index, mask );
  228.    }
  229.    if (ctx->Color.SWmasking) {
  230.       gl_mask_index_span( ctx, n, x, y, index );
  231.    }
  232.  
  233.    /* write pixels */
  234.    (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, index, mask );
  235.  
  236.  
  237.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  238.       /*** Also draw to back buffer ***/
  239.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  240.       MEMCPY( index, index_save, n * sizeof(GLuint) );
  241.       if (ctx->Color.SWLogicOpEnabled) {
  242.      gl_logicop_ci_span( ctx, n, x, y, index, mask );
  243.       }
  244.       if (ctx->Color.SWmasking) {
  245.      gl_mask_index_span( ctx, n, x, y, index );
  246.       }
  247.       (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, index, mask );
  248.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  249.    }
  250. }
  251.  
  252.  
  253.  
  254.  
  255. void gl_write_monoindex_span( GLcontext *ctx,
  256.                   GLuint n, GLint x, GLint y, GLdepth z[],
  257.                   GLuint index, GLenum primitive )
  258. {
  259.    GLuint i;
  260.    GLubyte mask[MAX_WIDTH];
  261.    GLuint index_save[MAX_WIDTH];
  262.  
  263.    /* init mask to 1's (all pixels are to be written) */
  264.    MEMSET(mask, 1, n);
  265.  
  266.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  267.       if (clip_span( ctx,n,x,y,mask)==0) {
  268.      return;
  269.       }
  270.    }
  271.  
  272.    /* Do the scissor test */
  273.    if (ctx->Scissor.Enabled) {
  274.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  275.      return;
  276.       }
  277.    }
  278.  
  279.    /* Polygon Stippling */
  280.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  281.       stipple_polygon_span( ctx, n, x, y, mask );
  282.    }
  283.  
  284.    if (ctx->Stencil.Enabled) {
  285.       /* first stencil test */
  286.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  287.      return;
  288.       }
  289.       /* depth buffering w/ stencil */
  290.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  291.    }
  292.    else if (ctx->Depth.Test) {
  293.       /* regular depth testing */
  294.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  295.    }
  296.  
  297.    if (ctx->RasterMask & NO_DRAW_BIT) {
  298.       /* write no pixels */
  299.       return;
  300.    }
  301.  
  302.    if ((ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP))
  303.     || ctx->Color.SWLogicOpEnabled || ctx->Color.SWmasking) {
  304.       GLuint ispan[MAX_WIDTH];
  305.       /* index may change, replicate single index into an array */
  306.       for (i=0;i<n;i++) {
  307.      ispan[i] = index;
  308.       }
  309.  
  310.       if (ctx->Fog.Enabled
  311.       && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  312.      gl_fog_index_pixels( ctx, n, z, ispan );
  313.       }
  314.  
  315.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  316.      MEMCPY( index_save, index, n * sizeof(GLuint) );
  317.       }
  318.  
  319.       if (ctx->Color.SWLogicOpEnabled) {
  320.      gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
  321.       }
  322.  
  323.       if (ctx->Color.SWmasking) {
  324.      gl_mask_index_span( ctx, n, x, y, ispan );
  325.       }
  326.  
  327.       (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, ispan, mask );
  328.  
  329.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  330.      /*** Also draw to back buffer ***/
  331.      (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  332.      for (i=0;i<n;i++) {
  333.         ispan[i] = index;
  334.      }
  335.      if (ctx->Color.SWLogicOpEnabled) {
  336.         gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
  337.      }
  338.      if (ctx->Color.SWmasking) {
  339.         gl_mask_index_span( ctx, n, x, y, ispan );
  340.      }
  341.      (*ctx->Driver.WriteIndexSpan)( ctx, n, x, y, ispan, mask );
  342.      (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  343.       }
  344.    }
  345.    else {
  346.       (*ctx->Driver.WriteMonoindexSpan)( ctx, n, x, y, mask );
  347.  
  348.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  349.      /*** Also draw to back buffer ***/
  350.      (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  351.      (*ctx->Driver.WriteMonoindexSpan)( ctx, n, x, y, mask );
  352.      (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  353.       }
  354.    }
  355. }
  356.  
  357.  
  358.  
  359. void gl_write_color_span( GLcontext *ctx,
  360.               GLuint n, GLint x, GLint y, GLdepth z[],
  361.               GLubyte r[], GLubyte g[],
  362.               GLubyte b[], GLubyte a[],
  363.               GLenum primitive )
  364. {
  365.    GLubyte mask[MAX_WIDTH];
  366.    GLboolean write_all = GL_TRUE;
  367.    GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH];
  368.    GLubyte *red, *green, *blue, *alpha;
  369.  
  370.    /* init mask to 1's (all pixels are to be written) */
  371.    MEMSET(mask, 1, n);
  372.  
  373.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  374.       if (clip_span( ctx,n,x,y,mask)==0) {
  375.      return;
  376.       }
  377.       write_all = GL_FALSE;
  378.    }
  379.  
  380.    if ((primitive==GL_BITMAP && ctx->MutablePixels)
  381.        || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  382.       /* must make a copy of the colors since they may be modified */
  383.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  384.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  385.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  386.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  387.       red = rtmp;
  388.       green = gtmp;
  389.       blue = btmp;
  390.       alpha = atmp;
  391.    }
  392.    else {
  393.       red   = r;
  394.       green = g;
  395.       blue  = b;
  396.       alpha = a;
  397.    }
  398.  
  399.    /* Per-pixel fog */
  400.    if (ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP
  401.                 || ctx->Texture.Enabled)) {
  402.       gl_fog_color_pixels( ctx, n, z, red, green, blue, alpha );
  403.    }
  404.  
  405.    /* Do the scissor test */
  406.    if (ctx->Scissor.Enabled) {
  407.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  408.      return;
  409.       }
  410.       write_all = GL_FALSE;
  411.    }
  412.  
  413.    /* Polygon Stippling */
  414.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  415.       stipple_polygon_span( ctx, n, x, y, mask );
  416.       write_all = GL_FALSE;
  417.    }
  418.  
  419.    /* Do the alpha test */
  420.    if (ctx->Color.AlphaEnabled) {
  421.       if (gl_alpha_test( ctx, n, alpha, mask )==0) {
  422.      return;
  423.       }
  424.       write_all = GL_FALSE;
  425.    }
  426.  
  427.    if (ctx->Stencil.Enabled) {
  428.       /* first stencil test */
  429.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  430.      return;
  431.       }
  432.       /* depth buffering w/ stencil */
  433.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  434.       write_all = GL_FALSE;
  435.    }
  436.    else if (ctx->Depth.Test) {
  437.       /* regular depth testing */
  438.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  439.       if (m==0) {
  440.      return;
  441.       }
  442.       if (m<n) {
  443.      write_all = GL_FALSE;
  444.       }
  445.    }
  446.  
  447.    if (ctx->RasterMask & NO_DRAW_BIT) {
  448.       /* write no pixels */
  449.       return;
  450.    }
  451.  
  452.    /* logic op or blending */
  453.    if (ctx->Color.SWLogicOpEnabled) {
  454.       gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  455.    }
  456.    else if (ctx->Color.BlendEnabled) {
  457.       gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  458.    }
  459.  
  460.    /* Color component masking */
  461.    if (ctx->Color.SWmasking) {
  462.       gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  463.    }
  464.  
  465.    /* write pixels */
  466.    (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  467.                   write_all ? NULL : mask );
  468.    if (ctx->RasterMask & ALPHABUF_BIT) {
  469.       gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  470.    }
  471.  
  472.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  473.       /*** Also render to back buffer ***/
  474.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  475.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  476.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  477.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  478.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  479.       if (ctx->Color.SWLogicOpEnabled) {
  480.      gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  481.       }
  482.       else  if (ctx->Color.BlendEnabled) {
  483.      gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  484.       }
  485.       if (ctx->Color.SWmasking) {
  486.      gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  487.       }
  488.       (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  489.                   write_all ? NULL : mask );
  490.       if (ctx->RasterMask & ALPHABUF_BIT) {
  491.      ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  492.      gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  493.      ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  494.       }
  495.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  496.    }
  497.  
  498. }
  499.  
  500.  
  501.  
  502. /*
  503.  * Write a horizontal span of color pixels to the frame buffer.
  504.  * The color is initially constant for the whole span.
  505.  * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
  506.  * Input:  n - number of pixels in the span
  507.  *         x, y - location of leftmost pixel in the span
  508.  *         z - array of [n] z-values
  509.  *         r, g, b, a - the color of the pixels
  510.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  511.  */
  512. void gl_write_monocolor_span( GLcontext *ctx,
  513.                   GLuint n, GLint x, GLint y, GLdepth z[],
  514.                   GLint r, GLint g, GLint b, GLint a,
  515.                   GLenum primitive )
  516. {
  517.    GLuint i;
  518.    GLubyte mask[MAX_WIDTH];
  519.    GLboolean write_all = GL_TRUE;
  520.    GLubyte red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH], alpha[MAX_WIDTH];
  521.  
  522.    /* init mask to 1's (all pixels are to be written) */
  523.    MEMSET(mask, 1, n);
  524.  
  525.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  526.       if (clip_span( ctx,n,x,y,mask)==0) {
  527.      return;
  528.       }
  529.       write_all = GL_FALSE;
  530.    }
  531.  
  532.    /* Do the scissor test */
  533.    if (ctx->Scissor.Enabled) {
  534.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  535.      return;
  536.       }
  537.       write_all = GL_FALSE;
  538.    }
  539.  
  540.    /* Polygon Stippling */
  541.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  542.       stipple_polygon_span( ctx, n, x, y, mask );
  543.       write_all = GL_FALSE;
  544.    }
  545.  
  546.    /* Do the alpha test */
  547.    if (ctx->Color.AlphaEnabled) {
  548.       GLubyte alpha[MAX_WIDTH];
  549.       for (i=0;i<n;i++) {
  550.      alpha[i] = a;
  551.       }
  552.       if (gl_alpha_test( ctx, n, alpha, mask )==0) {
  553.      return;
  554.       }
  555.       write_all = GL_FALSE;
  556.    }
  557.  
  558.    if (ctx->Stencil.Enabled) {
  559.       /* first stencil test */
  560.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  561.      return;
  562.       }
  563.       /* depth buffering w/ stencil */
  564.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  565.       write_all = GL_FALSE;
  566.    }
  567.    else if (ctx->Depth.Test) {
  568.       /* regular depth testing */
  569.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  570.       if (m==0) {
  571.      return;
  572.       }
  573.       if (m<n) {
  574.      write_all = GL_FALSE;
  575.       }
  576.    }
  577.  
  578.    if (ctx->RasterMask & NO_DRAW_BIT) {
  579.       /* write no pixels */
  580.       return;
  581.    }
  582.  
  583.    if (ctx->Color.BlendEnabled || ctx->Color.SWLogicOpEnabled
  584.        || ctx->Color.SWmasking) {
  585.       /* assign same color to each pixel */
  586.       for (i=0;i<n;i++) {
  587.      if (mask[i]) {
  588.         red[i]   = r;
  589.         green[i] = g;
  590.         blue[i]  = b;
  591.         alpha[i] = a;
  592.      }
  593.       }
  594.  
  595.       if (ctx->Color.SWLogicOpEnabled) {
  596.      gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  597.       }
  598.       else if (ctx->Color.BlendEnabled) {
  599.      gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  600.       }
  601.  
  602.       /* Color component masking */
  603.       if (ctx->Color.SWmasking) {
  604.      gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  605.       }
  606.  
  607.       /* write pixels */
  608.       (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  609.                      write_all ? NULL : mask );
  610.       if (ctx->RasterMask & ALPHABUF_BIT) {
  611.      gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  612.       }
  613.  
  614.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  615.      /*** Also draw to back buffer ***/
  616.      for (i=0;i<n;i++) {
  617.         if (mask[i]) {
  618.            red[i]   = r;
  619.            green[i] = g;
  620.            blue[i]  = b;
  621.            alpha[i] = a;
  622.         }
  623.      }
  624.      (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  625.      if (ctx->Color.SWLogicOpEnabled) {
  626.         gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask);
  627.      }
  628.      else if (ctx->Color.BlendEnabled) {
  629.         gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  630.      }
  631.      if (ctx->Color.SWmasking) {
  632.         gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  633.      }
  634.      (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  635.                     write_all ? NULL : mask );
  636.      (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  637.      if (ctx->RasterMask & ALPHABUF_BIT) {
  638.         ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  639.         gl_write_alpha_span( ctx, n, x, y, alpha,
  640.                  write_all ? NULL : mask );
  641.         ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  642.      }
  643.       }
  644.    }
  645.    else {
  646.       (*ctx->Driver.WriteMonocolorSpan)( ctx, n, x, y, mask );
  647.       if (ctx->RasterMask & ALPHABUF_BIT) {
  648.      gl_write_mono_alpha_span( ctx, n, x, y, a, write_all ? NULL : mask );
  649.       }
  650.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  651.      /* Also draw to back buffer */
  652.      (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  653.      (*ctx->Driver.WriteMonocolorSpan)( ctx, n, x, y, mask );
  654.      (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  655.      if (ctx->RasterMask & ALPHABUF_BIT) {
  656.         ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  657.         gl_write_mono_alpha_span( ctx, n, x, y, a,
  658.                       write_all ? NULL : mask );
  659.         ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  660.      }
  661.       }
  662.    }
  663. }
  664.  
  665.  
  666.  
  667. /*
  668.  * Write a horizontal span of textured pixels to the frame buffer.
  669.  * The color of each pixel is different.
  670.  * Alpha-testing, stenciling, depth-testing, and blending are done
  671.  * as needed.
  672.  * Input:  n - number of pixels in the span
  673.  *         x, y - location of leftmost pixel in the span
  674.  *         z - array of [n] z-values
  675.  *         s, t - array of (s,t) texture coordinates for each pixel
  676.  *         lambda - array of texture lambda values
  677.  *         red, green, blue, alpha - array of [n] color components
  678.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  679.  */
  680. void gl_write_texture_span( GLcontext *ctx,
  681.                 GLuint n, GLint x, GLint y, GLdepth z[],
  682.                 GLfloat s[], GLfloat t[], GLfloat u[],
  683.                 GLfloat lambda[],
  684.                 GLubyte r[], GLubyte g[],
  685.                 GLubyte b[], GLubyte a[],
  686.                 GLenum primitive )
  687. {
  688.    GLubyte mask[MAX_WIDTH];
  689.    GLboolean write_all = GL_TRUE;
  690.    GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH];
  691.    GLubyte *red, *green, *blue, *alpha;
  692.  
  693.    /* init mask to 1's (all pixels are to be written) */
  694.    MEMSET(mask, 1, n);
  695.  
  696.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  697.       if (clip_span( ctx,n,x,y,mask)==0) {
  698.      return;
  699.       }
  700.       write_all = GL_FALSE;
  701.    }
  702.  
  703.  
  704.    if (primitive==GL_BITMAP || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  705.       /* must make a copy of the colors since they may be modified */
  706.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  707.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  708.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  709.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  710.       red = rtmp;
  711.       green = gtmp;
  712.       blue = btmp;
  713.       alpha = atmp;
  714.    }
  715.    else {
  716.       red   = r;
  717.       green = g;
  718.       blue  = b;
  719.       alpha = a;
  720.    }
  721.  
  722.    /* Texture */
  723.    ASSERT(ctx->Texture.Enabled);
  724.    gl_texture_pixels( ctx, n, s, t, u, lambda, red, green, blue, alpha );
  725.  
  726.    /* Per-pixel fog */
  727.    if (ctx->Fog.Enabled && (ctx->Hint.Fog==GL_NICEST || primitive==GL_BITMAP
  728.                 || ctx->Texture.Enabled)) {
  729.       gl_fog_color_pixels( ctx, n, z, red, green, blue, alpha );
  730.    }
  731.  
  732.    /* Do the scissor test */
  733.    if (ctx->Scissor.Enabled) {
  734.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  735.      return;
  736.       }
  737.       write_all = GL_FALSE;
  738.    }
  739.  
  740.    /* Polygon Stippling */
  741.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  742.       stipple_polygon_span( ctx, n, x, y, mask );
  743.       write_all = GL_FALSE;
  744.    }
  745.  
  746.    /* Do the alpha test */
  747.    if (ctx->Color.AlphaEnabled) {
  748.       if (gl_alpha_test( ctx, n, alpha, mask )==0) {
  749.      return;
  750.       }
  751.       write_all = GL_FALSE;
  752.    }
  753.  
  754.    if (ctx->Stencil.Enabled) {
  755.       /* first stencil test */
  756.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  757.      return;
  758.       }
  759.       /* depth buffering w/ stencil */
  760.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  761.       write_all = GL_FALSE;
  762.    }
  763.    else if (ctx->Depth.Test) {
  764.       /* regular depth testing */
  765.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  766.       if (m==0) {
  767.      return;
  768.       }
  769.       if (m<n) {
  770.      write_all = GL_FALSE;
  771.       }
  772.    }
  773.  
  774.    if (ctx->RasterMask & NO_DRAW_BIT) {
  775.       /* write no pixels */
  776.       return;
  777.    }
  778.  
  779.    /* blending */
  780.    if (ctx->Color.SWLogicOpEnabled) {
  781.       gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  782.    }
  783.    else  if (ctx->Color.BlendEnabled) {
  784.       gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  785.    }
  786.  
  787.    if (ctx->Color.SWmasking) {
  788.       gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  789.    }
  790.  
  791.    /* write pixels */
  792.    (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  793.                   write_all ? NULL : mask );
  794.    if (ctx->RasterMask & ALPHABUF_BIT) {
  795.       gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  796.    }
  797.  
  798.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  799.       /* Also draw to back buffer */
  800.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  801.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  802.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  803.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  804.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  805.       if (ctx->Color.SWLogicOpEnabled) {
  806.      gl_logicop_rgba_span( ctx, n, x, y, red, green, blue, alpha, mask );
  807.       }
  808.       else if (ctx->Color.BlendEnabled) {
  809.      gl_blend_span( ctx, n, x, y, red, green, blue, alpha, mask );
  810.       }
  811.       if (ctx->Color.SWmasking) {
  812.      gl_mask_color_span( ctx, n, x, y, red, green, blue, alpha );
  813.       }
  814.       (*ctx->Driver.WriteColorSpan)( ctx, n, x, y, red, green, blue, alpha,
  815.                      write_all ? NULL : mask );
  816.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  817.       if (ctx->RasterMask & ALPHABUF_BIT) {
  818.      ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  819.      gl_write_alpha_span( ctx, n, x, y, alpha, write_all ? NULL : mask );
  820.      ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  821.       }
  822.    }
  823. }
  824.  
  825.  
  826.  
  827. /*
  828.  * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
  829.  * reading ouside the buffer's boundaries.
  830.  */
  831. void gl_read_color_span( GLcontext *ctx,
  832.              GLuint n, GLint x, GLint y,
  833.              GLubyte red[], GLubyte green[],
  834.              GLubyte blue[], GLubyte alpha[] )
  835. {
  836.    register GLuint i;
  837.  
  838.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  839.       /* completely above, below, or right */
  840.       for (i=0;i<n;i++) {
  841.      red[i] = green[i] = blue[i] = alpha[i] = 0;
  842.       }
  843.    }
  844.    else {
  845.       if (x>=0 && x+n<=ctx->Buffer->Width) {
  846.      /* OK */
  847.      (*ctx->Driver.ReadColorSpan)( ctx, n, x, y, red, green, blue, alpha );
  848.      if (ctx->RasterMask & ALPHABUF_BIT) {
  849.         gl_read_alpha_span( ctx, n, x, y, alpha );
  850.      }
  851.       }
  852.       else {
  853.      i = 0;
  854.      if (x<0) {
  855.         while (x<0 && n>0) {
  856.            red[i] = green[i] =  blue[i] = alpha[i] = 0;
  857.            x++;
  858.            n--;
  859.            i++;
  860.         }
  861.      }
  862.      n = MIN2( n, ctx->Buffer->Width - x );
  863.      (*ctx->Driver.ReadColorSpan)( ctx, n, x, y, red+i, green+i, blue+i, alpha+i);
  864.      if (ctx->RasterMask & ALPHABUF_BIT) {
  865.         gl_read_alpha_span( ctx, n, x, y, alpha+i );
  866.      }
  867.       }
  868.    }
  869. }
  870.  
  871.  
  872.  
  873.  
  874. /*
  875.  * Read CI pixels from frame buffer.  Clipping will be done to prevent
  876.  * reading ouside the buffer's boundaries.
  877.  */
  878. void gl_read_index_span( GLcontext *ctx,
  879.              GLuint n, GLint x, GLint y, GLuint indx[] )
  880. {
  881.    register GLuint i;
  882.  
  883.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  884.       /* completely above, below, or right */
  885.       for (i=0;i<n;i++) {
  886.      indx[i] = 0;
  887.       }
  888.    }
  889.    else {
  890.       if (x>=0 && x+n<=ctx->Buffer->Width) {
  891.      /* OK */
  892.      (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, indx );
  893.       }
  894.       else {
  895.      i = 0;
  896.      if (x<0) {
  897.         while (x<0 && n>0) {
  898.            indx[i] = 0;
  899.            x++;
  900.            n--;
  901.            i++;
  902.         }
  903.      }
  904.      n = MIN2( n, ctx->Buffer->Width - x );
  905.      (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, indx+i );
  906.       }
  907.    }
  908. }
  909.  
  910.  
  911.