home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / blend.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  18KB  |  688 lines

  1. /* blend.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  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.  * Pixel blending.
  26.  */
  27.  
  28.  
  29. /*
  30. $Id: blend.c,v 1.16 1996/02/19 21:50:00 brianp Exp $
  31.  
  32. $Log: blend.c,v $
  33.  * Revision 1.16  1996/02/19  21:50:00  brianp
  34.  * added support for software alpha buffering
  35.  *
  36.  * Revision 1.15  1995/12/19  17:05:37  brianp
  37.  * added gl_save_blendcolor() and gl_save_blendequation() calls
  38.  *
  39.  * Revision 1.14  1995/10/30  15:30:33  brianp
  40.  * pass mask array to DD.read_color_pixels
  41.  *
  42.  * Revision 1.13  1995/08/31  21:30:26  brianp
  43.  * renamed blend() as dd_blend()
  44.  * use *DD.read_color_pixels instead of dd_read_color_pixels
  45.  * introduced CC.NewState convention
  46.  *
  47.  * Revision 1.12  1995/06/12  15:34:31  brianp
  48.  * changed color arrays to GLubyte
  49.  *
  50.  * Revision 1.11  1995/05/31  14:57:10  brianp
  51.  * call gl_read_color_span() instead of dd_read_color_span()
  52.  *
  53.  * Revision 1.10  1995/05/22  21:02:41  brianp
  54.  * Release 1.2
  55.  *
  56.  * Revision 1.9  1995/05/12  19:20:19  brianp
  57.  * replaced CC.Mode!=0 with INSIDE_BEGIN_END
  58.  *
  59.  * Revision 1.8  1995/03/30  21:09:04  brianp
  60.  * fixed bugs in blend scale factors
  61.  *
  62.  * Revision 1.7  1995/03/24  20:03:44  brianp
  63.  * added missing cases to glBlendEquationEXT
  64.  *
  65.  * Revision 1.6  1995/03/24  16:59:17  brianp
  66.  * fixed blending/logicop bug
  67.  *
  68.  * Revision 1.5  1995/03/13  20:55:02  brianp
  69.  * introduced blend function
  70.  * added rest of logic ops
  71.  * optimized common cases
  72.  *
  73.  * Revision 1.4  1995/03/10  16:45:52  brianp
  74.  * updated for new blending extensions
  75.  *
  76.  * Revision 1.3  1995/03/07  18:58:42  brianp
  77.  * added gl_blend_pixels()
  78.  *
  79.  * Revision 1.2  1995/03/04  19:29:44  brianp
  80.  * 1.1 beta revision
  81.  *
  82.  * Revision 1.1  1995/02/24  14:17:11  brianp
  83.  * Initial revision
  84.  *
  85.  */
  86.  
  87.  
  88. #ifdef DEBUG
  89. #  include <assert.h>
  90. #endif
  91. #include "alphabuf.h"
  92. #include "context.h"
  93. #include "dd.h"
  94. #include "list.h"
  95. #include "macros.h"
  96. #include "pb.h"
  97. #include "span.h"
  98.  
  99.  
  100.  
  101. void glBlendFunc( GLenum sfactor, GLenum dfactor )
  102. {
  103.    if (CC.CompileFlag) {
  104.       gl_save_blendfunc( sfactor, dfactor );
  105.    }
  106.    if (CC.ExecuteFlag) {
  107.       if (INSIDE_BEGIN_END) {
  108.      gl_error( GL_INVALID_OPERATION, "glBlendFunction" );
  109.      return;
  110.       }
  111.  
  112.       switch (sfactor) {
  113.      case GL_ZERO:
  114.      case GL_ONE:
  115.      case GL_DST_COLOR:
  116.      case GL_ONE_MINUS_DST_COLOR:
  117.      case GL_SRC_ALPHA:
  118.      case GL_ONE_MINUS_SRC_ALPHA:
  119.      case GL_DST_ALPHA:
  120.      case GL_ONE_MINUS_DST_ALPHA:
  121.      case GL_SRC_ALPHA_SATURATE:
  122.      case GL_CONSTANT_COLOR_EXT:
  123.      case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
  124.      case GL_CONSTANT_ALPHA_EXT:
  125.      case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
  126.         CC.Color.BlendSrc = sfactor;
  127.         break;
  128.      default:
  129.         gl_error( GL_INVALID_ENUM, "glBlendFunction" );
  130.         return;
  131.       }
  132.  
  133.       switch (dfactor) {
  134.      case GL_ZERO:
  135.      case GL_ONE:
  136.      case GL_SRC_COLOR:
  137.      case GL_ONE_MINUS_SRC_COLOR:
  138.      case GL_SRC_ALPHA:
  139.      case GL_ONE_MINUS_SRC_ALPHA:
  140.      case GL_DST_ALPHA:
  141.      case GL_ONE_MINUS_DST_ALPHA:
  142.      case GL_CONSTANT_COLOR_EXT:
  143.      case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
  144.      case GL_CONSTANT_ALPHA_EXT:
  145.      case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
  146.         CC.Color.BlendDst = dfactor;
  147.         break;
  148.      default:
  149.         gl_error( GL_INVALID_ENUM, "glBlendFunction" );
  150.       }
  151.  
  152.       CC.NewState = GL_TRUE;
  153.    }
  154. }
  155.  
  156.  
  157.  
  158. /*
  159.  * This is not a standard OpenGL function.  It is an extension!
  160.  */
  161. void glBlendEquationEXT( GLenum mode )
  162. {
  163.    if (CC.CompileFlag) {
  164.       gl_save_blendequation( mode );
  165.    }
  166.    if (CC.ExecuteFlag) {
  167.       if (INSIDE_BEGIN_END) {
  168.      gl_error( GL_INVALID_OPERATION, "glBlendEquation" );
  169.      return;
  170.       }
  171.  
  172.       switch (mode) {
  173.      case GL_MIN_EXT:
  174.      case GL_MAX_EXT:
  175.      case GL_LOGIC_OP:
  176.      case GL_FUNC_ADD_EXT:
  177.      case GL_FUNC_SUBTRACT_EXT:
  178.      case GL_FUNC_REVERSE_SUBTRACT_EXT:
  179.         CC.Color.BlendEquation = mode;
  180.         break;
  181.     default:
  182.         gl_error( GL_INVALID_ENUM, "glBlendEquation" );
  183.       }
  184.       CC.NewState = GL_TRUE;
  185.    }
  186. }
  187.  
  188.  
  189.  
  190. /*
  191.  * This is not a standard OpenGL function.  It is an extension!
  192.  */
  193. void glBlendColorEXT( GLclampf red, GLclampf green,
  194.               GLclampf blue, GLclampf alpha )
  195. {
  196.    if (CC.CompileFlag) {
  197.       gl_save_blendcolor( red, green, blue, alpha );
  198.    }
  199.    if (CC.ExecuteFlag) {
  200.       CC.Color.BlendColor[0] = CLAMP( red,   0.0, 1.0 );
  201.       CC.Color.BlendColor[1] = CLAMP( green, 0.0, 1.0 );
  202.       CC.Color.BlendColor[2] = CLAMP( blue,  0.0, 1.0 );
  203.       CC.Color.BlendColor[3] = CLAMP( alpha, 0.0, 1.0 );
  204.    }
  205. }
  206.  
  207.  
  208.  
  209. /*
  210.  * Do the real work of gl_blend_span() and gl_blend_pixels().
  211.  * Input:  n - number of pixels
  212.  *         mask - the usual write mask
  213.  * In/Out:  red, green, blue, alpha - the incoming and modified pixels
  214.  * Input:  rdest, gdest, bdest, adest - the pixels from the dest color buffer
  215.  */
  216. static void do_blend( GLuint n, const GLubyte mask[],
  217.                       GLubyte red[], GLubyte green[],
  218.                       GLubyte blue[], GLubyte alpha[],
  219.                       const GLubyte rdest[], const GLubyte gdest[],
  220.                       const GLubyte bdest[], const GLubyte adest[] )
  221. {
  222.    GLfloat rscale, gscale, bscale, ascale;
  223.    GLuint i;
  224.  
  225.  
  226.    rscale = 1.0F / CC.RedScale;
  227.    gscale = 1.0F / CC.GreenScale;
  228.    bscale = 1.0F / CC.BlueScale;
  229.    ascale = 1.0F / CC.AlphaScale;
  230.  
  231.    /* Common cases: */
  232.  
  233.    if (CC.Color.BlendEquation==GL_FUNC_ADD_EXT
  234.        && CC.Color.BlendSrc==GL_SRC_ALPHA
  235.        && CC.Color.BlendDst==GL_ONE_MINUS_SRC_ALPHA) {
  236.       /* Alpha blending */
  237.       for (i=0;i<n;i++) {
  238.      if (mask[i]) {
  239.         GLfloat r, g, b, a;
  240.         GLfloat t = (GLfloat) alpha[i] * ascale;
  241.         r = red[i]   * t + rdest[i] * (1.0F-t);
  242.         g = green[i] * t + gdest[i] * (1.0F-t);
  243.         b = blue[i]  * t + bdest[i] * (1.0F-t);
  244.         a = alpha[i] * t + adest[i] * (1.0F-t);
  245.         red[i]   = (GLint) MIN2( r, CC.RedScale );
  246.         green[i] = (GLint) MIN2( g, CC.GreenScale );
  247.         blue[i]  = (GLint) MIN2( b, CC.BlueScale );
  248.         alpha[i] = (GLint) MIN2( a, CC.AlphaScale );
  249.      }
  250.       }
  251.    }
  252.    else if (CC.Color.BlendEquation==GL_LOGIC_OP
  253.         && CC.Color.LogicOp==GL_XOR) {
  254.       /* XOR drawing */
  255.       for (i=0;i<n;i++) {
  256.      if (mask[i]) {
  257.         red[i]   ^= rdest[i];
  258.         green[i] ^= gdest[i];
  259.         blue[i]  ^= bdest[i];
  260.         alpha[i] ^= adest[i];
  261.      }
  262.       }
  263.    }
  264.  
  265.    /* General cases: */
  266.  
  267.    else if (CC.Color.BlendEquation==GL_FUNC_ADD_EXT
  268.          || CC.Color.BlendEquation==GL_FUNC_SUBTRACT_EXT
  269.          || CC.Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
  270.       for (i=0;i<n;i++) {
  271.      if (mask[i]) {
  272.         GLint Rs, Gs, Bs, As;  /* Source colors */
  273.         GLint Rd, Gd, Bd, Ad;  /* Dest colors */
  274.         GLfloat sR, sG, sB, sA;  /* Source scaling */
  275.         GLfloat dR, dG, dB, dA;  /* Dest scaling */
  276.         GLfloat r, g, b, a;
  277.  
  278.         /* Source Color */
  279.         Rs = red[i];
  280.         Gs = green[i];
  281.         Bs = blue[i];
  282.         As = alpha[i];
  283.  
  284.         /* Frame buffer color */
  285.         Rd = rdest[i];
  286.         Gd = gdest[i];
  287.         Bd = bdest[i];
  288.         Ad = adest[i];
  289.  
  290.         /* Source scaling */
  291.         switch (CC.Color.BlendSrc) {
  292.            case GL_ZERO:
  293.           sR = sG = sB = sA = 0.0F;
  294.           break;
  295.            case GL_ONE:
  296.           sR = sG = sB = sA = 1.0F;
  297.           break;
  298.            case GL_DST_COLOR:
  299.           sR = (GLfloat) Rd * rscale;
  300.           sG = (GLfloat) Gd * gscale;
  301.           sB = (GLfloat) Bd * bscale;
  302.           sA = (GLfloat) Ad * ascale;
  303.           break;
  304.            case GL_ONE_MINUS_DST_COLOR:
  305.           sR = 1.0F - (GLfloat) Rd * rscale;
  306.           sG = 1.0F - (GLfloat) Gd * gscale;
  307.           sB = 1.0F - (GLfloat) Bd * bscale;
  308.           sA = 1.0F - (GLfloat) Ad * ascale;
  309.           break;
  310.            case GL_SRC_ALPHA:
  311.           sR = sG = sB = sA = (GLfloat) As * ascale;
  312.           break;
  313.            case GL_ONE_MINUS_SRC_ALPHA:
  314.           sR = sG = sB = sA = (GLfloat) 1.0F - (GLfloat) As * ascale;
  315.           break;
  316.            case GL_DST_ALPHA:
  317.           sR = sG = sB = sA =(GLfloat) Ad * ascale;
  318.           break;
  319.            case GL_ONE_MINUS_DST_ALPHA:
  320.           sR = sG = sB = sA = 1.0F - (GLfloat) Ad * ascale;
  321.           break;
  322.            case GL_SRC_ALPHA_SATURATE:
  323.           if (As < 1.0F - (GLfloat) Ad * ascale) {
  324.              sR = sG = sB = (GLfloat) As * ascale;
  325.           }
  326.           else {
  327.              sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
  328.           }
  329.           sA = 1.0;
  330.           break;
  331.            case GL_CONSTANT_COLOR_EXT:
  332.           sR = CC.Color.BlendColor[0];
  333.           sG = CC.Color.BlendColor[1];
  334.           sB = CC.Color.BlendColor[2];
  335.           sA = CC.Color.BlendColor[3];
  336.           break;
  337.            case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
  338.           sR = 1.0F - CC.Color.BlendColor[0];
  339.           sG = 1.0F - CC.Color.BlendColor[1];
  340.           sB = 1.0F - CC.Color.BlendColor[2];
  341.           sA = 1.0F - CC.Color.BlendColor[3];
  342.           break;
  343.            case GL_CONSTANT_ALPHA_EXT:
  344.           sR = sG = sB = sA = CC.Color.BlendColor[3];
  345.           break;
  346.            case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
  347.           sR = sG = sB = sA = 1.0F - CC.Color.BlendColor[3];
  348.           break;
  349.            default:
  350.           gl_error( GL_INVALID_ENUM, "gl_blend source" );
  351.         }
  352.  
  353.         /* Dest scaling */
  354.         switch (CC.Color.BlendDst) {
  355.            case GL_ZERO:
  356.           dR = dG = dB = dA = 0.0F;
  357.           break;
  358.            case GL_ONE:
  359.           dR = dG = dB = dA = 1.0F;
  360.           break;
  361.            case GL_SRC_COLOR:
  362.           dR = (GLfloat) Rs * rscale;
  363.           dG = (GLfloat) Gs * gscale;
  364.           dB = (GLfloat) Bs * bscale;
  365.           dA = (GLfloat) As * ascale;
  366.           break;
  367.            case GL_ONE_MINUS_SRC_COLOR:
  368.           dR = 1.0F - (GLfloat) Rs * rscale;
  369.           dG = 1.0F - (GLfloat) Gs * gscale;
  370.           dB = 1.0F - (GLfloat) Bs * bscale;
  371.           dA = 1.0F - (GLfloat) As * ascale;
  372.           break;
  373.            case GL_SRC_ALPHA:
  374.           dR = dG = dB = dA = (GLfloat) As * ascale;
  375.           break;
  376.            case GL_ONE_MINUS_SRC_ALPHA:
  377.           dR = dG = dB = dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
  378.           break;
  379.            case GL_DST_ALPHA:
  380.           dR = dG = dB = dA = (GLfloat) Ad * ascale;
  381.           break;
  382.            case GL_ONE_MINUS_DST_ALPHA:
  383.           dR = dG = dB = dA = 1.0F - (GLfloat) Ad * ascale;
  384.           break;
  385.            case GL_CONSTANT_COLOR_EXT:
  386.           dR = CC.Color.BlendColor[0];
  387.           dG = CC.Color.BlendColor[1];
  388.           dB = CC.Color.BlendColor[2];
  389.           dA = CC.Color.BlendColor[3];
  390.           break;
  391.            case GL_ONE_MINUS_CONSTANT_COLOR_EXT:
  392.           dR = 1.0F - CC.Color.BlendColor[0];
  393.           dG = 1.0F - CC.Color.BlendColor[1];
  394.           dB = 1.0F - CC.Color.BlendColor[2];
  395.           dA = 1.0F - CC.Color.BlendColor[3];
  396.           break;
  397.            case GL_CONSTANT_ALPHA_EXT:
  398.           dR = dG = dB = dA = CC.Color.BlendColor[3];
  399.           break;
  400.            case GL_ONE_MINUS_CONSTANT_ALPHA_EXT:
  401.           dR = dG = dB = dA = 1.0F - CC.Color.BlendColor[3] * ascale;
  402.           break;
  403.            default:
  404.           gl_error( GL_INVALID_ENUM, "gl_blend dest" );
  405.         }
  406.  
  407. #ifdef DEBUG
  408.         assert( sR>= 0.0 && sR<=1.0 );
  409.         assert( sG>= 0.0 && sG<=1.0 );
  410.         assert( sB>= 0.0 && sB<=1.0 );
  411.         assert( sA>= 0.0 && sA<=1.0 );
  412.         assert( dR>= 0.0 && dR<=1.0 );
  413.         assert( dG>= 0.0 && dG<=1.0 );
  414.         assert( dB>= 0.0 && dB<=1.0 );
  415.         assert( dA>= 0.0 && dA<=1.0 );
  416. #endif
  417.  
  418.         /* compute blended color */
  419.         if (CC.Color.BlendEquation==GL_FUNC_ADD_EXT) {
  420.            r = Rs * sR + Rd * dR;
  421.            g = Gs * sG + Gd * dG;
  422.            b = Bs * sB + Bd * dB;
  423.            a = As * sA + Ad * dA;
  424.         }
  425.         else if (CC.Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
  426.            r = Rs * sR - Rd * dR;
  427.            g = Gs * sG - Gd * dG;
  428.            b = Bs * sB - Bd * dB;
  429.            a = As * sA - Ad * dA;
  430.         }
  431.         else if (CC.Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
  432.            r = Rd * dR - Rs * sR;
  433.            g = Gd * dG - Gs * sG;
  434.            b = Bd * dB - Bs * sB;
  435.            a = Ad * dA - As * sA;
  436.         }
  437.         red[i]   = (GLint) CLAMP( r, 0.0, CC.RedScale );
  438.         green[i] = (GLint) CLAMP( g, 0.0, CC.GreenScale );
  439.         blue[i]  = (GLint) CLAMP( b, 0.0, CC.BlueScale );
  440.         alpha[i] = (GLint) CLAMP( a, 0.0, CC.AlphaScale );
  441.      }
  442.       }
  443.    }
  444.  
  445.    else if (CC.Color.BlendEquation==GL_LOGIC_OP) {
  446.       /* EXTENSION */
  447.       switch (CC.Color.LogicOp) {
  448.      case GL_CLEAR:
  449.         for (i=0;i<n;i++) {
  450.            if (mask[i]) {
  451.           red[i] = green[i] = blue[i] = alpha[i] = 0;
  452.            }
  453.         }
  454.         break;
  455.      case GL_SET:
  456.         for (i=0;i<n;i++) {
  457.            if (mask[i]) {
  458.           red[i]   = (GLint) CC.RedScale;
  459.           green[i] = (GLint) CC.GreenScale;
  460.           blue[i]  = (GLint) CC.BlueScale;
  461.           alpha[i] = (GLint) CC.AlphaScale;
  462.            }
  463.         }
  464.         break;
  465.      case GL_COPY:
  466.         /* do nothing */
  467.         break;
  468.      case GL_COPY_INVERTED:
  469.         for (i=0;i<n;i++) {
  470.            if (mask[i]) {
  471.           red[i]   = !red[i];
  472.           green[i] = !green[i];
  473.           blue[i]  = !blue[i];
  474.           alpha[i] = !alpha[i];
  475.            }
  476.         }
  477.         break;
  478.      case GL_NOOP:
  479.         for (i=0;i<n;i++) {
  480.            if (mask[i]) {
  481.           red[i]   = rdest[i];
  482.           green[i] = gdest[i];
  483.           blue[i]  = bdest[i];
  484.           alpha[i] = adest[i];
  485.            }
  486.         }
  487.         break;
  488.      case GL_INVERT:
  489.         for (i=0;i<n;i++) {
  490.            if (mask[i]) {
  491.           red[i]   = !rdest[i];
  492.           green[i] = !gdest[i];
  493.           blue[i]  = !bdest[i];
  494.           alpha[i] = !adest[i];
  495.            }
  496.         }
  497.         break;
  498.      case GL_AND:
  499.         for (i=0;i<n;i++) {
  500.            if (mask[i]) {
  501.           red[i]   &= rdest[i];
  502.           green[i] &= gdest[i];
  503.           blue[i]  &= bdest[i];
  504.           alpha[i] &= adest[i];
  505.            }
  506.         }
  507.         break;
  508.      case GL_NAND:
  509.         for (i=0;i<n;i++) {
  510.            if (mask[i]) {
  511.           red[i]   = !(red[i]   & rdest[i]);
  512.           green[i] = !(green[i] & gdest[i]);
  513.           blue[i]  = !(blue[i]  & bdest[i]);
  514.           alpha[i] = !(alpha[i] & adest[i]);
  515.            }
  516.         }
  517.         break;
  518.      case GL_OR:
  519.         for (i=0;i<n;i++) {
  520.            if (mask[i]) {
  521.           red[i]   |= rdest[i];
  522.           green[i] |= gdest[i];
  523.           blue[i]  |= bdest[i];
  524.           alpha[i] |= adest[i];
  525.            }
  526.         }
  527.         break;
  528.      case GL_NOR:
  529.         for (i=0;i<n;i++) {
  530.            if (mask[i]) {
  531.           red[i]   = !(red[i]   | rdest[i]);
  532.           green[i] = !(green[i] | gdest[i]);
  533.           blue[i]  = !(blue[i]  | bdest[i]);
  534.           alpha[i] = !(alpha[i] | adest[i]);
  535.            }
  536.         }
  537.         break;
  538.      case GL_XOR:
  539.         for (i=0;i<n;i++) {
  540.            if (mask[i]) {
  541.           red[i]   ^= rdest[i];
  542.           green[i] ^= gdest[i];
  543.           blue[i]  ^= bdest[i];
  544.           alpha[i] ^= adest[i];
  545.            }
  546.         }
  547.         break;
  548.      case GL_EQUIV:
  549.         for (i=0;i<n;i++) {
  550.            if (mask[i]) {
  551.           red[i]   = !(red[i]   ^ rdest[i]);
  552.           green[i] = !(green[i] ^ gdest[i]);
  553.           blue[i]  = !(blue[i]  ^ bdest[i]);
  554.           alpha[i] = !(alpha[i] ^ adest[i]);
  555.            }
  556.         }
  557.         break;
  558.      case GL_AND_REVERSE:
  559.         for (i=0;i<n;i++) {
  560.            if (mask[i]) {
  561.           red[i]   = red[i]   & !rdest[i];
  562.           green[i] = green[i] & !gdest[i];
  563.           blue[i]  = blue[i]  & !bdest[i];
  564.           alpha[i] = alpha[i] & !adest[i];
  565.            }
  566.         }
  567.         break;
  568.      case GL_AND_INVERTED:
  569.         for (i=0;i<n;i++) {
  570.            if (mask[i]) {
  571.           red[i]   = !red[i]   & rdest[i];
  572.           green[i] = !green[i] & gdest[i];
  573.           blue[i]  = !blue[i]  & bdest[i];
  574.           alpha[i] = !alpha[i] & adest[i];
  575.            }
  576.         }
  577.         break;
  578.      case GL_OR_REVERSE:
  579.         for (i=0;i<n;i++) {
  580.            if (mask[i]) {
  581.           red[i]   = red[i]   | !rdest[i];
  582.           green[i] = green[i] | !gdest[i];
  583.           blue[i]  = blue[i]  | !bdest[i];
  584.           alpha[i] = alpha[i] | !adest[i];
  585.            }
  586.         }
  587.         break;
  588.      case GL_OR_INVERTED:
  589.         for (i=0;i<n;i++) {
  590.            if (mask[i]) {
  591.           red[i]   = !red[i]   | rdest[i];
  592.           green[i] = !green[i] | gdest[i];
  593.           blue[i]  = !blue[i]  | bdest[i];
  594.           alpha[i] = !alpha[i] | adest[i];
  595.            }
  596.         }
  597.         break;
  598.      default:
  599.         ;  /* nothing */
  600.       }
  601.    }
  602.    else if (CC.Color.BlendEquation==GL_MIN_EXT) {
  603.       /* EXTENSION */
  604.       for (i=0;i<n;i++) {
  605.      if (mask[i]) {
  606.         red[i]   = MIN2( red[i],   rdest[i] );
  607.         green[i] = MIN2( green[i], gdest[i] );
  608.         blue[i]  = MIN2( blue[i],  bdest[i] );
  609.         alpha[i] = MIN2( alpha[i], adest[i] );
  610.      }
  611.       }
  612.    }
  613.    else if (CC.Color.BlendEquation==GL_MAX_EXT) {
  614.       /* EXTENSION */
  615.       for (i=0;i<n;i++) {
  616.      if (mask[i]) {
  617.         red[i]   = MAX2( red[i],   rdest[i] );
  618.         green[i] = MAX2( green[i], gdest[i] );
  619.         blue[i]  = MAX2( blue[i],  bdest[i] );
  620.         alpha[i] = MAX2( alpha[i], adest[i] );
  621.      }
  622.       }
  623.    }
  624.  
  625. }
  626.  
  627.  
  628.  
  629.  
  630.  
  631. /*
  632.  * Apply the blending operator to a span of pixels.
  633.  * Input:  n - number of pixels in span
  634.  *         x, y - location of leftmost pixel in span in window coords.
  635.  *         mask - boolean mask indicating which pixels to blend.
  636.  * In/Out:  red, green, blue, alpha - pixel values
  637.  */
  638. void gl_blend_span( GLuint n, GLint x, GLint y,
  639.             GLubyte red[], GLubyte green[],
  640.             GLubyte blue[], GLubyte alpha[],
  641.             GLubyte mask[] )
  642. {
  643.    GLubyte rdest[MAX_WIDTH], gdest[MAX_WIDTH];
  644.    GLubyte bdest[MAX_WIDTH], adest[MAX_WIDTH];
  645.  
  646.    /* Check if device driver can do the work */
  647.    if (CC.Color.BlendEquation==GL_LOGIC_OP && !CC.Color.SWLogicOpEnabled) {
  648.       return;
  649.    }
  650.  
  651.    /* Read span of current frame buffer pixels */
  652.    gl_read_color_span( n, x, y, rdest, gdest, bdest, adest );
  653.  
  654.    do_blend( n, mask, red, green, blue, alpha, rdest, gdest, bdest, adest );
  655. }
  656.  
  657.  
  658.  
  659.  
  660.  
  661. /*
  662.  * Apply the blending operator to an array of pixels.
  663.  * Input:  n - number of pixels in span
  664.  *         x, y - array of pixel locations
  665.  *         mask - boolean mask indicating which pixels to blend.
  666.  * In/Out:  red, green, blue, alpha - array of pixel values
  667.  */
  668. void gl_blend_pixels( GLuint n, const GLint x[], const GLint y[],
  669.               GLubyte red[], GLubyte green[],
  670.               GLubyte blue[], GLubyte alpha[],
  671.               GLubyte mask[] )
  672. {
  673.    GLubyte rdest[PB_SIZE], gdest[PB_SIZE], bdest[PB_SIZE], adest[PB_SIZE];
  674.  
  675.    /* Check if device driver can do the work */
  676.    if (CC.Color.BlendEquation==GL_LOGIC_OP && !CC.Color.SWLogicOpEnabled) {
  677.       return;
  678.    }
  679.  
  680.    /* Read pixels from current color buffer */
  681.    (*DD.read_color_pixels)( n, x, y, rdest, gdest, bdest, adest, mask );
  682.    if (CC.RasterMask & ALPHABUF_BIT) {
  683.       gl_read_alpha_pixels( n, x, y, adest, mask );
  684.    }
  685.  
  686.    do_blend( n, mask, red, green, blue, alpha, rdest, gdest, bdest, adest );
  687. }
  688.