Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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