Subversion Repositories Kolibri OS

Rev

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