Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.