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

  1. /* $Id: blend.c,v 1.7 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. #ifdef PC_HEADER
  30. #include "all.h"
  31. #else
  32. #ifndef XFree86Server
  33. #include <stdio.h>
  34. #include <assert.h>
  35. #include <stdlib.h>
  36. #else
  37. #include "GL/xf86glx.h"
  38. #endif
  39. #include "alphabuf.h"
  40. #include "blend.h"
  41. #include "context.h"
  42. #include "enums.h"
  43. #include "macros.h"
  44. #include "pb.h"
  45. #include "span.h"
  46. #include "types.h"
  47. #endif
  48.  
  49.  
  50. void gl_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
  51. {
  52.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFunc");
  53.  
  54.    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
  55.       fprintf(stderr, "glBlendFunc %s %s\n",
  56.           gl_lookup_enum_by_nr(sfactor),
  57.           gl_lookup_enum_by_nr(dfactor));
  58.  
  59.    switch (sfactor) {
  60.       case GL_ZERO:
  61.       case GL_ONE:
  62.       case GL_DST_COLOR:
  63.       case GL_ONE_MINUS_DST_COLOR:
  64.       case GL_SRC_ALPHA:
  65.       case GL_ONE_MINUS_SRC_ALPHA:
  66.       case GL_DST_ALPHA:
  67.       case GL_ONE_MINUS_DST_ALPHA:
  68.       case GL_SRC_ALPHA_SATURATE:
  69.       case GL_CONSTANT_COLOR:
  70.       case GL_ONE_MINUS_CONSTANT_COLOR:
  71.       case GL_CONSTANT_ALPHA:
  72.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  73.          ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor;
  74.          break;
  75.       default:
  76.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
  77.          return;
  78.    }
  79.  
  80.    switch (dfactor) {
  81.       case GL_ZERO:
  82.       case GL_ONE:
  83.       case GL_SRC_COLOR:
  84.       case GL_ONE_MINUS_SRC_COLOR:
  85.       case GL_SRC_ALPHA:
  86.       case GL_ONE_MINUS_SRC_ALPHA:
  87.       case GL_DST_ALPHA:
  88.       case GL_ONE_MINUS_DST_ALPHA:
  89.       case GL_CONSTANT_COLOR:
  90.       case GL_ONE_MINUS_CONSTANT_COLOR:
  91.       case GL_CONSTANT_ALPHA:
  92.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  93.          ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor;
  94.          break;
  95.       default:
  96.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
  97.          return;
  98.    }
  99.  
  100.    if (ctx->Driver.BlendFunc) {
  101.       (*ctx->Driver.BlendFunc)( ctx, sfactor, dfactor );
  102.    }
  103.  
  104.    ctx->Color.BlendFunc = NULL;
  105.    ctx->NewState |= NEW_RASTER_OPS;
  106. }
  107.  
  108.  
  109. /* GL_INGR_blend_func_separate */
  110. void
  111. gl_BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
  112.                       GLenum sfactorA, GLenum dfactorA )
  113. {
  114.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFuncSeparate");
  115.  
  116.    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
  117.       fprintf(stderr, "glBlendFuncSeperate %s %s %s %s\n",
  118.           gl_lookup_enum_by_nr(sfactorRGB),
  119.           gl_lookup_enum_by_nr(dfactorRGB),
  120.           gl_lookup_enum_by_nr(sfactorA),
  121.           gl_lookup_enum_by_nr(dfactorA));
  122.  
  123.    switch (sfactorRGB) {
  124.       case GL_ZERO:
  125.       case GL_ONE:
  126.       case GL_DST_COLOR:
  127.       case GL_ONE_MINUS_DST_COLOR:
  128.       case GL_SRC_ALPHA:
  129.       case GL_ONE_MINUS_SRC_ALPHA:
  130.       case GL_DST_ALPHA:
  131.       case GL_ONE_MINUS_DST_ALPHA:
  132.       case GL_SRC_ALPHA_SATURATE:
  133.       case GL_CONSTANT_COLOR:
  134.       case GL_ONE_MINUS_CONSTANT_COLOR:
  135.       case GL_CONSTANT_ALPHA:
  136.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  137.          ctx->Color.BlendSrcRGB = sfactorRGB;
  138.          break;
  139.       default:
  140.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)" );
  141.          return;
  142.    }
  143.  
  144.    switch (dfactorRGB) {
  145.       case GL_ZERO:
  146.       case GL_ONE:
  147.       case GL_SRC_COLOR:
  148.       case GL_ONE_MINUS_SRC_COLOR:
  149.       case GL_SRC_ALPHA:
  150.       case GL_ONE_MINUS_SRC_ALPHA:
  151.       case GL_DST_ALPHA:
  152.       case GL_ONE_MINUS_DST_ALPHA:
  153.       case GL_CONSTANT_COLOR:
  154.       case GL_ONE_MINUS_CONSTANT_COLOR:
  155.       case GL_CONSTANT_ALPHA:
  156.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  157.          ctx->Color.BlendDstRGB = dfactorRGB;
  158.          break;
  159.       default:
  160.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)" );
  161.          return;
  162.    }
  163.  
  164.    switch (sfactorA) {
  165.       case GL_ZERO:
  166.       case GL_ONE:
  167.       case GL_DST_COLOR:
  168.       case GL_ONE_MINUS_DST_COLOR:
  169.       case GL_SRC_ALPHA:
  170.       case GL_ONE_MINUS_SRC_ALPHA:
  171.       case GL_DST_ALPHA:
  172.       case GL_ONE_MINUS_DST_ALPHA:
  173.       case GL_SRC_ALPHA_SATURATE:
  174.       case GL_CONSTANT_COLOR:
  175.       case GL_ONE_MINUS_CONSTANT_COLOR:
  176.       case GL_CONSTANT_ALPHA:
  177.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  178.          ctx->Color.BlendSrcA = sfactorA;
  179.          break;
  180.       default:
  181.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)" );
  182.          return;
  183.    }
  184.  
  185.    switch (dfactorA) {
  186.       case GL_ZERO:
  187.       case GL_ONE:
  188.       case GL_SRC_COLOR:
  189.       case GL_ONE_MINUS_SRC_COLOR:
  190.       case GL_SRC_ALPHA:
  191.       case GL_ONE_MINUS_SRC_ALPHA:
  192.       case GL_DST_ALPHA:
  193.       case GL_ONE_MINUS_DST_ALPHA:
  194.       case GL_CONSTANT_COLOR:
  195.       case GL_ONE_MINUS_CONSTANT_COLOR:
  196.       case GL_CONSTANT_ALPHA:
  197.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  198.          ctx->Color.BlendDstA = dfactorA;
  199.          break;
  200.       default:
  201.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" );
  202.          return;
  203.    }
  204.  
  205.    ctx->Color.BlendFunc = NULL;
  206.    ctx->NewState |= NEW_RASTER_OPS;
  207.  
  208.    if (ctx->Driver.BlendFuncSeparate) {
  209.       (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
  210.                     sfactorA, dfactorA );
  211.    }
  212. }
  213.  
  214.  
  215.  
  216. /* This is really an extension function! */
  217. void gl_BlendEquation( GLcontext *ctx, GLenum mode )
  218. {
  219.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendEquation");
  220.  
  221.    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
  222.       fprintf(stderr, "glBlendEquation %s\n",
  223.           gl_lookup_enum_by_nr(mode));
  224.  
  225.  
  226.    switch (mode) {
  227.       case GL_MIN_EXT:
  228.       case GL_MAX_EXT:
  229.       case GL_LOGIC_OP:
  230.       case GL_FUNC_ADD_EXT:
  231.       case GL_FUNC_SUBTRACT_EXT:
  232.       case GL_FUNC_REVERSE_SUBTRACT_EXT:
  233.          ctx->Color.BlendEquation = mode;
  234.          break;
  235.       default:
  236.          gl_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
  237.          return;
  238.    }
  239.  
  240.    /* This is needed to support 1.1's RGB logic ops AND
  241.     * 1.0's blending logicops.
  242.     */
  243.    if (mode==GL_LOGIC_OP && ctx->Color.BlendEnabled) {
  244.       ctx->Color.ColorLogicOpEnabled = GL_TRUE;
  245.    }
  246.    else {
  247.       ctx->Color.ColorLogicOpEnabled = GL_FALSE;
  248.    }
  249.  
  250.    ctx->Color.BlendFunc = NULL;
  251.    ctx->NewState |= NEW_RASTER_OPS;
  252.    
  253.    if (ctx->Driver.BlendEquation)
  254.       ctx->Driver.BlendEquation( ctx, mode );
  255. }
  256.  
  257.  
  258.  
  259. void gl_BlendColor( GLcontext *ctx, GLclampf red, GLclampf green,
  260.             GLclampf blue, GLclampf alpha )
  261. {
  262.    ctx->Color.BlendColor[0] = CLAMP( red,   0.0F, 1.0F );
  263.    ctx->Color.BlendColor[1] = CLAMP( green, 0.0F, 1.0F );
  264.    ctx->Color.BlendColor[2] = CLAMP( blue,  0.0F, 1.0F );
  265.    ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0F, 1.0F );
  266. }
  267.  
  268.  
  269.  
  270. /*
  271.  * Common transparency blending mode.
  272.  */
  273. static void blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
  274.                                 GLubyte rgba[][4], CONST GLubyte dest[][4] )
  275. {
  276.    GLuint i;
  277.    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
  278.    ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA);
  279.    ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA);
  280.    (void) ctx;
  281.  
  282.    for (i=0;i<n;i++) {
  283.       if (mask[i]) {
  284.          GLint t = rgba[i][ACOMP];  /* t in [0,255] */
  285.          if (t == 0) {
  286.             rgba[i][RCOMP] = dest[i][RCOMP];
  287.             rgba[i][GCOMP] = dest[i][GCOMP];
  288.             rgba[i][BCOMP] = dest[i][BCOMP];
  289.             rgba[i][ACOMP] = dest[i][ACOMP];
  290.          }
  291.          else if (t == 255) {
  292.             /* no-op */
  293.          }
  294.          else {
  295.             GLint s = 255 - t;
  296.             GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8;
  297.             GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8;
  298.             GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8;
  299.             GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8;
  300.             ASSERT(r <= 255);
  301.             ASSERT(g <= 255);
  302.             ASSERT(b <= 255);
  303.             ASSERT(a <= 255);
  304.             rgba[i][RCOMP] = (GLubyte) r;
  305.             rgba[i][GCOMP] = (GLubyte) g;
  306.             rgba[i][BCOMP] = (GLubyte) b;
  307.             rgba[i][ACOMP] = (GLubyte) a;
  308.          }
  309.       }
  310.    }
  311. }
  312.  
  313.  
  314.  
  315. /*
  316.  * Add src and dest.
  317.  */
  318. static void blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
  319.                        GLubyte rgba[][4], CONST GLubyte dest[][4] )
  320. {
  321.    GLuint i;
  322.    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
  323.    ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
  324.    ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
  325.    (void) ctx;
  326.  
  327.    for (i=0;i<n;i++) {
  328.       if (mask[i]) {
  329.          GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
  330.          GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
  331.          GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
  332.          GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
  333.          rgba[i][RCOMP] = (GLubyte) MIN2( r, 255 );
  334.          rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 );
  335.          rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 );
  336.          rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 );
  337.       }
  338.    }
  339. }
  340.  
  341.  
  342.  
  343. /*
  344.  * Blend min function  (for GL_EXT_blend_minmax)
  345.  */
  346. static void blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
  347.                        GLubyte rgba[][4], CONST GLubyte dest[][4] )
  348. {
  349.    GLuint i;
  350.    ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
  351.    (void) ctx;
  352.  
  353.    for (i=0;i<n;i++) {
  354.       if (mask[i]) {
  355.          rgba[i][RCOMP] = (GLubyte) MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
  356.          rgba[i][GCOMP] = (GLubyte) MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
  357.          rgba[i][BCOMP] = (GLubyte) MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
  358.          rgba[i][ACOMP] = (GLubyte) MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
  359.       }
  360.    }
  361. }
  362.  
  363.  
  364.  
  365. /*
  366.  * Blend max function  (for GL_EXT_blend_minmax)
  367.  */
  368. static void blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
  369.                        GLubyte rgba[][4], CONST GLubyte dest[][4] )
  370. {
  371.    GLuint i;
  372.    ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
  373.    (void) ctx;
  374.  
  375.    for (i=0;i<n;i++) {
  376.       if (mask[i]) {
  377.          rgba[i][RCOMP] = (GLubyte) MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
  378.          rgba[i][GCOMP] = (GLubyte) MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
  379.          rgba[i][BCOMP] = (GLubyte) MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
  380.          rgba[i][ACOMP] = (GLubyte) MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
  381.       }
  382.    }
  383. }
  384.  
  385.  
  386.  
  387. /*
  388.  * Modulate:  result = src * dest
  389.  */
  390. static void blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
  391.                             GLubyte rgba[][4], CONST GLubyte dest[][4] )
  392. {
  393.    GLuint i;
  394.    (void) ctx;
  395.  
  396.    for (i=0;i<n;i++) {
  397.       if (mask[i]) {
  398.          GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8;
  399.          GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8;
  400.          GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8;
  401.          GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8;
  402.          rgba[i][RCOMP] = (GLubyte) r;
  403.          rgba[i][GCOMP] = (GLubyte) g;
  404.          rgba[i][BCOMP] = (GLubyte) b;
  405.          rgba[i][ACOMP] = (GLubyte) a;
  406.       }
  407.    }
  408. }
  409.  
  410.  
  411.  
  412. /*
  413.  * General case blend pixels.
  414.  * Input:  n - number of pixels
  415.  *         mask - the usual write mask
  416.  * In/Out:  rgba - the incoming and modified pixels
  417.  * Input:  dest - the pixels from the dest color buffer
  418.  */
  419. static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
  420.                            GLubyte rgba[][4], CONST GLubyte dest[][4] )
  421. {
  422.    GLfloat rscale = 1.0F / 255.0F;
  423.    GLfloat gscale = 1.0F / 255.0F;
  424.    GLfloat bscale = 1.0F / 255.0F;
  425.    GLfloat ascale = 1.0F / 255.0F;
  426.    GLuint i;
  427.  
  428.    for (i=0;i<n;i++) {
  429.       if (mask[i]) {
  430.          GLint Rs, Gs, Bs, As;  /* Source colors */
  431.          GLint Rd, Gd, Bd, Ad;  /* Dest colors */
  432.          GLfloat sR, sG, sB, sA;  /* Source scaling */
  433.          GLfloat dR, dG, dB, dA;  /* Dest scaling */
  434.          GLfloat r, g, b, a;
  435.  
  436.          /* Source Color */
  437.          Rs = rgba[i][RCOMP];
  438.          Gs = rgba[i][GCOMP];
  439.          Bs = rgba[i][BCOMP];
  440.          As = rgba[i][ACOMP];
  441.  
  442.          /* Frame buffer color */
  443.          Rd = dest[i][RCOMP];
  444.          Gd = dest[i][GCOMP];
  445.          Bd = dest[i][BCOMP];
  446.          Ad = dest[i][ACOMP];
  447.  
  448.          /* Source RGB factor */
  449.          switch (ctx->Color.BlendSrcRGB) {
  450.             case GL_ZERO:
  451.                sR = sG = sB = 0.0F;
  452.                break;
  453.             case GL_ONE:
  454.                sR = sG = sB = 1.0F;
  455.                break;
  456.             case GL_DST_COLOR:
  457.                sR = (GLfloat) Rd * rscale;
  458.                sG = (GLfloat) Gd * gscale;
  459.                sB = (GLfloat) Bd * bscale;
  460.                break;
  461.             case GL_ONE_MINUS_DST_COLOR:
  462.                sR = 1.0F - (GLfloat) Rd * rscale;
  463.                sG = 1.0F - (GLfloat) Gd * gscale;
  464.                sB = 1.0F - (GLfloat) Bd * bscale;
  465.                break;
  466.             case GL_SRC_ALPHA:
  467.                sR = sG = sB = (GLfloat) As * ascale;
  468.                break;
  469.             case GL_ONE_MINUS_SRC_ALPHA:
  470.                sR = sG = sB = (GLfloat) 1.0F - (GLfloat) As * ascale;
  471.                break;
  472.             case GL_DST_ALPHA:
  473.                sR = sG = sB = (GLfloat) Ad * ascale;
  474.                break;
  475.             case GL_ONE_MINUS_DST_ALPHA:
  476.                sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
  477.                break;
  478.             case GL_SRC_ALPHA_SATURATE:
  479.                if (As < 1.0F - (GLfloat) Ad * ascale) {
  480.                   sR = sG = sB = (GLfloat) As * ascale;
  481.                }
  482.                else {
  483.                   sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
  484.                }
  485.                break;
  486.             case GL_CONSTANT_COLOR:
  487.                sR = ctx->Color.BlendColor[0];
  488.                sG = ctx->Color.BlendColor[1];
  489.                sB = ctx->Color.BlendColor[2];
  490.                break;
  491.             case GL_ONE_MINUS_CONSTANT_COLOR:
  492.                sR = 1.0F - ctx->Color.BlendColor[0];
  493.                sG = 1.0F - ctx->Color.BlendColor[1];
  494.                sB = 1.0F - ctx->Color.BlendColor[2];
  495.                break;
  496.             case GL_CONSTANT_ALPHA:
  497.                sR = sG = sB = ctx->Color.BlendColor[3];
  498.                break;
  499.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  500.                sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
  501.                break;
  502.             default:
  503.                /* this should never happen */
  504.                gl_problem(ctx, "Bad blend source RGB factor in do_blend");
  505.            return;
  506.          }
  507.  
  508.          /* Source Alpha factor */
  509.          switch (ctx->Color.BlendSrcA) {
  510.             case GL_ZERO:
  511.                sA = 0.0F;
  512.                break;
  513.             case GL_ONE:
  514.                sA = 1.0F;
  515.                break;
  516.             case GL_DST_COLOR:
  517.                sA = (GLfloat) Ad * ascale;
  518.                break;
  519.             case GL_ONE_MINUS_DST_COLOR:
  520.                sA = 1.0F - (GLfloat) Ad * ascale;
  521.                break;
  522.             case GL_SRC_ALPHA:
  523.                sA = (GLfloat) As * ascale;
  524.                break;
  525.             case GL_ONE_MINUS_SRC_ALPHA:
  526.                sA = (GLfloat) 1.0F - (GLfloat) As * ascale;
  527.                break;
  528.             case GL_DST_ALPHA:
  529.                sA =(GLfloat) Ad * ascale;
  530.                break;
  531.             case GL_ONE_MINUS_DST_ALPHA:
  532.                sA = 1.0F - (GLfloat) Ad * ascale;
  533.                break;
  534.             case GL_SRC_ALPHA_SATURATE:
  535.                sA = 1.0;
  536.                break;
  537.             case GL_CONSTANT_COLOR:
  538.                sA = ctx->Color.BlendColor[3];
  539.                break;
  540.             case GL_ONE_MINUS_CONSTANT_COLOR:
  541.                sA = 1.0F - ctx->Color.BlendColor[3];
  542.                break;
  543.             case GL_CONSTANT_ALPHA:
  544.                sA = ctx->Color.BlendColor[3];
  545.                break;
  546.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  547.                sA = 1.0F - ctx->Color.BlendColor[3];
  548.                break;
  549.             default:
  550.                /* this should never happen */
  551.                sA = 0.0F;
  552.                gl_problem(ctx, "Bad blend source A factor in do_blend");
  553.          }
  554.  
  555.          /* Dest RGB factor */
  556.          switch (ctx->Color.BlendDstRGB) {
  557.             case GL_ZERO:
  558.                dR = dG = dB = 0.0F;
  559.                break;
  560.             case GL_ONE:
  561.                dR = dG = dB = 1.0F;
  562.                break;
  563.             case GL_SRC_COLOR:
  564.                dR = (GLfloat) Rs * rscale;
  565.                dG = (GLfloat) Gs * gscale;
  566.                dB = (GLfloat) Bs * bscale;
  567.                break;
  568.             case GL_ONE_MINUS_SRC_COLOR:
  569.                dR = 1.0F - (GLfloat) Rs * rscale;
  570.                dG = 1.0F - (GLfloat) Gs * gscale;
  571.                dB = 1.0F - (GLfloat) Bs * bscale;
  572.                break;
  573.             case GL_SRC_ALPHA:
  574.                dR = dG = dB = (GLfloat) As * ascale;
  575.                break;
  576.             case GL_ONE_MINUS_SRC_ALPHA:
  577.                dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale;
  578.                break;
  579.             case GL_DST_ALPHA:
  580.                dR = dG = dB = (GLfloat) Ad * ascale;
  581.                break;
  582.             case GL_ONE_MINUS_DST_ALPHA:
  583.                dR = dG = dB = 1.0F - (GLfloat) Ad * ascale;
  584.                break;
  585.             case GL_CONSTANT_COLOR:
  586.                dR = ctx->Color.BlendColor[0];
  587.                dG = ctx->Color.BlendColor[1];
  588.                dB = ctx->Color.BlendColor[2];
  589.                break;
  590.             case GL_ONE_MINUS_CONSTANT_COLOR:
  591.                dR = 1.0F - ctx->Color.BlendColor[0];
  592.                dG = 1.0F - ctx->Color.BlendColor[1];
  593.                dB = 1.0F - ctx->Color.BlendColor[2];
  594.                break;
  595.             case GL_CONSTANT_ALPHA:
  596.                dR = dG = dB = ctx->Color.BlendColor[3];
  597.                break;
  598.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  599.                dR = dG = dB = 1.0F - ctx->Color.BlendColor[3] * ascale;
  600.                break;
  601.             default:
  602.                /* this should never happen */
  603.                dR = dG = dB = 0.0F;
  604.                gl_problem(ctx, "Bad blend dest RGB factor in do_blend");
  605.          }
  606.  
  607.          /* Dest Alpha factor */
  608.          switch (ctx->Color.BlendDstA) {
  609.             case GL_ZERO:
  610.                dA = 0.0F;
  611.                break;
  612.             case GL_ONE:
  613.                dA = 1.0F;
  614.                break;
  615.             case GL_SRC_COLOR:
  616.                dA = (GLfloat) As * ascale;
  617.                break;
  618.             case GL_ONE_MINUS_SRC_COLOR:
  619.                dA = 1.0F - (GLfloat) As * ascale;
  620.                break;
  621.             case GL_SRC_ALPHA:
  622.                dA = (GLfloat) As * ascale;
  623.                break;
  624.             case GL_ONE_MINUS_SRC_ALPHA:
  625.                dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
  626.                break;
  627.             case GL_DST_ALPHA:
  628.                dA = (GLfloat) Ad * ascale;
  629.                break;
  630.             case GL_ONE_MINUS_DST_ALPHA:
  631.                dA = 1.0F - (GLfloat) Ad * ascale;
  632.                break;
  633.             case GL_CONSTANT_COLOR:
  634.                dA = ctx->Color.BlendColor[3];
  635.                break;
  636.             case GL_ONE_MINUS_CONSTANT_COLOR:
  637.                dA = 1.0F - ctx->Color.BlendColor[3];
  638.                break;
  639.             case GL_CONSTANT_ALPHA:
  640.                dA = ctx->Color.BlendColor[3];
  641.                break;
  642.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  643.                dA = 1.0F - ctx->Color.BlendColor[3] * ascale;
  644.                break;
  645.             default:
  646.                /* this should never happen */
  647.                dA = 0.0F;
  648.                gl_problem(ctx, "Bad blend dest A factor in do_blend");
  649.            return;
  650.          }
  651.  
  652.          /* Due to round-off problems we have to clamp against zero. */
  653.          /* Optimization: we don't have to do this for all src & dst factors */
  654.          if (dA < 0.0F)  dA = 0.0F;
  655.          if (dR < 0.0F)  dR = 0.0F;
  656.          if (dG < 0.0F)  dG = 0.0F;
  657.          if (dB < 0.0F)  dB = 0.0F;
  658.          if (sA < 0.0F)  sA = 0.0F;
  659.          if (sR < 0.0F)  sR = 0.0F;
  660.          if (sG < 0.0F)  sG = 0.0F;
  661.          if (sB < 0.0F)  sB = 0.0F;
  662.  
  663.          ASSERT( sR <= 1.0 );
  664.          ASSERT( sG <= 1.0 );
  665.          ASSERT( sB <= 1.0 );
  666.          ASSERT( sA <= 1.0 );
  667.          ASSERT( dR <= 1.0 );
  668.          ASSERT( dG <= 1.0 );
  669.          ASSERT( dB <= 1.0 );
  670.          ASSERT( dA <= 1.0 );
  671.  
  672.          /* compute blended color */
  673.          if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
  674.             r = Rs * sR + Rd * dR;
  675.             g = Gs * sG + Gd * dG;
  676.             b = Bs * sB + Bd * dB;
  677.             a = As * sA + Ad * dA;
  678.          }
  679.          else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
  680.             r = Rs * sR - Rd * dR;
  681.             g = Gs * sG - Gd * dG;
  682.             b = Bs * sB - Bd * dB;
  683.             a = As * sA - Ad * dA;
  684.          }
  685.          else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
  686.             r = Rd * dR - Rs * sR;
  687.             g = Gd * dG - Gs * sG;
  688.             b = Bd * dB - Bs * sB;
  689.             a = Ad * dA - As * sA;
  690.          }
  691.          else {
  692.             /* should never get here */
  693.             r = g = b = a = 0.0F;  /* silence uninitialized var warning */
  694.             gl_problem(ctx, "unexpected BlendEquation in blend_general()");
  695.          }
  696.  
  697.          /* final clamping */
  698.          rgba[i][RCOMP] = (GLubyte) (GLint) CLAMP( r, 0.0F, 255.0F );
  699.          rgba[i][GCOMP] = (GLubyte) (GLint) CLAMP( g, 0.0F, 255.0F );
  700.          rgba[i][BCOMP] = (GLubyte) (GLint) CLAMP( b, 0.0F, 255.0F );
  701.          rgba[i][ACOMP] = (GLubyte) (GLint) CLAMP( a, 0.0F, 255.0F );
  702.       }
  703.    }
  704. }
  705.  
  706.  
  707.  
  708. #if defined(USE_MMX_ASM)
  709. #include "X86/mmx.h"
  710. #include "X86/common_x86asm.h"
  711. #endif
  712.  
  713.  
  714. /*
  715.  * Analyze current blending parameters to pick fastest blending function.
  716.  * Result: the ctx->Color.BlendFunc pointer is updated.
  717.  */
  718. static void set_blend_function( GLcontext *ctx )
  719. {
  720.    const GLenum eq = ctx->Color.BlendEquation;
  721.    const GLenum srcRGB = ctx->Color.BlendSrcRGB;
  722.    const GLenum dstRGB = ctx->Color.BlendDstRGB;
  723.    const GLenum srcA = ctx->Color.BlendSrcA;
  724.    const GLenum dstA = ctx->Color.BlendDstA;
  725.  
  726. #if defined(USE_MMX_ASM)
  727.    /* Hmm.  A table here would have 12^4 == way too many entries.
  728.     * Provide a hook for MMX instead.
  729.     */
  730.    if (gl_x86_cpu_features & GL_CPU_MMX) {
  731.       gl_mmx_set_blend_function (ctx);
  732.    } else
  733. #endif
  734.    if (srcRGB != srcA || dstRGB != dstA) {
  735.       ctx->Color.BlendFunc = blend_general;
  736.    }
  737.    else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
  738.        && dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
  739.       ctx->Color.BlendFunc = blend_transparency;
  740.    }
  741.    else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
  742.       ctx->Color.BlendFunc = blend_add;
  743.    }
  744.    else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
  745.              && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
  746.             ||
  747.             ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
  748.              && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
  749.       ctx->Color.BlendFunc = blend_modulate;
  750.    }
  751.    else if (eq==GL_MIN_EXT) {
  752.       ctx->Color.BlendFunc = blend_min;
  753.    }
  754.    else if (eq==GL_MAX_EXT) {
  755.       ctx->Color.BlendFunc = blend_max;
  756.    }
  757.    else {
  758.       ctx->Color.BlendFunc = blend_general;
  759.    }
  760. }
  761.  
  762.  
  763.  
  764. /*
  765.  * Apply the blending operator to a span of pixels.
  766.  * Input:  n - number of pixels in span
  767.  *         x, y - location of leftmost pixel in span in window coords.
  768.  *         mask - boolean mask indicating which pixels to blend.
  769.  * In/Out:  rgba - pixel values
  770.  */
  771. void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
  772.             GLubyte rgba[][4], const GLubyte mask[] )
  773. {
  774.    GLubyte dest[MAX_WIDTH][4];
  775.  
  776.    /* Check if device driver can do the work */
  777.    if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
  778.       return;
  779.    }
  780.  
  781.    /* Read span of current frame buffer pixels */
  782.    gl_read_rgba_span( ctx, n, x, y, dest );
  783.  
  784.    if (!ctx->Color.BlendFunc)
  785.       set_blend_function(ctx);
  786.  
  787.    (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
  788. }
  789.  
  790.  
  791.  
  792.  
  793.  
  794. /*
  795.  * Apply the blending operator to an array of pixels.
  796.  * Input:  n - number of pixels in span
  797.  *         x, y - array of pixel locations
  798.  *         mask - boolean mask indicating which pixels to blend.
  799.  * In/Out:  rgba - pixel values
  800.  */
  801. void gl_blend_pixels( GLcontext *ctx,
  802.                       GLuint n, const GLint x[], const GLint y[],
  803.               GLubyte rgba[][4], const GLubyte mask[] )
  804. {
  805.    GLubyte dest[PB_SIZE][4];
  806.  
  807.    /* Check if device driver can do the work */
  808.    if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
  809.       return;
  810.    }
  811.  
  812.    /* Read pixels from current color buffer */
  813.    (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
  814.    if (ctx->RasterMask & ALPHABUF_BIT) {
  815.       gl_read_alpha_pixels( ctx, n, x, y, dest, mask );
  816.    }
  817.  
  818.    if (!ctx->Color.BlendFunc)
  819.       set_blend_function(ctx);
  820.  
  821.    (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
  822. }
  823.