Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  5.  * 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/imports.h"
  30. #include "main/macros.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]._Current)
  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]._Current)
  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.       default:
  433.          _mesa_problem(ctx, "invalid combine mode");
  434.       }
  435.    }
  436.  
  437.    /* Alpha channel combine */
  438.    {
  439.       float4_array arg0 = argA[0];
  440.       float4_array arg1 = argA[1];
  441.       float4_array arg2 = argA[2];
  442.       float4_array arg3 = argA[3];
  443.  
  444.       switch (combine->ModeA) {
  445.       case GL_REPLACE:
  446.          for (i = 0; i < n; i++) {
  447.             rgba[i][ACOMP] = arg0[i][ACOMP] * scaleA;
  448.          }
  449.          break;
  450.       case GL_MODULATE:
  451.          for (i = 0; i < n; i++) {
  452.             rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * scaleA;
  453.          }
  454.          break;
  455.       case GL_ADD:
  456.          if (textureUnit->EnvMode == GL_COMBINE4_NV) {
  457.             /* (a * b) + (c * d) */
  458.             for (i = 0; i < n; i++) {
  459.                rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
  460.                                  arg2[i][ACOMP] * arg3[i][ACOMP]) * scaleA;
  461.             }
  462.          }
  463.          else {
  464.             /* two-term add */
  465.             for (i = 0; i < n; i++) {
  466.                rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * scaleA;
  467.             }
  468.          }
  469.          break;
  470.       case GL_ADD_SIGNED:
  471.          if (textureUnit->EnvMode == GL_COMBINE4_NV) {
  472.             /* (a * b) + (c * d) - 0.5 */
  473.             for (i = 0; i < n; i++) {
  474.                rgba[i][ACOMP] = (arg0[i][ACOMP] * arg1[i][ACOMP] +
  475.                                  arg2[i][ACOMP] * arg3[i][ACOMP] -
  476.                                  0.5F) * scaleA;
  477.             }
  478.          }
  479.          else {
  480.             /* a + b - 0.5 */
  481.             for (i = 0; i < n; i++) {
  482.                rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * scaleA;
  483.             }
  484.          }
  485.          break;
  486.       case GL_INTERPOLATE:
  487.          for (i = 0; i < n; i++) {
  488.             rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
  489.                               arg1[i][ACOMP] * (1.0F - arg2[i][ACOMP]))
  490.                * scaleA;
  491.          }
  492.          break;
  493.       case GL_SUBTRACT:
  494.          for (i = 0; i < n; i++) {
  495.             rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * scaleA;
  496.          }
  497.          break;
  498.       case GL_MODULATE_ADD_ATI:
  499.          for (i = 0; i < n; i++) {
  500.             rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
  501.                               + arg1[i][ACOMP]) * scaleA;
  502.          }
  503.          break;
  504.       case GL_MODULATE_SIGNED_ADD_ATI:
  505.          for (i = 0; i < n; i++) {
  506.             rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP]) +
  507.                               arg1[i][ACOMP] - 0.5F) * scaleA;
  508.          }
  509.          break;
  510.       case GL_MODULATE_SUBTRACT_ATI:
  511.          for (i = 0; i < n; i++) {
  512.             rgba[i][ACOMP] = ((arg0[i][ACOMP] * arg2[i][ACOMP])
  513.                               - arg1[i][ACOMP]) * scaleA;
  514.          }
  515.          break;
  516.       default:
  517.          _mesa_problem(ctx, "invalid combine mode");
  518.       }
  519.    }
  520.  
  521.    /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
  522.     * This is kind of a kludge.  It would have been better if the spec
  523.     * were written such that the GL_COMBINE_ALPHA value could be set to
  524.     * GL_DOT3.
  525.     */
  526.    if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
  527.        combine->ModeRGB == GL_DOT3_RGBA) {
  528.       for (i = 0; i < n; i++) {
  529.          rgba[i][ACOMP] = rgba[i][RCOMP];
  530.       }
  531.    }
  532.  
  533.    for (i = 0; i < n; i++) {
  534.       UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][RCOMP], rgba[i][RCOMP]);
  535.       UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][GCOMP], rgba[i][GCOMP]);
  536.       UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][BCOMP], rgba[i][BCOMP]);
  537.       UNCLAMPED_FLOAT_TO_CHAN(rgbaChan[i][ACOMP], rgba[i][ACOMP]);
  538.    }
  539.    /* The span->array->rgba values are of CHAN type so set
  540.     * span->array->ChanType field accordingly.
  541.     */
  542.    span->array->ChanType = CHAN_TYPE;
  543.  
  544. end:
  545.    for (i = 0; i < numArgsRGB || i < numArgsA; i++) {
  546.       free(ccolor[i]);
  547.    }
  548.    free(rgba);
  549. }
  550.  
  551.  
  552. /**
  553.  * Apply X/Y/Z/W/0/1 swizzle to an array of colors/texels.
  554.  * See GL_EXT_texture_swizzle.
  555.  */
  556. static void
  557. swizzle_texels(GLuint swizzle, GLuint count, float4_array texels)
  558. {
  559.    const GLuint swzR = GET_SWZ(swizzle, 0);
  560.    const GLuint swzG = GET_SWZ(swizzle, 1);
  561.    const GLuint swzB = GET_SWZ(swizzle, 2);
  562.    const GLuint swzA = GET_SWZ(swizzle, 3);
  563.    GLfloat vector[6];
  564.    GLuint i;
  565.  
  566.    vector[SWIZZLE_ZERO] = 0;
  567.    vector[SWIZZLE_ONE] = 1.0F;
  568.  
  569.    for (i = 0; i < count; i++) {
  570.       vector[SWIZZLE_X] = texels[i][0];
  571.       vector[SWIZZLE_Y] = texels[i][1];
  572.       vector[SWIZZLE_Z] = texels[i][2];
  573.       vector[SWIZZLE_W] = texels[i][3];
  574.       texels[i][RCOMP] = vector[swzR];
  575.       texels[i][GCOMP] = vector[swzG];
  576.       texels[i][BCOMP] = vector[swzB];
  577.       texels[i][ACOMP] = vector[swzA];
  578.    }
  579. }
  580.  
  581.  
  582. /**
  583.  * Apply texture mapping to a span of fragments.
  584.  */
  585. void
  586. _swrast_texture_span( struct gl_context *ctx, SWspan *span )
  587. {
  588.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  589.    float4_array primary_rgba;
  590.    GLuint unit;
  591.  
  592.    if (!swrast->TexelBuffer) {
  593. #ifdef _OPENMP
  594.       const GLint maxThreads = omp_get_max_threads();
  595.  
  596.       /* TexelBuffer memory allocation needs to be done in a critical section
  597.        * as this code runs in a parallel loop.
  598.        * When entering the section, first check if TexelBuffer has been
  599.        * initialized already by another thread while this thread was waiting.
  600.        */
  601.       #pragma omp critical
  602.       if (!swrast->TexelBuffer) {
  603. #else
  604.       const GLint maxThreads = 1;
  605. #endif
  606.  
  607.       /* TexelBuffer is also global and normally shared by all SWspan
  608.        * instances; when running with multiple threads, create one per
  609.        * thread.
  610.        */
  611.       swrast->TexelBuffer =
  612.          malloc(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits * maxThreads *
  613.                             SWRAST_MAX_WIDTH * 4 * sizeof(GLfloat));
  614. #ifdef _OPENMP
  615.       } /* critical section */
  616. #endif
  617.  
  618.       if (!swrast->TexelBuffer) {
  619.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
  620.          return;
  621.       }
  622.    }
  623.  
  624.    primary_rgba = malloc(span->end * 4 * sizeof(GLfloat));
  625.  
  626.    if (!primary_rgba) {
  627.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span");
  628.       return;
  629.    }
  630.  
  631.    assert(span->end <= SWRAST_MAX_WIDTH);
  632.  
  633.    /*
  634.     * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
  635.     */
  636.    if (swrast->_TextureCombinePrimary) {
  637.       GLuint i;
  638.       for (i = 0; i < span->end; i++) {
  639.          primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
  640.          primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
  641.          primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
  642.          primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
  643.       }
  644.    }
  645.  
  646.    /*
  647.     * Must do all texture sampling before combining in order to
  648.     * accommodate GL_ARB_texture_env_crossbar.
  649.     */
  650.    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
  651.       const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  652.       if (texUnit->_Current) {
  653.          const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
  654.             span->array->attribs[VARYING_SLOT_TEX0 + unit];
  655.          const struct gl_texture_object *curObj = texUnit->_Current;
  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.  
  660.          /* adjust texture lod (lambda) */
  661.          if (span->arrayMask & SPAN_LAMBDA) {
  662.             if (texUnit->LodBias + samp->LodBias != 0.0F) {
  663.                /* apply LOD bias, but don't clamp yet */
  664.                const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias,
  665.                                           -ctx->Const.MaxTextureLodBias,
  666.                                           ctx->Const.MaxTextureLodBias);
  667.                GLuint i;
  668.                for (i = 0; i < span->end; i++) {
  669.                   lambda[i] += bias;
  670.                }
  671.             }
  672.  
  673.             if (samp->MinLod != -1000.0 ||
  674.                 samp->MaxLod != 1000.0) {
  675.                /* apply LOD clamping to lambda */
  676.                const GLfloat min = samp->MinLod;
  677.                const GLfloat max = samp->MaxLod;
  678.                GLuint i;
  679.                for (i = 0; i < span->end; i++) {
  680.                   GLfloat l = lambda[i];
  681.                   lambda[i] = CLAMP(l, min, max);
  682.                }
  683.             }
  684.          }
  685.          else if (samp->MaxAnisotropy > 1.0 &&
  686.                   samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
  687.             /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
  688.              * it requires the current SWspan *span as an additional parameter.
  689.              * In order to keep the same function signature, the unused lambda
  690.              * parameter will be modified to actually contain the SWspan pointer.
  691.              * This is a Hack. To make it right, the texture_sample_func
  692.              * signature and all implementing functions need to be modified.
  693.              */
  694.             /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
  695.             lambda = (GLfloat *)span;
  696.          }
  697.  
  698.          /* Sample the texture (span->end = number of fragments) */
  699.          swrast->TextureSample[unit]( ctx, samp,
  700.                                       ctx->Texture.Unit[unit]._Current,
  701.                                       span->end, texcoords, lambda, texels );
  702.  
  703.          /* GL_EXT_texture_swizzle */
  704.          if (curObj->_Swizzle != SWIZZLE_NOOP) {
  705.             swizzle_texels(curObj->_Swizzle, span->end, texels);
  706.          }
  707.       }
  708.    }
  709.  
  710.    /*
  711.     * OK, now apply the texture (aka texture combine/blend).
  712.     * We modify the span->color.rgba values.
  713.     */
  714.    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
  715.       if (ctx->Texture.Unit[unit]._Current)
  716.          texture_combine(ctx, unit, primary_rgba, swrast->TexelBuffer, span);
  717.    }
  718.  
  719.    free(primary_rgba);
  720. }
  721.