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.5
  4.  *
  5.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  6.  * Copyright (C) 2009  VMware, Inc.   All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice shall be included
  16.  * in all copies or substantial portions of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  21.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  22.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26.  
  27. #include "main/glheader.h"
  28. #include "main/context.h"
  29. #include "main/colormac.h"
  30. #include "main/imports.h"
  31. #include "main/pixeltransfer.h"
  32. #include "program/prog_instruction.h"
  33.  
  34. #include "s_context.h"
  35. #include "s_texcombine.h"
  36.  
  37.  
  38. /**
  39.  * Pointer to array of float[4]
  40.  * This type makes the code below more concise and avoids a lot of casting.
  41.  */
  42. typedef float (*float4_array)[4];
  43.  
  44.  
  45. /**
  46.  * Return array of texels for given unit.
  47.  */
  48. static INLINE float4_array
  49. get_texel_array(SWcontext *swrast, GLuint unit)
  50. {
  51.    return (float4_array) (swrast->TexelBuffer + unit * MAX_WIDTH * 4);
  52. }
  53.  
  54.  
  55.  
  56. /**
  57.  * Do texture application for:
  58.  *  GL_EXT_texture_env_combine
  59.  *  GL_ARB_texture_env_combine
  60.  *  GL_EXT_texture_env_dot3
  61.  *  GL_ARB_texture_env_dot3
  62.  *  GL_ATI_texture_env_combine3
  63.  *  GL_NV_texture_env_combine4
  64.  *  conventional GL texture env modes
  65.  *
  66.  * \param ctx          rendering context
  67.  * \param unit         the texture combiner unit
  68.  * \param n            number of fragments to process (span width)
  69.  * \param primary_rgba incoming fragment color array
  70.  * \param texelBuffer  pointer to texel colors for all texture units
  71.  *
  72.  * \param rgba         incoming/result fragment colors
  73.  */
  74. static void
  75. texture_combine( struct gl_context *ctx, GLuint unit, GLuint n,
  76.                  const float4_array primary_rgba,
  77.                  const GLfloat *texelBuffer,
  78.                  GLchan (*rgbaChan)[4] )
  79. {
  80.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  81.    const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
  82.    const struct gl_tex_env_combine_state *combine = textureUnit->_CurrentCombine;
  83.    float4_array argRGB[MAX_COMBINER_TERMS];
  84.    float4_array argA[MAX_COMBINER_TERMS];
  85.    const GLfloat scaleRGB = (GLfloat) (1 << combine->ScaleShiftRGB);
  86.    const GLfloat scaleA = (GLfloat) (1 << combine->ScaleShiftA);
  87.    const GLuint numArgsRGB = combine->_NumArgsRGB;
  88.    const GLuint numArgsA = combine->_NumArgsA;
  89.    float4_array ccolor[4], rgba;
  90.    GLuint i, term;
  91.  
  92.    /* alloc temp pixel buffers */
  93.    rgba = (float4_array) malloc(4 * n * sizeof(GLfloat));
  94.    if (!rgba) {
  95.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
  96.       return;
  97.    }
  98.  
  99.    for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
  100.       ccolor[i] = (float4_array) malloc(4 * n * sizeof(GLfloat));
  101.       if (!ccolor[i]) {
  102.          while (i) {
  103.             free(ccolor[i]);
  104.             i--;
  105.          }
  106.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
  107.          return;
  108.       }
  109.    }
  110.  
  111.    for (i = 0; i < n; i++) {
  112.       rgba[i][RCOMP] = CHAN_TO_FLOAT(rgbaChan[i][RCOMP]);
  113.       rgba[i][GCOMP] = CHAN_TO_FLOAT(rgbaChan[i][GCOMP]);
  114.       rgba[i][BCOMP] = CHAN_TO_FLOAT(rgbaChan[i][BCOMP]);
  115.       rgba[i][ACOMP] = CHAN_TO_FLOAT(rgbaChan[i][ACOMP]);
  116.    }
  117.  
  118.    /*
  119.    printf("modeRGB 0x%x  modeA 0x%x  srcRGB1 0x%x  srcA1 0x%x  srcRGB2 0x%x  srcA2 0x%x\n",
  120.           combine->ModeRGB,
  121.           combine->ModeA,
  122.           combine->SourceRGB[0],
  123.           combine->SourceA[0],
  124.           combine->SourceRGB[1],
  125.           combine->SourceA[1]);
  126.    */
  127.  
  128.    /*
  129.     * Do operand setup for up to 4 operands.  Loop over the terms.
  130.     */
  131.    for (term = 0; term < numArgsRGB; term++) {
  132.       const GLenum srcRGB = combine->SourceRGB[term];
  133.       const GLenum operandRGB = combine->OperandRGB[term];
  134.  
  135.       switch (srcRGB) {
  136.          case GL_TEXTURE:
  137.             argRGB[term] = get_texel_array(swrast, unit);
  138.             break;
  139.          case GL_PRIMARY_COLOR:
  140.             argRGB[term] = primary_rgba;
  141.             break;
  142.          case GL_PREVIOUS:
  143.             argRGB[term] = rgba;
  144.             break;
  145.          case GL_CONSTANT:
  146.             {
  147.                float4_array c = ccolor[term];
  148.                GLfloat red   = textureUnit->EnvColor[0];
  149.                GLfloat green = textureUnit->EnvColor[1];
  150.                GLfloat blue  = textureUnit->EnvColor[2];
  151.                GLfloat alpha = textureUnit->EnvColor[3];
  152.                for (i = 0; i < n; i++) {
  153.                   ASSIGN_4V(c[i], red, green, blue, alpha);
  154.                }
  155.                argRGB[term] = ccolor[term];
  156.             }
  157.             break;
  158.          /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
  159.           */
  160.          case GL_ZERO:
  161.             {
  162.                float4_array c = ccolor[term];
  163.                for (i = 0; i < n; i++) {
  164.                   ASSIGN_4V(c[i], 0.0F, 0.0F, 0.0F, 0.0F);
  165.                }
  166.                argRGB[term] = ccolor[term];
  167.             }
  168.             break;
  169.          case GL_ONE:
  170.             {
  171.                float4_array c = ccolor[term];
  172.                for (i = 0; i < n; i++) {
  173.                   ASSIGN_4V(c[i], 1.0F, 1.0F, 1.0F, 1.0F);
  174.                }
  175.                argRGB[term] = ccolor[term];
  176.             }
  177.             break;
  178.          default:
  179.             /* ARB_texture_env_crossbar source */
  180.             {
  181.                const GLuint srcUnit = srcRGB - GL_TEXTURE0;
  182.                ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
  183.                if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
  184.                   goto end;
  185.                argRGB[term] = get_texel_array(swrast, srcUnit);
  186.             }
  187.       }
  188.  
  189.       if (operandRGB != GL_SRC_COLOR) {
  190.          float4_array src = argRGB[term];
  191.          float4_array dst = ccolor[term];
  192.  
  193.          /* point to new arg[term] storage */
  194.          argRGB[term] = ccolor[term];
  195.  
  196.          switch (operandRGB) {
  197.          case GL_ONE_MINUS_SRC_COLOR:
  198.             for (i = 0; i < n; i++) {
  199.                dst[i][RCOMP] = 1.0F - src[i][RCOMP];
  200.                dst[i][GCOMP] = 1.0F - src[i][GCOMP];
  201.                dst[i][BCOMP] = 1.0F - src[i][BCOMP];
  202.             }
  203.             break;
  204.          case GL_SRC_ALPHA:
  205.             for (i = 0; i < n; i++) {
  206.                dst[i][RCOMP] =
  207.                dst[i][GCOMP] =
  208.                dst[i][BCOMP] = src[i][ACOMP];
  209.             }
  210.             break;
  211.          case GL_ONE_MINUS_SRC_ALPHA:
  212.             for (i = 0; i < n; i++) {
  213.                dst[i][RCOMP] =
  214.                dst[i][GCOMP] =
  215.                dst[i][BCOMP] = 1.0F - src[i][ACOMP];
  216.             }
  217.             break;
  218.          default:
  219.             _mesa_problem(ctx, "Bad operandRGB");
  220.          }
  221.       }
  222.    }
  223.  
  224.    /*
  225.     * Set up the argA[term] pointers
  226.     */
  227.    for (term = 0; term < numArgsA; term++) {
  228.       const GLenum srcA = combine->SourceA[term];
  229.       const GLenum operandA = combine->OperandA[term];
  230.  
  231.       switch (srcA) {
  232.          case GL_TEXTURE:
  233.             argA[term] = get_texel_array(swrast, unit);
  234.             break;
  235.          case GL_PRIMARY_COLOR:
  236.             argA[term] = primary_rgba;
  237.             break;
  238.          case GL_PREVIOUS:
  239.             argA[term] = rgba;
  240.             break;
  241.          case GL_CONSTANT:
  242.             {
  243.                float4_array c = ccolor[term];
  244.                GLfloat alpha = textureUnit->EnvColor[3];
  245.                for (i = 0; i < n; i++)
  246.                   c[i][ACOMP] = alpha;
  247.                argA[term] = ccolor[term];
  248.             }
  249.             break;
  250.          /* GL_ATI_texture_env_combine3 allows GL_ZERO & GL_ONE as sources.
  251.           */
  252.          case GL_ZERO:
  253.             {
  254.                float4_array c = ccolor[term];
  255.                for (i = 0; i < n; i++)
  256.                   c[i][ACOMP] = 0.0F;
  257.                argA[term] = ccolor[term];
  258.             }
  259.             break;
  260.          case GL_ONE:
  261.             {
  262.                float4_array c = ccolor[term];
  263.                for (i = 0; i < n; i++)
  264.                   c[i][ACOMP] = 1.0F;
  265.                argA[term] = ccolor[term];
  266.             }
  267.             break;
  268.          default:
  269.             /* ARB_texture_env_crossbar source */
  270.             {
  271.                const GLuint srcUnit = srcA - GL_TEXTURE0;
  272.                ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
  273.                if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
  274.                   goto end;
  275.                argA[term] = get_texel_array(swrast, srcUnit);
  276.             }
  277.       }
  278.  
  279.       if (operandA == GL_ONE_MINUS_SRC_ALPHA) {
  280.          float4_array src = argA[term];
  281.          float4_array dst = ccolor[term];
  282.          argA[term] = ccolor[term];
  283.          for (i = 0; i < n; i++) {
  284.             dst[i][ACOMP] = 1.0F - src[i][ACOMP];
  285.          }
  286.       }
  287.    }
  288.  
  289.    /* RGB channel combine */
  290.    {
  291.       float4_array arg0 = argRGB[0];
  292.       float4_array arg1 = argRGB[1];
  293.       float4_array arg2 = argRGB[2];
  294.       float4_array arg3 = argRGB[3];
  295.  
  296.       switch (combine->ModeRGB) {
  297.       case GL_REPLACE:
  298.          for (i = 0; i < n; i++) {
  299.             rgba[i][RCOMP] = arg0[i][RCOMP] * scaleRGB;
  300.             rgba[i][GCOMP] = arg0[i][GCOMP] * scaleRGB;
  301.             rgba[i][BCOMP] = arg0[i][BCOMP] * scaleRGB;
  302.          }
  303.          break;
  304.       case GL_MODULATE:
  305.          for (i = 0; i < n; i++) {
  306.             rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * scaleRGB;
  307.             rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * scaleRGB;
  308.             rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * scaleRGB;
  309.          }
  310.          break;
  311.       case GL_ADD:
  312.          if (textureUnit->EnvMode == GL_COMBINE4_NV) {
  313.             /* (a * b) + (c * d) */
  314.             for (i = 0; i < n; i++) {
  315.                rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
  316.                                  arg2[i][RCOMP] * arg3[i][RCOMP]) * scaleRGB;
  317.                rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
  318.                                  arg2[i][GCOMP] * arg3[i][GCOMP]) * scaleRGB;
  319.                rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
  320.                                  arg2[i][BCOMP] * arg3[i][BCOMP]) * scaleRGB;
  321.             }
  322.          }
  323.          else {
  324.             /* 2-term addition */
  325.             for (i = 0; i < n; i++) {
  326.                rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * scaleRGB;
  327.                rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * scaleRGB;
  328.                rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * scaleRGB;
  329.             }
  330.          }
  331.          break;
  332.       case GL_ADD_SIGNED:
  333.          if (textureUnit->EnvMode == GL_COMBINE4_NV) {
  334.             /* (a * b) + (c * d) - 0.5 */
  335.             for (i = 0; i < n; i++) {
  336.                rgba[i][RCOMP] = (arg0[i][RCOMP] * arg1[i][RCOMP] +
  337.                                  arg2[i][RCOMP] * arg3[i][RCOMP] - 0.5F) * scaleRGB;
  338.                rgba[i][GCOMP] = (arg0[i][GCOMP] * arg1[i][GCOMP] +
  339.                                  arg2[i][GCOMP] * arg3[i][GCOMP] - 0.5F) * scaleRGB;
  340.                rgba[i][BCOMP] = (arg0[i][BCOMP] * arg1[i][BCOMP] +
  341.                                  arg2[i][BCOMP] * arg3[i][BCOMP] - 0.5F) * scaleRGB;
  342.             }
  343.          }
  344.          else {
  345.             for (i = 0; i < n; i++) {
  346.                rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5F) * scaleRGB;
  347.                rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5F) * scaleRGB;
  348.                rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5F) * scaleRGB;
  349.             }
  350.          }
  351.          break;
  352.       case GL_INTERPOLATE:
  353.          for (i = 0; i < n; i++) {
  354.             rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
  355.                           arg1[i][RCOMP] * (1.0F - arg2[i][RCOMP])) * scaleRGB;
  356.             rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
  357.                           arg1[i][GCOMP] * (1.0F - arg2[i][GCOMP])) * scaleRGB;
  358.             rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
  359.                           arg1[i][BCOMP] * (1.0F - arg2[i][BCOMP])) * scaleRGB;
  360.          }
  361.          break;
  362.       case GL_SUBTRACT:
  363.          for (i = 0; i < n; i++) {
  364.             rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * scaleRGB;
  365.             rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * scaleRGB;
  366.             rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * scaleRGB;
  367.          }
  368.          break;
  369.       case GL_DOT3_RGB_EXT:
  370.       case GL_DOT3_RGBA_EXT:
  371.          /* Do not scale the result by 1 2 or 4 */
  372.          for (i = 0; i < n; i++) {
  373.             GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
  374.                            (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
  375.                            (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
  376.                * 4.0F;
  377.             dot = CLAMP(dot, 0.0F, 1.0F);
  378.             rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
  379.          }
  380.          break;
  381.       case GL_DOT3_RGB:
  382.       case GL_DOT3_RGBA:
  383.          /* DO scale the result by 1 2 or 4 */
  384.          for (i = 0; i < n; i++) {
  385.             GLfloat dot = ((arg0[i][RCOMP] - 0.5F) * (arg1[i][RCOMP] - 0.5F) +
  386.                            (arg0[i][GCOMP] - 0.5F) * (arg1[i][GCOMP] - 0.5F) +
  387.                            (arg0[i][BCOMP] - 0.5F) * (arg1[i][BCOMP] - 0.5F))
  388.                * 4.0F * scaleRGB;
  389.             dot = CLAMP(dot, 0.0F, 1.0F);
  390.             rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = dot;
  391.          }
  392.          break;
  393.       case GL_MODULATE_ADD_ATI:
  394.          for (i = 0; i < n; i++) {
  395.             rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
  396.                               arg1[i][RCOMP]) * scaleRGB;
  397.             rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
  398.                               arg1[i][GCOMP]) * scaleRGB;
  399.             rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
  400.                               arg1[i][BCOMP]) * scaleRGB;
  401.          }
  402.          break;
  403.       case GL_MODULATE_SIGNED_ADD_ATI:
  404.          for (i = 0; i < n; i++) {
  405.             rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) +
  406.                               arg1[i][RCOMP] - 0.5F) * scaleRGB;
  407.             rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) +
  408.                               arg1[i][GCOMP] - 0.5F) * scaleRGB;
  409.             rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) +
  410.                               arg1[i][BCOMP] - 0.5F) * scaleRGB;
  411.          }
  412.          break;
  413.       case GL_MODULATE_SUBTRACT_ATI:
  414.          for (i = 0; i < n; i++) {
  415.             rgba[i][RCOMP] = ((arg0[i][RCOMP] * arg2[i][RCOMP]) -
  416.                               arg1[i][RCOMP]) * scaleRGB;
  417.             rgba[i][GCOMP] = ((arg0[i][GCOMP] * arg2[i][GCOMP]) -
  418.                               arg1[i][GCOMP]) * scaleRGB;
  419.             rgba[i][BCOMP] = ((arg0[i][BCOMP] * arg2[i][BCOMP]) -
  420.                               arg1[i][BCOMP]) * scaleRGB;
  421.          }
  422.          break;
  423.       case GL_BUMP_ENVMAP_ATI:
  424.          /* this produces a fixed rgba color, and the coord calc is done elsewhere */
  425.          for (i = 0; i < n; i++) {
  426.             /* rgba result is 0,0,0,1 */
  427.             rgba[i][RCOMP] = 0.0;
  428.             rgba[i][GCOMP] = 0.0;
  429.             rgba[i][BCOMP] = 0.0;
  430.             rgba[i][ACOMP] = 1.0;
  431.          }
  432.          goto end; /* no alpha processing */
  433.       default:
  434.          _mesa_problem(ctx, "invalid combine mode");
  435.       }
  436.    }
  437.  
  438.    /* Alpha channel combine */
  439.    {
  440.       float4_array arg0 = argA[0];
  441.       float4_array arg1 = argA[1];
  442.       float4_array arg2 = argA[2];
  443.       float4_array arg3 = argA[3];
  444.  
  445.       switch (combine->ModeA) {
  446.       case GL_REPLACE:
  447.          for (i = 0; i < n; i++) {
  448.             rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
  449.          }
  450.          break;
  451.       case GL_MODULATE:
  452.          for (i = 0; i < n; i++) {
  453.             rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
  454.          }
  455.          break;
  456.       case GL_ADD:
  457.          if (textureUnit->EnvMode == GL_COMBINE4_NV) {
  458.             /* (a * b) + (c * d) */
  459.             for (i = 0; i < n; i++) {
  460.                rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
  461.                                  arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
  462.             }
  463.          }
  464.          else {
  465.             /* two-term add */
  466.             for (i = 0; i < n; i++) {
  467.                rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
  468.             }
  469.          }
  470.          break;
  471.       case GL_ADD_SIGNED:
  472.          if (textureUnit->EnvMode == GL_COMBINE4_NV) {
  473.             /* (a * b) + (c * d) - 0.5 */
  474.             for (i = 0; i < n; i++) {
  475.                rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
  476.                                  arg2[i][ACOMP] * arg3[i][ACOMP] -
  477.                                  0.5F) * scaleA;
  478.             }
  479.          }
  480.          else {
  481.             /* a + b - 0.5 */
  482.             for (i = 0; i < n; i++) {
  483.                rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
  484.             }
  485.          }
  486.          break;
  487.       case GL_INTERPOLATE:
  488.          for (i = 0; i < n; i++) {
  489.             rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
  490.                               arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
  491.                * scaleA;
  492.          }
  493.          break;
  494.       case GL_SUBTRACT:
  495.          for (i = 0; i < n; i++) {
  496.             rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
  497.          }
  498.          break;
  499.       case GL_MODULATE_ADD_ATI:
  500.          for (i = 0; i < n; i++) {
  501.             rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
  502.                               + arg1[i][ACOMP]) * scaleA;
  503.          }
  504.          break;
  505.       case GL_MODULATE_SIGNED_ADD_ATI:
  506.          for (i = 0; i < n; i++) {
  507.             rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
  508.                               arg1[i][ACOMP] - 0.5F) * scaleA;
  509.          }
  510.          break;
  511.       case GL_MODULATE_SUBTRACT_ATI:
  512.          for (i = 0; i < n; i++) {
  513.             rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
  514.                               - arg1[i][ACOMP]) * scaleA;
  515.          }
  516.          break;
  517.       default:
  518.          _mesa_problem(ctx, "invalid combine mode");
  519.       }
  520.    }
  521.  
  522.    /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
  523.     * This is kind of a kludge.  It would have been better if the spec
  524.     * were written such that the GL_COMBINE_ALPHA value could be set to
  525.     * GL_DOT3.
  526.     */
  527.    if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
  528.        combine->ModeRGB == GL_DOT3_RGBA) {
  529.       for (i = 0; i < n; i++) {
  530.          rgba[i][ACOMP] = rgba[i][RCOMP];
  531.       }
  532.    }
  533.  
  534.    for (i = 0; i < n; i++) {
  535.       UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
  536.       UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
  537.       UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
  538.       UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
  539.    }
  540.  
  541. end:
  542.    for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
  543.       free(ccolor[i]);
  544.    }
  545.    free(rgba);
  546. }
  547.  
  548.  
  549. /**
  550.  * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
  551.  * See GL_EXT_texture_swizzle.
  552.  */
  553. static void
  554. swizzle_texels(GLuint swizzle, GLuint count, float4_array texels)
  555. {
  556.    const GLuint swzR = GET_SWZ(swizzle, 0);
  557.    const GLuint swzG = GET_SWZ(swizzle, 1);
  558.    const GLuint swzB = GET_SWZ(swizzle, 2);
  559.    const GLuint swzA = GET_SWZ(swizzle, 3);
  560.    GLfloat vector[6];
  561.    GLuint i;
  562.  
  563.    vector[SWIZZLE_ZERO] = 0;
  564.    vector[SWIZZLE_ONE] = 1.0F;
  565.  
  566.    for (i = 0; i < count; i++) {
  567.       vector[SWIZZLE_X] = texels[i][0];
  568.       vector[SWIZZLE_Y] = texels[i][1];
  569.       vector[SWIZZLE_Z] = texels[i][2];
  570.       vector[SWIZZLE_W] = texels[i][3];
  571.       texels[i][RCOMP] = vector[swzR];
  572.       texels[i][GCOMP] = vector[swzG];
  573.       texels[i][BCOMP] = vector[swzB];
  574.       texels[i][ACOMP] = vector[swzA];
  575.    }
  576. }
  577.  
  578.  
  579. /**
  580.  * Apply texture mapping to a span of fragments.
  581.  */
  582. void
  583. _swrast_texture_span( struct gl_context *ctx, SWspan *span )
  584. {
  585.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  586.    float4_array primary_rgba;
  587.    GLuint unit;
  588.  
  589.    primary_rgba = (float4_array) malloc(span->end * 4 * sizeof(GLfloat));
  590.  
  591.    if (!primary_rgba) {
  592.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span");
  593.       return;
  594.    }
  595.  
  596.    ASSERT(span->end <= MAX_WIDTH);
  597.  
  598.    /*
  599.     * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
  600.     */
  601.    if (swrast->_TextureCombinePrimary) {
  602.       GLuint i;
  603.       for (i = 0; i < span->end; i++) {
  604.          primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
  605.          primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
  606.          primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
  607.          primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
  608.       }
  609.    }
  610.  
  611.    /* First must sample all bump maps */
  612.    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
  613.       const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  614.  
  615.       if (texUnit->_ReallyEnabled &&
  616.          texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
  617.          const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
  618.             span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
  619.          float4_array targetcoords =
  620.             span->array->attribs[FRAG_ATTRIB_TEX0 +
  621.                ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];
  622.  
  623.          const struct gl_texture_object *curObj = texUnit->_Current;
  624.          GLfloat *lambda = span->array->lambda[unit];
  625.          float4_array texels = get_texel_array(swrast, unit);
  626.          GLuint i;
  627.          GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
  628.          GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
  629.          GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
  630.          GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];
  631.  
  632.          /* adjust texture lod (lambda) */
  633.          if (span->arrayMask & SPAN_LAMBDA) {
  634.             if (texUnit->LodBias + curObj->LodBias != 0.0F) {
  635.                /* apply LOD bias, but don't clamp yet */
  636.                const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
  637.                                           -ctx->Const.MaxTextureLodBias,
  638.                                           ctx->Const.MaxTextureLodBias);
  639.                GLuint i;
  640.                for (i = 0; i < span->end; i++) {
  641.                   lambda[i] += bias;
  642.                }
  643.             }
  644.  
  645.             if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
  646.                /* apply LOD clamping to lambda */
  647.                const GLfloat min = curObj->MinLod;
  648.                const GLfloat max = curObj->MaxLod;
  649.                GLuint i;
  650.                for (i = 0; i < span->end; i++) {
  651.                   GLfloat l = lambda[i];
  652.                   lambda[i] = CLAMP(l, min, max);
  653.                }
  654.             }
  655.          }
  656.  
  657.          /* Sample the texture (span->end = number of fragments) */
  658.          swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
  659.                                       texcoords, lambda, texels );
  660.  
  661.          /* manipulate the span values of the bump target
  662.             not sure this can work correctly even ignoring
  663.             the problem that channel is unsigned */
  664.          for (i = 0; i < span->end; i++) {
  665.             targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
  666.                                   rotMatrix01) / targetcoords[i][3];
  667.             targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
  668.                                   rotMatrix11) / targetcoords[i][3];
  669.          }
  670.       }
  671.    }
  672.  
  673.    /*
  674.     * Must do all texture sampling before combining in order to
  675.     * accomodate GL_ARB_texture_env_crossbar.
  676.     */
  677.    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
  678.       const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  679.       if (texUnit->_ReallyEnabled &&
  680.           texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
  681.          const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
  682.             span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
  683.          const struct gl_texture_object *curObj = texUnit->_Current;
  684.          GLfloat *lambda = span->array->lambda[unit];
  685.          float4_array texels = get_texel_array(swrast, unit);
  686.  
  687.          /* adjust texture lod (lambda) */
  688.          if (span->arrayMask & SPAN_LAMBDA) {
  689.             if (texUnit->LodBias + curObj->LodBias != 0.0F) {
  690.                /* apply LOD bias, but don't clamp yet */
  691.                const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
  692.                                           -ctx->Const.MaxTextureLodBias,
  693.                                           ctx->Const.MaxTextureLodBias);
  694.                GLuint i;
  695.                for (i = 0; i < span->end; i++) {
  696.                   lambda[i] += bias;
  697.                }
  698.             }
  699.  
  700.             if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
  701.                /* apply LOD clamping to lambda */
  702.                const GLfloat min = curObj->MinLod;
  703.                const GLfloat max = curObj->MaxLod;
  704.                GLuint i;
  705.                for (i = 0; i < span->end; i++) {
  706.                   GLfloat l = lambda[i];
  707.                   lambda[i] = CLAMP(l, min, max);
  708.                }
  709.             }
  710.          }
  711.  
  712.          /* Sample the texture (span->end = number of fragments) */
  713.          swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
  714.                                       texcoords, lambda, texels );
  715.  
  716.          /* GL_SGI_texture_color_table */
  717.          if (texUnit->ColorTableEnabled) {
  718.             _mesa_lookup_rgba_float(&texUnit->ColorTable, span->end, texels);
  719.          }
  720.  
  721.          /* GL_EXT_texture_swizzle */
  722.          if (curObj->_Swizzle != SWIZZLE_NOOP) {
  723.             swizzle_texels(curObj->_Swizzle, span->end, texels);
  724.          }
  725.       }
  726.    }
  727.  
  728.    /*
  729.     * OK, now apply the texture (aka texture combine/blend).
  730.     * We modify the span->color.rgba values.
  731.     */
  732.    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
  733.       if (ctx->Texture.Unit[unit]._ReallyEnabled) {
  734.          texture_combine( ctx, unit, span->end,
  735.                           primary_rgba,
  736.                           swrast->TexelBuffer,
  737.                           span->array->rgba );
  738.       }
  739.    }
  740.  
  741.    free(primary_rgba);
  742. }
  743.