Home | History | Annotate | Download | only in swrast
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 
     26 /**
     27  * \file swrast/s_blend.c
     28  * \brief software blending.
     29  * \author Brian Paul
     30  *
     31  * Only a few blend modes have been optimized (min, max, transparency, add)
     32  * more optimized cases can easily be added if needed.
     33  * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example.
     34  */
     35 
     36 
     37 
     38 #include "main/glheader.h"
     39 #include "main/context.h"
     40 #include "main/colormac.h"
     41 #include "main/macros.h"
     42 
     43 #include "s_blend.h"
     44 #include "s_context.h"
     45 #include "s_span.h"
     46 
     47 
     48 #if defined(USE_MMX_ASM)
     49 #include "x86/mmx.h"
     50 #include "x86/common_x86_asm.h"
     51 #endif
     52 
     53 
     54 /**
     55  * Integer divide by 255
     56  * Declare "int divtemp" before using.
     57  * This satisfies Glean and should be reasonably fast.
     58  * Contributed by Nathan Hand.
     59  */
     60 #define DIV255(X)  (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16)
     61 
     62 
     63 
     64 /**
     65  * Special case for glBlendFunc(GL_ZERO, GL_ONE).
     66  * No-op means the framebuffer values remain unchanged.
     67  * Any chanType ok.
     68  */
     69 static void
     70 blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[],
     71            GLvoid *src, const GLvoid *dst, GLenum chanType)
     72 {
     73    GLint bytes;
     74 
     75    assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
     76    assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
     77    assert(ctx->Color.Blend[0].SrcRGB == GL_ZERO);
     78    assert(ctx->Color.Blend[0].DstRGB == GL_ONE);
     79    (void) ctx;
     80 
     81    /* just memcpy */
     82    if (chanType == GL_UNSIGNED_BYTE)
     83       bytes = 4 * n * sizeof(GLubyte);
     84    else if (chanType == GL_UNSIGNED_SHORT)
     85       bytes = 4 * n * sizeof(GLushort);
     86    else
     87       bytes = 4 * n * sizeof(GLfloat);
     88 
     89    memcpy(src, dst, bytes);
     90 }
     91 
     92 
     93 /**
     94  * Special case for glBlendFunc(GL_ONE, GL_ZERO)
     95  * Any chanType ok.
     96  */
     97 static void
     98 blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[],
     99               GLvoid *src, const GLvoid *dst, GLenum chanType)
    100 {
    101    assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
    102    assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
    103    assert(ctx->Color.Blend[0].SrcRGB == GL_ONE);
    104    assert(ctx->Color.Blend[0].DstRGB == GL_ZERO);
    105    (void) ctx;
    106    (void) n;
    107    (void) mask;
    108    (void) src;
    109    (void) dst;
    110 }
    111 
    112 
    113 /**
    114  * Common transparency blending mode:
    115  * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
    116  */
    117 static void
    118 blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[],
    119                          GLvoid *src, const GLvoid *dst, GLenum chanType)
    120 {
    121    GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
    122    const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
    123    GLuint i;
    124 
    125    assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
    126    assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
    127    assert(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
    128    assert(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
    129    assert(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
    130    assert(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
    131    assert(chanType == GL_UNSIGNED_BYTE);
    132 
    133    (void) ctx;
    134 
    135    for (i = 0; i < n; i++) {
    136       if (mask[i]) {
    137          const GLint t = rgba[i][ACOMP];  /* t is in [0, 255] */
    138          if (t == 0) {
    139             /* 0% alpha */
    140             COPY_4UBV(rgba[i], dest[i]);
    141          }
    142          else if (t != 255) {
    143 	    GLint divtemp;
    144             const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP];
    145             const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP];
    146             const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP];
    147             const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP];
    148             assert(r <= 255);
    149             assert(g <= 255);
    150             assert(b <= 255);
    151             assert(a <= 255);
    152             rgba[i][RCOMP] = (GLubyte) r;
    153             rgba[i][GCOMP] = (GLubyte) g;
    154             rgba[i][BCOMP] = (GLubyte) b;
    155             rgba[i][ACOMP] = (GLubyte) a;
    156          }
    157       }
    158    }
    159 }
    160 
    161 
    162 static void
    163 blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[],
    164                           GLvoid *src, const GLvoid *dst, GLenum chanType)
    165 {
    166    GLushort (*rgba)[4] = (GLushort (*)[4]) src;
    167    const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
    168    GLuint i;
    169 
    170    assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
    171    assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
    172    assert(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
    173    assert(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
    174    assert(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
    175    assert(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
    176    assert(chanType == GL_UNSIGNED_SHORT);
    177 
    178    (void) ctx;
    179 
    180    for (i = 0; i < n; i++) {
    181       if (mask[i]) {
    182          const GLint t = rgba[i][ACOMP];
    183          if (t == 0) {
    184             /* 0% alpha */
    185             COPY_4V(rgba[i], dest[i]);
    186          }
    187          else if (t != 65535) {
    188             const GLfloat tt = (GLfloat) t / 65535.0F;
    189             GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]);
    190             GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]);
    191             GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]);
    192             GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]);
    193             ASSIGN_4V(rgba[i], r, g, b, a);
    194          }
    195       }
    196    }
    197 }
    198 
    199 
    200 static void
    201 blend_transparency_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
    202                          GLvoid *src, const GLvoid *dst, GLenum chanType)
    203 {
    204    GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
    205    const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
    206    GLuint i;
    207 
    208    assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
    209    assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
    210    assert(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
    211    assert(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
    212    assert(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
    213    assert(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
    214    assert(chanType == GL_FLOAT);
    215 
    216    (void) ctx;
    217 
    218    for (i = 0; i < n; i++) {
    219       if (mask[i]) {
    220          const GLfloat t = rgba[i][ACOMP];  /* t in [0, 1] */
    221          if (t == 0.0F) {
    222             /* 0% alpha */
    223             COPY_4V(rgba[i], dest[i]);
    224          }
    225          else if (t != 1.0F) {
    226             GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP];
    227             GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP];
    228             GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP];
    229             GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP];
    230             ASSIGN_4V(rgba[i], r, g, b, a);
    231          }
    232       }
    233    }
    234 }
    235 
    236 
    237 
    238 /**
    239  * Add src and dest: glBlendFunc(GL_ONE, GL_ONE).
    240  * Any chanType ok.
    241  */
    242 static void
    243 blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[],
    244           GLvoid *src, const GLvoid *dst, GLenum chanType)
    245 {
    246    GLuint i;
    247 
    248    assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
    249    assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
    250    assert(ctx->Color.Blend[0].SrcRGB == GL_ONE);
    251    assert(ctx->Color.Blend[0].DstRGB == GL_ONE);
    252    (void) ctx;
    253 
    254    if (chanType == GL_UNSIGNED_BYTE) {
    255       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
    256       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
    257       for (i=0;i<n;i++) {
    258          if (mask[i]) {
    259             GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
    260             GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
    261             GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
    262             GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
    263             rgba[i][RCOMP] = (GLubyte) MIN2( r, 255 );
    264             rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 );
    265             rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 );
    266             rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 );
    267          }
    268       }
    269    }
    270    else if (chanType == GL_UNSIGNED_SHORT) {
    271       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
    272       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
    273       for (i=0;i<n;i++) {
    274          if (mask[i]) {
    275             GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
    276             GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
    277             GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
    278             GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
    279             rgba[i][RCOMP] = (GLshort) MIN2( r, 255 );
    280             rgba[i][GCOMP] = (GLshort) MIN2( g, 255 );
    281             rgba[i][BCOMP] = (GLshort) MIN2( b, 255 );
    282             rgba[i][ACOMP] = (GLshort) MIN2( a, 255 );
    283          }
    284       }
    285    }
    286    else {
    287       GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
    288       const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
    289       assert(chanType == GL_FLOAT);
    290       for (i=0;i<n;i++) {
    291          if (mask[i]) {
    292             /* don't RGB clamp to max */
    293             rgba[i][RCOMP] += dest[i][RCOMP];
    294             rgba[i][GCOMP] += dest[i][GCOMP];
    295             rgba[i][BCOMP] += dest[i][BCOMP];
    296             rgba[i][ACOMP] += dest[i][ACOMP];
    297          }
    298       }
    299    }
    300 }
    301 
    302 
    303 
    304 /**
    305  * Blend min function.
    306  * Any chanType ok.
    307  */
    308 static void
    309 blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[],
    310           GLvoid *src, const GLvoid *dst, GLenum chanType)
    311 {
    312    GLuint i;
    313    assert(ctx->Color.Blend[0].EquationRGB == GL_MIN);
    314    assert(ctx->Color.Blend[0].EquationA == GL_MIN);
    315    (void) ctx;
    316 
    317    if (chanType == GL_UNSIGNED_BYTE) {
    318       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
    319       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
    320       for (i=0;i<n;i++) {
    321          if (mask[i]) {
    322             rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
    323             rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
    324             rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
    325             rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
    326          }
    327       }
    328    }
    329    else if (chanType == GL_UNSIGNED_SHORT) {
    330       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
    331       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
    332       for (i=0;i<n;i++) {
    333          if (mask[i]) {
    334             rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
    335             rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
    336             rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
    337             rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
    338          }
    339       }
    340    }
    341    else {
    342       GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
    343       const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
    344       assert(chanType == GL_FLOAT);
    345       for (i=0;i<n;i++) {
    346          if (mask[i]) {
    347             rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
    348             rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
    349             rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
    350             rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
    351          }
    352       }
    353    }
    354 }
    355 
    356 
    357 /**
    358  * Blend max function.
    359  * Any chanType ok.
    360  */
    361 static void
    362 blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[],
    363           GLvoid *src, const GLvoid *dst, GLenum chanType)
    364 {
    365    GLuint i;
    366    assert(ctx->Color.Blend[0].EquationRGB == GL_MAX);
    367    assert(ctx->Color.Blend[0].EquationA == GL_MAX);
    368    (void) ctx;
    369 
    370    if (chanType == GL_UNSIGNED_BYTE) {
    371       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
    372       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
    373       for (i=0;i<n;i++) {
    374          if (mask[i]) {
    375             rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
    376             rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
    377             rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
    378             rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
    379          }
    380       }
    381    }
    382    else if (chanType == GL_UNSIGNED_SHORT) {
    383       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
    384       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
    385       for (i=0;i<n;i++) {
    386          if (mask[i]) {
    387             rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
    388             rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
    389             rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
    390             rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
    391          }
    392       }
    393    }
    394    else {
    395       GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
    396       const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
    397       assert(chanType == GL_FLOAT);
    398       for (i=0;i<n;i++) {
    399          if (mask[i]) {
    400             rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
    401             rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
    402             rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
    403             rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
    404          }
    405       }
    406    }
    407 }
    408 
    409 
    410 
    411 /**
    412  * Modulate:  result = src * dest
    413  * Any chanType ok.
    414  */
    415 static void
    416 blend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[],
    417                GLvoid *src, const GLvoid *dst, GLenum chanType)
    418 {
    419    GLuint i;
    420    (void) ctx;
    421 
    422    if (chanType == GL_UNSIGNED_BYTE) {
    423       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
    424       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
    425       for (i=0;i<n;i++) {
    426          if (mask[i]) {
    427 	    GLint divtemp;
    428             rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]);
    429             rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]);
    430             rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]);
    431             rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]);
    432          }
    433       }
    434    }
    435    else if (chanType == GL_UNSIGNED_SHORT) {
    436       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
    437       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
    438       for (i=0;i<n;i++) {
    439          if (mask[i]) {
    440             rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16;
    441             rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16;
    442             rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16;
    443             rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16;
    444          }
    445       }
    446    }
    447    else {
    448       GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
    449       const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
    450       assert(chanType == GL_FLOAT);
    451       for (i=0;i<n;i++) {
    452          if (mask[i]) {
    453             rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
    454             rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
    455             rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
    456             rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
    457          }
    458       }
    459    }
    460 }
    461 
    462 
    463 /**
    464  * Do any blending operation, using floating point.
    465  * \param n  number of pixels
    466  * \param mask  fragment writemask array
    467  * \param rgba  array of incoming (and modified) pixels
    468  * \param dest  array of pixels from the dest color buffer
    469  */
    470 static void
    471 blend_general_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
    472                     GLfloat rgba[][4], GLfloat dest[][4],
    473                     GLenum chanType)
    474 {
    475    GLuint i;
    476 
    477    for (i = 0; i < n; i++) {
    478       if (mask[i]) {
    479          /* Incoming/source Color */
    480          const GLfloat Rs = rgba[i][RCOMP];
    481          const GLfloat Gs = rgba[i][GCOMP];
    482          const GLfloat Bs = rgba[i][BCOMP];
    483          const GLfloat As = rgba[i][ACOMP];
    484 
    485          /* Frame buffer/dest color */
    486          const GLfloat Rd = dest[i][RCOMP];
    487          const GLfloat Gd = dest[i][GCOMP];
    488          const GLfloat Bd = dest[i][BCOMP];
    489          const GLfloat Ad = dest[i][ACOMP];
    490 
    491          GLfloat sR, sG, sB, sA;  /* Source factor */
    492          GLfloat dR, dG, dB, dA;  /* Dest factor */
    493          GLfloat r, g, b, a;      /* result color */
    494 
    495          /* XXX for the case of constant blend terms we could init
    496           * the sX and dX variables just once before the loop.
    497           */
    498 
    499          /* Source RGB factor */
    500          switch (ctx->Color.Blend[0].SrcRGB) {
    501             case GL_ZERO:
    502                sR = sG = sB = 0.0F;
    503                break;
    504             case GL_ONE:
    505                sR = sG = sB = 1.0F;
    506                break;
    507             case GL_DST_COLOR:
    508                sR = Rd;
    509                sG = Gd;
    510                sB = Bd;
    511                break;
    512             case GL_ONE_MINUS_DST_COLOR:
    513                sR = 1.0F - Rd;
    514                sG = 1.0F - Gd;
    515                sB = 1.0F - Bd;
    516                break;
    517             case GL_SRC_ALPHA:
    518                sR = sG = sB = As;
    519                break;
    520             case GL_ONE_MINUS_SRC_ALPHA:
    521                sR = sG = sB = 1.0F - As;
    522                break;
    523             case GL_DST_ALPHA:
    524                sR = sG = sB = Ad;
    525                break;
    526             case GL_ONE_MINUS_DST_ALPHA:
    527                sR = sG = sB = 1.0F - Ad;
    528                break;
    529             case GL_SRC_ALPHA_SATURATE:
    530                if (As < 1.0F - Ad) {
    531                   sR = sG = sB = As;
    532                }
    533                else {
    534                   sR = sG = sB = 1.0F - Ad;
    535                }
    536                break;
    537             case GL_CONSTANT_COLOR:
    538                sR = ctx->Color.BlendColor[0];
    539                sG = ctx->Color.BlendColor[1];
    540                sB = ctx->Color.BlendColor[2];
    541                break;
    542             case GL_ONE_MINUS_CONSTANT_COLOR:
    543                sR = 1.0F - ctx->Color.BlendColor[0];
    544                sG = 1.0F - ctx->Color.BlendColor[1];
    545                sB = 1.0F - ctx->Color.BlendColor[2];
    546                break;
    547             case GL_CONSTANT_ALPHA:
    548                sR = sG = sB = ctx->Color.BlendColor[3];
    549                break;
    550             case GL_ONE_MINUS_CONSTANT_ALPHA:
    551                sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
    552                break;
    553             case GL_SRC_COLOR:
    554                sR = Rs;
    555                sG = Gs;
    556                sB = Bs;
    557                break;
    558             case GL_ONE_MINUS_SRC_COLOR:
    559                sR = 1.0F - Rs;
    560                sG = 1.0F - Gs;
    561                sB = 1.0F - Bs;
    562                break;
    563             default:
    564                /* this should never happen */
    565                _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float");
    566                return;
    567          }
    568 
    569          /* Source Alpha factor */
    570          switch (ctx->Color.Blend[0].SrcA) {
    571             case GL_ZERO:
    572                sA = 0.0F;
    573                break;
    574             case GL_ONE:
    575                sA = 1.0F;
    576                break;
    577             case GL_DST_COLOR:
    578                sA = Ad;
    579                break;
    580             case GL_ONE_MINUS_DST_COLOR:
    581                sA = 1.0F - Ad;
    582                break;
    583             case GL_SRC_ALPHA:
    584                sA = As;
    585                break;
    586             case GL_ONE_MINUS_SRC_ALPHA:
    587                sA = 1.0F - As;
    588                break;
    589             case GL_DST_ALPHA:
    590                sA = Ad;
    591                break;
    592             case GL_ONE_MINUS_DST_ALPHA:
    593                sA = 1.0F - Ad;
    594                break;
    595             case GL_SRC_ALPHA_SATURATE:
    596                sA = 1.0;
    597                break;
    598             case GL_CONSTANT_COLOR:
    599                sA = ctx->Color.BlendColor[3];
    600                break;
    601             case GL_ONE_MINUS_CONSTANT_COLOR:
    602                sA = 1.0F - ctx->Color.BlendColor[3];
    603                break;
    604             case GL_CONSTANT_ALPHA:
    605                sA = ctx->Color.BlendColor[3];
    606                break;
    607             case GL_ONE_MINUS_CONSTANT_ALPHA:
    608                sA = 1.0F - ctx->Color.BlendColor[3];
    609                break;
    610             case GL_SRC_COLOR:
    611                sA = As;
    612                break;
    613             case GL_ONE_MINUS_SRC_COLOR:
    614                sA = 1.0F - As;
    615                break;
    616             default:
    617                /* this should never happen */
    618                sA = 0.0F;
    619                _mesa_problem(ctx, "Bad blend source A factor in blend_general_float");
    620                return;
    621          }
    622 
    623          /* Dest RGB factor */
    624          switch (ctx->Color.Blend[0].DstRGB) {
    625             case GL_ZERO:
    626                dR = dG = dB = 0.0F;
    627                break;
    628             case GL_ONE:
    629                dR = dG = dB = 1.0F;
    630                break;
    631             case GL_SRC_COLOR:
    632                dR = Rs;
    633                dG = Gs;
    634                dB = Bs;
    635                break;
    636             case GL_ONE_MINUS_SRC_COLOR:
    637                dR = 1.0F - Rs;
    638                dG = 1.0F - Gs;
    639                dB = 1.0F - Bs;
    640                break;
    641             case GL_SRC_ALPHA:
    642                dR = dG = dB = As;
    643                break;
    644             case GL_ONE_MINUS_SRC_ALPHA:
    645                dR = dG = dB = 1.0F - As;
    646                break;
    647             case GL_DST_ALPHA:
    648                dR = dG = dB = Ad;
    649                break;
    650             case GL_ONE_MINUS_DST_ALPHA:
    651                dR = dG = dB = 1.0F - Ad;
    652                break;
    653             case GL_CONSTANT_COLOR:
    654                dR = ctx->Color.BlendColor[0];
    655                dG = ctx->Color.BlendColor[1];
    656                dB = ctx->Color.BlendColor[2];
    657                break;
    658             case GL_ONE_MINUS_CONSTANT_COLOR:
    659                dR = 1.0F - ctx->Color.BlendColor[0];
    660                dG = 1.0F - ctx->Color.BlendColor[1];
    661                dB = 1.0F - ctx->Color.BlendColor[2];
    662                break;
    663             case GL_CONSTANT_ALPHA:
    664                dR = dG = dB = ctx->Color.BlendColor[3];
    665                break;
    666             case GL_ONE_MINUS_CONSTANT_ALPHA:
    667                dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
    668                break;
    669             case GL_DST_COLOR:
    670                dR = Rd;
    671                dG = Gd;
    672                dB = Bd;
    673                break;
    674             case GL_ONE_MINUS_DST_COLOR:
    675                dR = 1.0F - Rd;
    676                dG = 1.0F - Gd;
    677                dB = 1.0F - Bd;
    678                break;
    679             default:
    680                /* this should never happen */
    681                dR = dG = dB = 0.0F;
    682                _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general_float");
    683                return;
    684          }
    685 
    686          /* Dest Alpha factor */
    687          switch (ctx->Color.Blend[0].DstA) {
    688             case GL_ZERO:
    689                dA = 0.0F;
    690                break;
    691             case GL_ONE:
    692                dA = 1.0F;
    693                break;
    694             case GL_SRC_COLOR:
    695                dA = As;
    696                break;
    697             case GL_ONE_MINUS_SRC_COLOR:
    698                dA = 1.0F - As;
    699                break;
    700             case GL_SRC_ALPHA:
    701                dA = As;
    702                break;
    703             case GL_ONE_MINUS_SRC_ALPHA:
    704                dA = 1.0F - As;
    705                break;
    706             case GL_DST_ALPHA:
    707                dA = Ad;
    708                break;
    709             case GL_ONE_MINUS_DST_ALPHA:
    710                dA = 1.0F - Ad;
    711                break;
    712             case GL_CONSTANT_COLOR:
    713                dA = ctx->Color.BlendColor[3];
    714                break;
    715             case GL_ONE_MINUS_CONSTANT_COLOR:
    716                dA = 1.0F - ctx->Color.BlendColor[3];
    717                break;
    718             case GL_CONSTANT_ALPHA:
    719                dA = ctx->Color.BlendColor[3];
    720                break;
    721             case GL_ONE_MINUS_CONSTANT_ALPHA:
    722                dA = 1.0F - ctx->Color.BlendColor[3];
    723                break;
    724             case GL_DST_COLOR:
    725                dA = Ad;
    726                break;
    727             case GL_ONE_MINUS_DST_COLOR:
    728                dA = 1.0F - Ad;
    729                break;
    730             default:
    731                /* this should never happen */
    732                dA = 0.0F;
    733                _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float");
    734                return;
    735          }
    736 
    737          /* compute the blended RGB */
    738          switch (ctx->Color.Blend[0].EquationRGB) {
    739          case GL_FUNC_ADD:
    740             r = Rs * sR + Rd * dR;
    741             g = Gs * sG + Gd * dG;
    742             b = Bs * sB + Bd * dB;
    743             a = As * sA + Ad * dA;
    744             break;
    745          case GL_FUNC_SUBTRACT:
    746             r = Rs * sR - Rd * dR;
    747             g = Gs * sG - Gd * dG;
    748             b = Bs * sB - Bd * dB;
    749             a = As * sA - Ad * dA;
    750             break;
    751          case GL_FUNC_REVERSE_SUBTRACT:
    752             r = Rd * dR - Rs * sR;
    753             g = Gd * dG - Gs * sG;
    754             b = Bd * dB - Bs * sB;
    755             a = Ad * dA - As * sA;
    756             break;
    757          case GL_MIN:
    758 	    r = MIN2( Rd, Rs );
    759 	    g = MIN2( Gd, Gs );
    760 	    b = MIN2( Bd, Bs );
    761             break;
    762          case GL_MAX:
    763 	    r = MAX2( Rd, Rs );
    764 	    g = MAX2( Gd, Gs );
    765 	    b = MAX2( Bd, Bs );
    766             break;
    767 	 default:
    768             /* should never get here */
    769             r = g = b = 0.0F;  /* silence uninitialized var warning */
    770             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
    771             return;
    772          }
    773 
    774          /* compute the blended alpha */
    775          switch (ctx->Color.Blend[0].EquationA) {
    776          case GL_FUNC_ADD:
    777             a = As * sA + Ad * dA;
    778             break;
    779          case GL_FUNC_SUBTRACT:
    780             a = As * sA - Ad * dA;
    781             break;
    782          case GL_FUNC_REVERSE_SUBTRACT:
    783             a = Ad * dA - As * sA;
    784             break;
    785          case GL_MIN:
    786 	    a = MIN2( Ad, As );
    787             break;
    788          case GL_MAX:
    789 	    a = MAX2( Ad, As );
    790             break;
    791          default:
    792             /* should never get here */
    793             a = 0.0F;  /* silence uninitialized var warning */
    794             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
    795             return;
    796          }
    797 
    798          /* final clamping */
    799 #if 0
    800          rgba[i][RCOMP] = MAX2( r, 0.0F );
    801          rgba[i][GCOMP] = MAX2( g, 0.0F );
    802          rgba[i][BCOMP] = MAX2( b, 0.0F );
    803          rgba[i][ACOMP] = CLAMP( a, 0.0F, 1.0F );
    804 #else
    805          ASSIGN_4V(rgba[i], r, g, b, a);
    806 #endif
    807       }
    808    }
    809 }
    810 
    811 
    812 /**
    813  * Do any blending operation, any chanType.
    814  */
    815 static void
    816 blend_general(struct gl_context *ctx, GLuint n, const GLubyte mask[],
    817               void *src, const void *dst, GLenum chanType)
    818 {
    819    GLfloat (*rgbaF)[4], (*destF)[4];
    820 
    821    rgbaF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
    822    destF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
    823    if (!rgbaF || !destF) {
    824       free(rgbaF);
    825       free(destF);
    826       _mesa_error(ctx, GL_OUT_OF_MEMORY, "blending");
    827       return;
    828    }
    829 
    830    if (chanType == GL_UNSIGNED_BYTE) {
    831       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
    832       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
    833       GLuint i;
    834       /* convert ubytes to floats */
    835       for (i = 0; i < n; i++) {
    836          if (mask[i]) {
    837             rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]);
    838             rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]);
    839             rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]);
    840             rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]);
    841             destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]);
    842             destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]);
    843             destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]);
    844             destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]);
    845          }
    846       }
    847       /* do blend */
    848       blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
    849       /* convert back to ubytes */
    850       for (i = 0; i < n; i++) {
    851          if (mask[i])
    852 	   _mesa_unclamped_float_rgba_to_ubyte(rgba[i], rgbaF[i]);
    853       }
    854    }
    855    else if (chanType == GL_UNSIGNED_SHORT) {
    856       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
    857       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
    858       GLuint i;
    859       /* convert ushorts to floats */
    860       for (i = 0; i < n; i++) {
    861          if (mask[i]) {
    862             rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]);
    863             rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]);
    864             rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]);
    865             rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]);
    866             destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]);
    867             destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]);
    868             destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]);
    869             destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]);
    870          }
    871       }
    872       /* do blend */
    873       blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
    874       /* convert back to ushorts */
    875       for (i = 0; i < n; i++) {
    876          if (mask[i]) {
    877             UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]);
    878             UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]);
    879             UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]);
    880             UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]);
    881          }
    882       }
    883    }
    884    else {
    885       blend_general_float(ctx, n, mask, (GLfloat (*)[4]) src,
    886                           (GLfloat (*)[4]) dst, chanType);
    887    }
    888 
    889    free(rgbaF);
    890    free(destF);
    891 }
    892 
    893 
    894 
    895 /**
    896  * Analyze current blending parameters to pick fastest blending function.
    897  * Result: the ctx->Color.BlendFunc pointer is updated.
    898  */
    899 void
    900 _swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType)
    901 {
    902    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    903    const GLenum eq = ctx->Color.Blend[0].EquationRGB;
    904    const GLenum srcRGB = ctx->Color.Blend[0].SrcRGB;
    905    const GLenum dstRGB = ctx->Color.Blend[0].DstRGB;
    906    const GLenum srcA = ctx->Color.Blend[0].SrcA;
    907    const GLenum dstA = ctx->Color.Blend[0].DstA;
    908 
    909    if (ctx->Color.Blend[0].EquationRGB != ctx->Color.Blend[0].EquationA) {
    910       swrast->BlendFunc = blend_general;
    911    }
    912    else if (eq == GL_MIN) {
    913       /* Note: GL_MIN ignores the blending weight factors */
    914 #if defined(USE_MMX_ASM)
    915       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
    916          swrast->BlendFunc = _mesa_mmx_blend_min;
    917       }
    918       else
    919 #endif
    920          swrast->BlendFunc = blend_min;
    921    }
    922    else if (eq == GL_MAX) {
    923       /* Note: GL_MAX ignores the blending weight factors */
    924 #if defined(USE_MMX_ASM)
    925       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
    926          swrast->BlendFunc = _mesa_mmx_blend_max;
    927       }
    928       else
    929 #endif
    930          swrast->BlendFunc = blend_max;
    931    }
    932    else if (srcRGB != srcA || dstRGB != dstA) {
    933       swrast->BlendFunc = blend_general;
    934    }
    935    else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA
    936             && dstRGB == GL_ONE_MINUS_SRC_ALPHA) {
    937 #if defined(USE_MMX_ASM)
    938       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
    939          swrast->BlendFunc = _mesa_mmx_blend_transparency;
    940       }
    941       else
    942 #endif
    943       {
    944          if (chanType == GL_UNSIGNED_BYTE)
    945             swrast->BlendFunc = blend_transparency_ubyte;
    946          else if (chanType == GL_UNSIGNED_SHORT)
    947             swrast->BlendFunc = blend_transparency_ushort;
    948          else
    949             swrast->BlendFunc = blend_transparency_float;
    950       }
    951    }
    952    else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) {
    953 #if defined(USE_MMX_ASM)
    954       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
    955          swrast->BlendFunc = _mesa_mmx_blend_add;
    956       }
    957       else
    958 #endif
    959          swrast->BlendFunc = blend_add;
    960    }
    961    else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT)
    962 	     && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR))
    963 	    ||
    964 	    ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT)
    965 	     && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) {
    966 #if defined(USE_MMX_ASM)
    967       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
    968          swrast->BlendFunc = _mesa_mmx_blend_modulate;
    969       }
    970       else
    971 #endif
    972          swrast->BlendFunc = blend_modulate;
    973    }
    974    else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
    975       swrast->BlendFunc = blend_noop;
    976    }
    977    else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
    978       swrast->BlendFunc = blend_replace;
    979    }
    980    else {
    981       swrast->BlendFunc = blend_general;
    982    }
    983 }
    984 
    985 
    986 
    987 /**
    988  * Apply the blending operator to a span of pixels.
    989  * We can handle horizontal runs of pixels (spans) or arrays of x/y
    990  * pixel coordinates.
    991  */
    992 void
    993 _swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span)
    994 {
    995    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    996    void *rbPixels;
    997 
    998    assert(span->end <= SWRAST_MAX_WIDTH);
    999    assert(span->arrayMask & SPAN_RGBA);
   1000    assert(!ctx->Color.ColorLogicOpEnabled);
   1001 
   1002    rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
   1003 
   1004    swrast->BlendFunc(ctx, span->end, span->array->mask,
   1005                      span->array->rgba, rbPixels, span->array->ChanType);
   1006 }
   1007