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

  1. /* $Id: s_blend.c,v 1.25 2002/10/17 15:26:39 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28.  
  29. #include "glheader.h"
  30. #include "context.h"
  31. #include "colormac.h"
  32. #include "macros.h"
  33.  
  34. #include "s_alphabuf.h"
  35. #include "s_blend.h"
  36. #include "s_context.h"
  37. #include "s_span.h"
  38.  
  39.  
  40. #if defined(USE_MMX_ASM)
  41. #include "X86/mmx.h"
  42. #include "X86/common_x86_asm.h"
  43. #define _BLENDAPI _ASMAPI
  44. #else
  45. #define _BLENDAPI
  46. #endif
  47.  
  48.  
  49. /*
  50.  * Special case for glBlendFunc(GL_ZERO, GL_ONE)
  51.  */
  52. static void _BLENDAPI
  53. blend_noop( GLcontext *ctx, GLuint n, const GLubyte mask[],
  54.             GLchan rgba[][4], CONST GLchan dest[][4] )
  55. {
  56.    GLuint i;
  57.    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
  58.    ASSERT(ctx->Color.BlendSrcRGB==GL_ZERO);
  59.    ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
  60.    (void) ctx;
  61.  
  62.    for (i = 0; i < n; i++) {
  63.       if (mask[i]) {
  64.          COPY_CHAN4( rgba[i], dest[i] );
  65.       }
  66.    }
  67. }
  68.  
  69.  
  70. /*
  71.  * Special case for glBlendFunc(GL_ONE, GL_ZERO)
  72.  */
  73. static void _BLENDAPI
  74. blend_replace( GLcontext *ctx, GLuint n, const GLubyte mask[],
  75.                GLchan rgba[][4], CONST GLchan dest[][4] )
  76. {
  77.    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
  78.    ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
  79.    ASSERT(ctx->Color.BlendDstRGB==GL_ZERO);
  80.    (void) ctx;
  81.    (void) n;
  82.    (void) mask;
  83.    (void) rgba;
  84.    (void) dest;
  85. }
  86.  
  87.  
  88. /*
  89.  * Common transparency blending mode.
  90.  */
  91. static void _BLENDAPI
  92. blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
  93.                     GLchan rgba[][4], CONST GLchan dest[][4] )
  94. {
  95.    GLuint i;
  96.    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
  97.    ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA);
  98.    ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA);
  99.    (void) ctx;
  100.  
  101.    for (i=0;i<n;i++) {
  102.       if (mask[i]) {
  103.          const GLchan t = rgba[i][ACOMP];  /* t in [0, CHAN_MAX] */
  104.          if (t == 0) {
  105.             /* 0% alpha */
  106.             rgba[i][RCOMP] = dest[i][RCOMP];
  107.             rgba[i][GCOMP] = dest[i][GCOMP];
  108.             rgba[i][BCOMP] = dest[i][BCOMP];
  109.             rgba[i][ACOMP] = dest[i][ACOMP];
  110.          }
  111.          else if (t == CHAN_MAX) {
  112.             /* 100% alpha, no-op */
  113.          }
  114.          else {
  115. #if 0
  116.             /* This is pretty close, but Glean complains */
  117.             const GLint s = CHAN_MAX - t;
  118.             const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s + 1) >> 8;
  119.             const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s + 1) >> 8;
  120.             const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s + 1) >> 8;
  121.             const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s + 1) >> 8;
  122. #elif 0
  123.             /* This is slower but satisfies Glean */
  124.             const GLint s = CHAN_MAX - t;
  125.             const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) / 255;
  126.             const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) / 255;
  127.             const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) / 255;
  128.             const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) / 255;
  129. #else
  130. #if CHAN_BITS == 8
  131.             /* This satisfies Glean and should be reasonably fast */
  132.             /* Contributed by Nathan Hand */
  133. #if 0
  134. #define DIV255(X)  (((X) << 8) + (X) + 256) >> 16
  135. #else
  136.         GLint temp;
  137. #define DIV255(X)  (temp = (X), ((temp << 8) + temp + 256) >> 16)
  138. #endif
  139.             const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP];
  140.             const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP];
  141.             const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP];
  142.             const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP]; 
  143.  
  144. #undef DIV255
  145. #elif CHAN_BITS == 16
  146.             const GLfloat tt = (GLfloat) t / CHAN_MAXF;
  147.             const GLint r = (GLint) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]);
  148.             const GLint g = (GLint) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]);
  149.             const GLint b = (GLint) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]);
  150.             const GLint a = (GLint) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]);
  151. #else /* CHAN_BITS == 32 */
  152.             const GLfloat tt = (GLfloat) t / CHAN_MAXF;
  153.             const GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP];
  154.             const GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP];
  155.             const GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP];
  156.             const GLfloat a = CLAMP( rgba[i][ACOMP], 0.0F, CHAN_MAXF ) * t +
  157.                               CLAMP( dest[i][ACOMP], 0.0F, CHAN_MAXF ) * (1.0F - t);
  158. #endif
  159. #endif
  160.             ASSERT(r <= CHAN_MAX);
  161.             ASSERT(g <= CHAN_MAX);
  162.             ASSERT(b <= CHAN_MAX);
  163.             ASSERT(a <= CHAN_MAX);
  164.             rgba[i][RCOMP] = (GLchan) r;
  165.             rgba[i][GCOMP] = (GLchan) g;
  166.             rgba[i][BCOMP] = (GLchan) b;
  167.             rgba[i][ACOMP] = (GLchan) a;
  168.          }
  169.       }
  170.    }
  171. }
  172.  
  173.  
  174.  
  175. /*
  176.  * Add src and dest.
  177.  */
  178. static void _BLENDAPI
  179. blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
  180.            GLchan rgba[][4], CONST GLchan dest[][4] )
  181. {
  182.    GLuint i;
  183.    ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
  184.    ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
  185.    ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
  186.    (void) ctx;
  187.  
  188.    for (i=0;i<n;i++) {
  189.       if (mask[i]) {
  190. #if CHAN_TYPE == GL_FLOAT
  191.          /* don't RGB clamp to max */
  192.          GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, CHAN_MAXF) + dest[i][ACOMP];
  193.          rgba[i][RCOMP] += dest[i][RCOMP];
  194.          rgba[i][GCOMP] += dest[i][GCOMP];
  195.          rgba[i][BCOMP] += dest[i][BCOMP];
  196.          rgba[i][ACOMP] = (GLchan) MIN2( a, CHAN_MAXF );
  197. #else
  198.          GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
  199.          GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
  200.          GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
  201.          GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
  202.          rgba[i][RCOMP] = (GLchan) MIN2( r, CHAN_MAX );
  203.          rgba[i][GCOMP] = (GLchan) MIN2( g, CHAN_MAX );
  204.          rgba[i][BCOMP] = (GLchan) MIN2( b, CHAN_MAX );
  205.          rgba[i][ACOMP] = (GLchan) MIN2( a, CHAN_MAX );
  206. #endif
  207.       }
  208.    }
  209. }
  210.  
  211.  
  212.  
  213. /*
  214.  * Blend min function  (for GL_EXT_blend_minmax)
  215.  */
  216. static void _BLENDAPI
  217. blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
  218.            GLchan rgba[][4], CONST GLchan dest[][4] )
  219. {
  220.    GLuint i;
  221.    ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
  222.    (void) ctx;
  223.  
  224.    for (i=0;i<n;i++) {
  225.       if (mask[i]) {
  226.          rgba[i][RCOMP] = (GLchan) MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
  227.          rgba[i][GCOMP] = (GLchan) MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
  228.          rgba[i][BCOMP] = (GLchan) MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
  229. #if CHAN_TYPE == GL_FLOAT
  230.          rgba[i][ACOMP] = (GLchan) MIN2(CLAMP(rgba[i][ACOMP], 0.0F, CHAN_MAXF),
  231.                                         dest[i][ACOMP]);
  232. #else
  233.          rgba[i][ACOMP] = (GLchan) MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
  234. #endif
  235.       }
  236.    }
  237. }
  238.  
  239.  
  240.  
  241. /*
  242.  * Blend max function  (for GL_EXT_blend_minmax)
  243.  */
  244. static void _BLENDAPI
  245. blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
  246.            GLchan rgba[][4], CONST GLchan dest[][4] )
  247. {
  248.    GLuint i;
  249.    ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
  250.    (void) ctx;
  251.  
  252.    for (i=0;i<n;i++) {
  253.       if (mask[i]) {
  254.          rgba[i][RCOMP] = (GLchan) MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
  255.          rgba[i][GCOMP] = (GLchan) MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
  256.          rgba[i][BCOMP] = (GLchan) MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
  257. #if CHAN_TYPE == GL_FLOAT
  258.          rgba[i][ACOMP] = (GLchan) MAX2(CLAMP(rgba[i][ACOMP], 0.0F, CHAN_MAXF),
  259.                                         dest[i][ACOMP]);
  260. #else
  261.          rgba[i][ACOMP] = (GLchan) MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
  262. #endif
  263.       }
  264.    }
  265. }
  266.  
  267.  
  268.  
  269. /*
  270.  * Modulate:  result = src * dest
  271.  */
  272. static void _BLENDAPI
  273. blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
  274.                 GLchan rgba[][4], CONST GLchan dest[][4] )
  275. {
  276.    GLuint i;
  277.    (void) ctx;
  278.  
  279.    for (i=0;i<n;i++) {
  280.       if (mask[i]) {
  281. #if CHAN_TYPE == GL_FLOAT
  282.          rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
  283.          rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
  284.          rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
  285.          rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
  286. #elif CHAN_TYPE == GL_UNSIGNED_SHORT
  287.          GLint r = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16;
  288.          GLint g = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16;
  289.          GLint b = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16;
  290.          GLint a = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16;
  291.          rgba[i][RCOMP] = (GLchan) r;
  292.          rgba[i][GCOMP] = (GLchan) g;
  293.          rgba[i][BCOMP] = (GLchan) b;
  294.          rgba[i][ACOMP] = (GLchan) a;
  295. #else
  296.          GLint r = (rgba[i][RCOMP] * dest[i][RCOMP] + 255) >> 8;
  297.          GLint g = (rgba[i][GCOMP] * dest[i][GCOMP] + 255) >> 8;
  298.          GLint b = (rgba[i][BCOMP] * dest[i][BCOMP] + 255) >> 8;
  299.          GLint a = (rgba[i][ACOMP] * dest[i][ACOMP] + 255) >> 8;
  300.          rgba[i][RCOMP] = (GLchan) r;
  301.          rgba[i][GCOMP] = (GLchan) g;
  302.          rgba[i][BCOMP] = (GLchan) b;
  303.          rgba[i][ACOMP] = (GLchan) a;
  304. #endif
  305.       }
  306.    }
  307. }
  308.  
  309.  
  310.  
  311. /*
  312.  * General case blend pixels.
  313.  * Input:  n - number of pixels
  314.  *         mask - the usual write mask
  315.  * In/Out:  rgba - the incoming and modified pixels
  316.  * Input:  dest - the pixels from the dest color buffer
  317.  */
  318. static void _BLENDAPI
  319. blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
  320.                GLchan rgba[][4], CONST GLchan dest[][4] )
  321. {
  322.    const GLfloat rscale = 1.0F / CHAN_MAXF;
  323.    const GLfloat gscale = 1.0F / CHAN_MAXF;
  324.    const GLfloat bscale = 1.0F / CHAN_MAXF;
  325.    const GLfloat ascale = 1.0F / CHAN_MAXF;
  326.    GLuint i;
  327.  
  328.    for (i=0;i<n;i++) {
  329.       if (mask[i]) {
  330. #if CHAN_TYPE == GL_FLOAT
  331.          GLfloat Rs, Gs, Bs, As;  /* Source colors */
  332.          GLfloat Rd, Gd, Bd, Ad;  /* Dest colors */
  333. #else
  334.          GLint Rs, Gs, Bs, As;  /* Source colors */
  335.          GLint Rd, Gd, Bd, Ad;  /* Dest colors */
  336. #endif
  337.          GLfloat sR, sG, sB, sA;  /* Source scaling */
  338.          GLfloat dR, dG, dB, dA;  /* Dest scaling */
  339.          GLfloat r, g, b, a;      /* result color */
  340.  
  341.          /* Incoming/source Color */
  342.          Rs = rgba[i][RCOMP];
  343.          Gs = rgba[i][GCOMP];
  344.          Bs = rgba[i][BCOMP];
  345.          As = rgba[i][ACOMP];
  346. #if CHAN_TYPE == GL_FLOAT
  347.          /* clamp */
  348.          Rs = MIN2(Rs, CHAN_MAXF);
  349.          Gs = MIN2(Gs, CHAN_MAXF);
  350.          Bs = MIN2(Bs, CHAN_MAXF);
  351.          As = MIN2(As, CHAN_MAXF);
  352. #endif
  353.  
  354.          /* Frame buffer/dest color */
  355.          Rd = dest[i][RCOMP];
  356.          Gd = dest[i][GCOMP];
  357.          Bd = dest[i][BCOMP];
  358.          Ad = dest[i][ACOMP];
  359. #if CHAN_TYPE == GL_FLOAT
  360.          /* clamp */
  361.          Rd = MIN2(Rd, CHAN_MAXF);
  362.          Gd = MIN2(Gd, CHAN_MAXF);
  363.          Bd = MIN2(Bd, CHAN_MAXF);
  364.          Ad = MIN2(Ad, CHAN_MAXF);
  365. #endif
  366.  
  367.          /* Source RGB factor */
  368.          switch (ctx->Color.BlendSrcRGB) {
  369.             case GL_ZERO:
  370.                sR = sG = sB = 0.0F;
  371.                break;
  372.             case GL_ONE:
  373.                sR = sG = sB = 1.0F;
  374.                break;
  375.             case GL_DST_COLOR:
  376.                sR = (GLfloat) Rd * rscale;
  377.                sG = (GLfloat) Gd * gscale;
  378.                sB = (GLfloat) Bd * bscale;
  379.                break;
  380.             case GL_ONE_MINUS_DST_COLOR:
  381.                sR = 1.0F - (GLfloat) Rd * rscale;
  382.                sG = 1.0F - (GLfloat) Gd * gscale;
  383.                sB = 1.0F - (GLfloat) Bd * bscale;
  384.                break;
  385.             case GL_SRC_ALPHA:
  386.                sR = sG = sB = (GLfloat) As * ascale;
  387.                break;
  388.             case GL_ONE_MINUS_SRC_ALPHA:
  389.                sR = sG = sB = 1.0F - (GLfloat) As * ascale;
  390.                break;
  391.             case GL_DST_ALPHA:
  392.                sR = sG = sB = (GLfloat) Ad * ascale;
  393.                break;
  394.             case GL_ONE_MINUS_DST_ALPHA:
  395.                sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
  396.                break;
  397.             case GL_SRC_ALPHA_SATURATE:
  398.                if (As < CHAN_MAX - Ad) {
  399.                   sR = sG = sB = (GLfloat) As * ascale;
  400.                }
  401.                else {
  402.                   sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
  403.                }
  404.                break;
  405.             case GL_CONSTANT_COLOR:
  406.                sR = ctx->Color.BlendColor[0];
  407.                sG = ctx->Color.BlendColor[1];
  408.                sB = ctx->Color.BlendColor[2];
  409.                break;
  410.             case GL_ONE_MINUS_CONSTANT_COLOR:
  411.                sR = 1.0F - ctx->Color.BlendColor[0];
  412.                sG = 1.0F - ctx->Color.BlendColor[1];
  413.                sB = 1.0F - ctx->Color.BlendColor[2];
  414.                break;
  415.             case GL_CONSTANT_ALPHA:
  416.                sR = sG = sB = ctx->Color.BlendColor[3];
  417.                break;
  418.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  419.                sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
  420.                break;
  421.             case GL_SRC_COLOR: /* GL_NV_blend_square */
  422.                sR = (GLfloat) Rs * rscale;
  423.                sG = (GLfloat) Gs * gscale;
  424.                sB = (GLfloat) Bs * bscale;
  425.                break;
  426.             case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
  427.                sR = 1.0F - (GLfloat) Rs * rscale;
  428.                sG = 1.0F - (GLfloat) Gs * gscale;
  429.                sB = 1.0F - (GLfloat) Bs * bscale;
  430.                break;
  431.             default:
  432.                /* this should never happen */
  433.                _mesa_problem(ctx, "Bad blend source RGB factor in do_blend");
  434.                return;
  435.          }
  436.  
  437.          /* Source Alpha factor */
  438.          switch (ctx->Color.BlendSrcA) {
  439.             case GL_ZERO:
  440.                sA = 0.0F;
  441.                break;
  442.             case GL_ONE:
  443.                sA = 1.0F;
  444.                break;
  445.             case GL_DST_COLOR:
  446.                sA = (GLfloat) Ad * ascale;
  447.                break;
  448.             case GL_ONE_MINUS_DST_COLOR:
  449.                sA = 1.0F - (GLfloat) Ad * ascale;
  450.                break;
  451.             case GL_SRC_ALPHA:
  452.                sA = (GLfloat) As * ascale;
  453.                break;
  454.             case GL_ONE_MINUS_SRC_ALPHA:
  455.                sA = 1.0F - (GLfloat) As * ascale;
  456.                break;
  457.             case GL_DST_ALPHA:
  458.                sA =(GLfloat) Ad * ascale;
  459.                break;
  460.             case GL_ONE_MINUS_DST_ALPHA:
  461.                sA = 1.0F - (GLfloat) Ad * ascale;
  462.                break;
  463.             case GL_SRC_ALPHA_SATURATE:
  464.                sA = 1.0;
  465.                break;
  466.             case GL_CONSTANT_COLOR:
  467.                sA = ctx->Color.BlendColor[3];
  468.                break;
  469.             case GL_ONE_MINUS_CONSTANT_COLOR:
  470.                sA = 1.0F - ctx->Color.BlendColor[3];
  471.                break;
  472.             case GL_CONSTANT_ALPHA:
  473.                sA = ctx->Color.BlendColor[3];
  474.                break;
  475.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  476.                sA = 1.0F - ctx->Color.BlendColor[3];
  477.                break;
  478.             case GL_SRC_COLOR: /* GL_NV_blend_square */
  479.                sA = (GLfloat) As * ascale;
  480.                break;
  481.             case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
  482.                sA = 1.0F - (GLfloat) As * ascale;
  483.                break;
  484.             default:
  485.                /* this should never happen */
  486.                sA = 0.0F;
  487.                _mesa_problem(ctx, "Bad blend source A factor in do_blend");
  488.          }
  489.  
  490.          /* Dest RGB factor */
  491.          switch (ctx->Color.BlendDstRGB) {
  492.             case GL_ZERO:
  493.                dR = dG = dB = 0.0F;
  494.                break;
  495.             case GL_ONE:
  496.                dR = dG = dB = 1.0F;
  497.                break;
  498.             case GL_SRC_COLOR:
  499.                dR = (GLfloat) Rs * rscale;
  500.                dG = (GLfloat) Gs * gscale;
  501.                dB = (GLfloat) Bs * bscale;
  502.                break;
  503.             case GL_ONE_MINUS_SRC_COLOR:
  504.                dR = 1.0F - (GLfloat) Rs * rscale;
  505.                dG = 1.0F - (GLfloat) Gs * gscale;
  506.                dB = 1.0F - (GLfloat) Bs * bscale;
  507.                break;
  508.             case GL_SRC_ALPHA:
  509.                dR = dG = dB = (GLfloat) As * ascale;
  510.                break;
  511.             case GL_ONE_MINUS_SRC_ALPHA:
  512.                dR = dG = dB = 1.0F - (GLfloat) As * ascale;
  513.                break;
  514.             case GL_DST_ALPHA:
  515.                dR = dG = dB = (GLfloat) Ad * ascale;
  516.                break;
  517.             case GL_ONE_MINUS_DST_ALPHA:
  518.                dR = dG = dB = 1.0F - (GLfloat) Ad * ascale;
  519.                break;
  520.             case GL_CONSTANT_COLOR:
  521.                dR = ctx->Color.BlendColor[0];
  522.                dG = ctx->Color.BlendColor[1];
  523.                dB = ctx->Color.BlendColor[2];
  524.                break;
  525.             case GL_ONE_MINUS_CONSTANT_COLOR:
  526.                dR = 1.0F - ctx->Color.BlendColor[0];
  527.                dG = 1.0F - ctx->Color.BlendColor[1];
  528.                dB = 1.0F - ctx->Color.BlendColor[2];
  529.                break;
  530.             case GL_CONSTANT_ALPHA:
  531.                dR = dG = dB = ctx->Color.BlendColor[3];
  532.                break;
  533.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  534.                dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
  535.                break;
  536.             case GL_DST_COLOR: /* GL_NV_blend_square */
  537.                dR = (GLfloat) Rd * rscale;
  538.                dG = (GLfloat) Gd * gscale;
  539.                dB = (GLfloat) Bd * bscale;
  540.                break;
  541.             case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
  542.                dR = 1.0F - (GLfloat) Rd * rscale;
  543.                dG = 1.0F - (GLfloat) Gd * gscale;
  544.                dB = 1.0F - (GLfloat) Bd * bscale;
  545.                break;
  546.             default:
  547.                /* this should never happen */
  548.                dR = dG = dB = 0.0F;
  549.                _mesa_problem(ctx, "Bad blend dest RGB factor in do_blend");
  550.          }
  551.  
  552.          /* Dest Alpha factor */
  553.          switch (ctx->Color.BlendDstA) {
  554.             case GL_ZERO:
  555.                dA = 0.0F;
  556.                break;
  557.             case GL_ONE:
  558.                dA = 1.0F;
  559.                break;
  560.             case GL_SRC_COLOR:
  561.                dA = (GLfloat) As * ascale;
  562.                break;
  563.             case GL_ONE_MINUS_SRC_COLOR:
  564.                dA = 1.0F - (GLfloat) As * ascale;
  565.                break;
  566.             case GL_SRC_ALPHA:
  567.                dA = (GLfloat) As * ascale;
  568.                break;
  569.             case GL_ONE_MINUS_SRC_ALPHA:
  570.                dA = 1.0F - (GLfloat) As * ascale;
  571.                break;
  572.             case GL_DST_ALPHA:
  573.                dA = (GLfloat) Ad * ascale;
  574.                break;
  575.             case GL_ONE_MINUS_DST_ALPHA:
  576.                dA = 1.0F - (GLfloat) Ad * ascale;
  577.                break;
  578.             case GL_CONSTANT_COLOR:
  579.                dA = ctx->Color.BlendColor[3];
  580.                break;
  581.             case GL_ONE_MINUS_CONSTANT_COLOR:
  582.                dA = 1.0F - ctx->Color.BlendColor[3];
  583.                break;
  584.             case GL_CONSTANT_ALPHA:
  585.                dA = ctx->Color.BlendColor[3];
  586.                break;
  587.             case GL_ONE_MINUS_CONSTANT_ALPHA:
  588.                dA = 1.0F - ctx->Color.BlendColor[3];
  589.                break;
  590.             case GL_DST_COLOR: /* GL_NV_blend_square */
  591.                dA = (GLfloat) Ad * ascale;
  592.                break;
  593.             case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
  594.                dA = 1.0F - (GLfloat) Ad * ascale;
  595.                break;
  596.             default:
  597.                /* this should never happen */
  598.                dA = 0.0F;
  599.                _mesa_problem(ctx, "Bad blend dest A factor in do_blend");
  600.                return;
  601.          }
  602.  
  603.          /* Due to round-off problems we have to clamp against zero. */
  604.          /* Optimization: we don't have to do this for all src & dst factors */
  605.          if (dA < 0.0F)  dA = 0.0F;
  606.          if (dR < 0.0F)  dR = 0.0F;
  607.          if (dG < 0.0F)  dG = 0.0F;
  608.          if (dB < 0.0F)  dB = 0.0F;
  609.          if (sA < 0.0F)  sA = 0.0F;
  610.          if (sR < 0.0F)  sR = 0.0F;
  611.          if (sG < 0.0F)  sG = 0.0F;
  612.          if (sB < 0.0F)  sB = 0.0F;
  613.  
  614.          ASSERT( sR <= 1.0 );
  615.          ASSERT( sG <= 1.0 );
  616.          ASSERT( sB <= 1.0 );
  617.          ASSERT( sA <= 1.0 );
  618.          ASSERT( dR <= 1.0 );
  619.          ASSERT( dG <= 1.0 );
  620.          ASSERT( dB <= 1.0 );
  621.          ASSERT( dA <= 1.0 );
  622.  
  623.          /* compute blended color */
  624. #if CHAN_TYPE == GL_FLOAT
  625.          if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
  626.             r = Rs * sR + Rd * dR;
  627.             g = Gs * sG + Gd * dG;
  628.             b = Bs * sB + Bd * dB;
  629.             a = As * sA + Ad * dA;
  630.          }
  631.          else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
  632.             r = Rs * sR - Rd * dR;
  633.             g = Gs * sG - Gd * dG;
  634.             b = Bs * sB - Bd * dB;
  635.             a = As * sA - Ad * dA;
  636.          }
  637.          else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
  638.             r = Rd * dR - Rs * sR;
  639.             g = Gd * dG - Gs * sG;
  640.             b = Bd * dB - Bs * sB;
  641.             a = Ad * dA - As * sA;
  642.          }
  643.          else {
  644.             /* should never get here */
  645.             r = g = b = a = 0.0F;  /* silence uninitialized var warning */
  646.             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
  647.          }
  648.  
  649.          /* final clamping */
  650.          rgba[i][RCOMP] = MAX2( r, 0.0F );
  651.          rgba[i][GCOMP] = MAX2( g, 0.0F );
  652.          rgba[i][BCOMP] = MAX2( b, 0.0F );
  653.          rgba[i][ACOMP] = CLAMP( a, 0.0F, CHAN_MAXF );
  654. #else
  655.          if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
  656.             r = Rs * sR + Rd * dR + 0.5F;
  657.             g = Gs * sG + Gd * dG + 0.5F;
  658.             b = Bs * sB + Bd * dB + 0.5F;
  659.             a = As * sA + Ad * dA + 0.5F;
  660.          }
  661.          else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
  662.             r = Rs * sR - Rd * dR + 0.5F;
  663.             g = Gs * sG - Gd * dG + 0.5F;
  664.             b = Bs * sB - Bd * dB + 0.5F;
  665.             a = As * sA - Ad * dA + 0.5F;
  666.          }
  667.          else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
  668.             r = Rd * dR - Rs * sR + 0.5F;
  669.             g = Gd * dG - Gs * sG + 0.5F;
  670.             b = Bd * dB - Bs * sB + 0.5F;
  671.             a = Ad * dA - As * sA + 0.5F;
  672.          }
  673.          else {
  674.             /* should never get here */
  675.             r = g = b = a = 0.0F;  /* silence uninitialized var warning */
  676.             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
  677.          }
  678.  
  679.          /* final clamping */
  680.          rgba[i][RCOMP] = (GLchan) (GLint) CLAMP( r, 0.0F, CHAN_MAXF );
  681.          rgba[i][GCOMP] = (GLchan) (GLint) CLAMP( g, 0.0F, CHAN_MAXF );
  682.          rgba[i][BCOMP] = (GLchan) (GLint) CLAMP( b, 0.0F, CHAN_MAXF );
  683.          rgba[i][ACOMP] = (GLchan) (GLint) CLAMP( a, 0.0F, CHAN_MAXF );
  684. #endif
  685.       }
  686.    }
  687. }
  688.  
  689.  
  690.  
  691.  
  692.  
  693. /*
  694.  * Analyze current blending parameters to pick fastest blending function.
  695.  * Result: the ctx->Color.BlendFunc pointer is updated.
  696.  */
  697. void _swrast_choose_blend_func( GLcontext *ctx )
  698. {
  699.    const GLenum eq = ctx->Color.BlendEquation;
  700.    const GLenum srcRGB = ctx->Color.BlendSrcRGB;
  701.    const GLenum dstRGB = ctx->Color.BlendDstRGB;
  702.    const GLenum srcA = ctx->Color.BlendSrcA;
  703.    const GLenum dstA = ctx->Color.BlendDstA;
  704.  
  705.    if (srcRGB != srcA || dstRGB != dstA) {
  706.       SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
  707.    }
  708.    else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
  709.             && dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
  710. #if defined(USE_MMX_ASM)
  711.       if ( cpu_has_mmx ) {
  712.          SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_transparency;
  713.       }
  714.       else
  715. #endif
  716.      SWRAST_CONTEXT(ctx)->BlendFunc = blend_transparency;
  717.    }
  718.    else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
  719. #if defined(USE_MMX_ASM)
  720.       if ( cpu_has_mmx ) {
  721.          SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_add;
  722.       }
  723.       else
  724. #endif
  725.          SWRAST_CONTEXT(ctx)->BlendFunc = blend_add;
  726.    }
  727.    else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
  728.          && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
  729.         ||
  730.         ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
  731.          && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
  732. #if defined(USE_MMX_ASM)
  733.       if ( cpu_has_mmx ) {
  734.          SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_modulate;
  735.       }
  736.       else
  737. #endif
  738.          SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate;
  739.    }
  740.    else if (eq==GL_MIN_EXT) {
  741. #if defined(USE_MMX_ASM)
  742.       if ( cpu_has_mmx ) {
  743.          SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_min;
  744.       }
  745.       else
  746. #endif
  747.          SWRAST_CONTEXT(ctx)->BlendFunc = blend_min;
  748.    }
  749.    else if (eq==GL_MAX_EXT) {
  750. #if defined(USE_MMX_ASM)
  751.       if ( cpu_has_mmx ) {
  752.          SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_max;
  753.       }
  754.       else
  755. #endif
  756.          SWRAST_CONTEXT(ctx)->BlendFunc = blend_max;
  757.    }
  758.    else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
  759.       SWRAST_CONTEXT(ctx)->BlendFunc = blend_noop;
  760.    }
  761.    else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
  762.       SWRAST_CONTEXT(ctx)->BlendFunc = blend_replace;
  763.    }
  764.    else {
  765.       SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
  766.    }
  767. }
  768.  
  769.  
  770.  
  771. /*
  772.  * Apply the blending operator to a span of pixels.
  773.  * We can handle horizontal runs of pixels (spans) or arrays of x/y
  774.  * pixel coordinates.
  775.  */
  776. void
  777. _mesa_blend_span( GLcontext *ctx, const struct sw_span *span,
  778.                   GLchan rgba[][4] )
  779. {
  780.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  781.    GLchan framebuffer[MAX_WIDTH][4];
  782.  
  783.    ASSERT(span->end <= MAX_WIDTH);
  784.    ASSERT(span->arrayMask & SPAN_RGBA);
  785.    ASSERT(!ctx->Color.ColorLogicOpEnabled);
  786.  
  787.    /* Read span of current frame buffer pixels */
  788.    if (span->arrayMask & SPAN_XY) {
  789.       /* array of x/y pixel coords */
  790.       (*swrast->Driver.ReadRGBAPixels)( ctx, span->end,
  791.                                         span->array->x, span->array->y,
  792.                                         framebuffer, span->array->mask );
  793.       if (swrast->_RasterMask & ALPHABUF_BIT) {
  794.          _mesa_read_alpha_pixels( ctx, span->end,
  795.                                   span->array->x, span->array->y,
  796.                                   framebuffer, span->array->mask );
  797.       }
  798.    }
  799.    else {
  800.       /* horizontal run of pixels */
  801.       _mesa_read_rgba_span( ctx, ctx->DrawBuffer, span->end,
  802.                             span->x, span->y, framebuffer );
  803.    }
  804.  
  805.    SWRAST_CONTEXT(ctx)->BlendFunc( ctx, span->end, span->array->mask, rgba,
  806.                    (const GLchan (*)[4]) framebuffer );
  807. }
  808.