home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / swrast / s_texture.cpp < prev    next >
C/C++ Source or Header  |  2002-11-12  |  135KB  |  3,744 lines

  1. /* $Id: s_texture.c,v 1.75 2002/11/12 19:27:24 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.0
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. #include "glheader.h"
  29. #include "context.h"
  30. #include "colormac.h"
  31. #include "macros.h"
  32. #include "mmath.h"
  33. #include "imports.h"
  34. #include "texformat.h"
  35. #include "teximage.h"
  36.  
  37. #include "s_context.h"
  38. #include "s_texture.h"
  39.  
  40.  
  41. /*
  42.  * These values are used in the fixed-point arithmetic used
  43.  * for linear filtering.
  44.  */
  45. #define WEIGHT_SCALE 65536.0F
  46. #define WEIGHT_SHIFT 16
  47.  
  48.  
  49. /*
  50.  * Used to compute texel locations for linear sampling.
  51.  * Input:
  52.  *    wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER_ARB
  53.  *    S = texcoord in [0,1]
  54.  *    SIZE = width (or height or depth) of texture
  55.  * Output:
  56.  *    U = texcoord in [0, width]
  57.  *    I0, I1 = two nearest texel indexes
  58.  */
  59. #define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1)    \
  60. {                                    \
  61.    if (wrapMode == GL_REPEAT) {                        \
  62.       U = S * SIZE - 0.5F;                        \
  63.       I0 = IFLOOR(U) & (SIZE - 1);                    \
  64.       I1 = (I0 + 1) & (SIZE - 1);                    \
  65.    }                                    \
  66.    else if (wrapMode == GL_CLAMP_TO_EDGE) {                \
  67.       if (S <= 0.0F)                            \
  68.          U = 0.0F;                            \
  69.       else if (S >= 1.0F)                        \
  70.          U = (GLfloat) SIZE;                        \
  71.       else                                \
  72.          U = S * SIZE;                            \
  73.       U -= 0.5F;                            \
  74.       I0 = IFLOOR(U);                            \
  75.       I1 = I0 + 1;                            \
  76.       if (I0 < 0)                            \
  77.          I0 = 0;                            \
  78.       if (I1 >= (GLint) SIZE)                        \
  79.          I1 = SIZE - 1;                            \
  80.    }                                    \
  81.    else  if (wrapMode == GL_CLAMP_TO_BORDER_ARB) {            \
  82.       const GLfloat min = -1.0F / (2.0F * SIZE);            \
  83.       const GLfloat max = 1.0F - min;                    \
  84.       if (S <= min)                            \
  85.          U = min * SIZE;                        \
  86.       else if (S >= max)                        \
  87.          U = max * SIZE;                        \
  88.       else                                \
  89.          U = S * SIZE;                            \
  90.       U -= 0.5F;                            \
  91.       I0 = IFLOOR(U);                            \
  92.       I1 = I0 + 1;                            \
  93.    }                                    \
  94.    else if (wrapMode == GL_MIRRORED_REPEAT_ARB) {            \
  95.       const GLint flr = IFLOOR(S);                    \
  96.       if (flr & 1)                            \
  97.          U = 1.0F - (S - (GLfloat) flr);    /* flr is odd */    \
  98.       else                                \
  99.          U = S - (GLfloat) flr;        /* flr is even */        \
  100.       U = (U * SIZE) - 0.5F;                        \
  101.       I0 = IFLOOR(U);                            \
  102.       I1 = I0 + 1;                            \
  103.       if (I0 < 0)                            \
  104.          I0 = 0;                            \
  105.       if (I1 >= (GLint) SIZE)                        \
  106.          I1 = SIZE - 1;                            \
  107.    }                                    \
  108.    else if (wrapMode == GL_MIRROR_CLAMP_ATI) {                \
  109.       U = (GLfloat) fabs(S);                        \
  110.       if (U >= 1.0F)                            \
  111.          U = (GLfloat) SIZE;                        \
  112.       else                                \
  113.          U *= SIZE;                            \
  114.       U -= 0.5F;                            \
  115.       I0 = IFLOOR(U);                            \
  116.       I1 = I0 + 1;                            \
  117.    }                                    \
  118.    else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) {            \
  119.       U = (GLfloat) fabs(S);                        \
  120.       if (U >= 1.0F)                            \
  121.          U = (GLfloat) SIZE;                        \
  122.       else                                \
  123.          U *= SIZE;                            \
  124.       U -= 0.5F;                            \
  125.       I0 = IFLOOR(U);                            \
  126.       I1 = I0 + 1;                            \
  127.       if (I0 < 0)                            \
  128.          I0 = 0;                            \
  129.       if (I1 >= (GLint) SIZE)                        \
  130.          I1 = SIZE - 1;                            \
  131.    }                                    \
  132.    else {                                \
  133.       ASSERT(wrapMode == GL_CLAMP);                    \
  134.       if (S <= 0.0F)                            \
  135.          U = 0.0F;                            \
  136.       else if (S >= 1.0F)                        \
  137.          U = (GLfloat) SIZE;                        \
  138.       else                                \
  139.          U = S * SIZE;                            \
  140.       U -= 0.5F;                            \
  141.       I0 = IFLOOR(U);                            \
  142.       I1 = I0 + 1;                            \
  143.    }                                    \
  144. }
  145.  
  146.  
  147. /*
  148.  * Used to compute texel location for nearest sampling.
  149.  */
  150. #define COMPUTE_NEAREST_TEXEL_LOCATION(wrapMode, S, SIZE, I)        \
  151. {                                    \
  152.    if (wrapMode == GL_REPEAT) {                        \
  153.       /* s limited to [0,1) */                        \
  154.       /* i limited to [0,size-1] */                    \
  155.       I = IFLOOR(S * SIZE);                        \
  156.       I &= (SIZE - 1);                            \
  157.    }                                    \
  158.    else if (wrapMode == GL_CLAMP_TO_EDGE) {                \
  159.       /* s limited to [min,max] */                    \
  160.       /* i limited to [0, size-1] */                    \
  161.       const GLfloat min = 1.0F / (2.0F * SIZE);                \
  162.       const GLfloat max = 1.0F - min;                    \
  163.       if (S < min)                            \
  164.          I = 0;                                \
  165.       else if (S > max)                            \
  166.          I = SIZE - 1;                            \
  167.       else                                \
  168.          I = IFLOOR(S * SIZE);                        \
  169.    }                                    \
  170.    else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) {            \
  171.       /* s limited to [min,max] */                    \
  172.       /* i limited to [-1, size] */                    \
  173.       const GLfloat min = -1.0F / (2.0F * SIZE);            \
  174.       const GLfloat max = 1.0F - min;                    \
  175.       if (S <= min)                            \
  176.          I = -1;                            \
  177.       else if (S >= max)                        \
  178.          I = SIZE;                            \
  179.       else                                \
  180.          I = IFLOOR(S * SIZE);                        \
  181.    }                                    \
  182.    else if (wrapMode == GL_MIRRORED_REPEAT_ARB) {            \
  183.       const GLfloat min = 1.0F / (2.0F * SIZE);                \
  184.       const GLfloat max = 1.0F - min;                    \
  185.       const GLint flr = IFLOOR(S);                    \
  186.       GLfloat u;                            \
  187.       if (flr & 1)                            \
  188.          u = 1.0F - (S - (GLfloat) flr);    /* flr is odd */    \
  189.       else                                \
  190.          u = S - (GLfloat) flr;        /* flr is even */        \
  191.       if (u < min)                            \
  192.          I = 0;                                \
  193.       else if (u > max)                            \
  194.          I = SIZE - 1;                            \
  195.       else                                \
  196.          I = IFLOOR(u * SIZE);                        \
  197.    }                                    \
  198.    else if (wrapMode == GL_MIRROR_CLAMP_ATI) {                \
  199.       /* s limited to [0,1] */                        \
  200.       /* i limited to [0,size-1] */                    \
  201.       const GLfloat u = (GLfloat) fabs(S);                \
  202.       if (u <= 0.0F)                            \
  203.          I = 0;                                \
  204.       else if (u >= 1.0F)                        \
  205.          I = SIZE - 1;                            \
  206.       else                                \
  207.          I = IFLOOR(u * SIZE);                        \
  208.    }                                    \
  209.    else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_ATI) {            \
  210.       /* s limited to [min,max] */                    \
  211.       /* i limited to [0, size-1] */                    \
  212.       const GLfloat min = 1.0F / (2.0F * SIZE);                \
  213.       const GLfloat max = 1.0F - min;                    \
  214.       const GLfloat u = (GLfloat) fabs(S);                \
  215.       if (u < min)                            \
  216.          I = 0;                                \
  217.       else if (u > max)                            \
  218.          I = SIZE - 1;                            \
  219.       else                                \
  220.          I = IFLOOR(u * SIZE);                        \
  221.    }                                    \
  222.    else {                                \
  223.       ASSERT(wrapMode == GL_CLAMP);                    \
  224.       /* s limited to [0,1] */                        \
  225.       /* i limited to [0,size-1] */                    \
  226.       if (S <= 0.0F)                            \
  227.          I = 0;                                \
  228.       else if (S >= 1.0F)                        \
  229.          I = SIZE - 1;                            \
  230.       else                                \
  231.          I = IFLOOR(S * SIZE);                        \
  232.    }                                    \
  233. }
  234.  
  235.  
  236. #define COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(S, U, SIZE, I0, I1)    \
  237. {                                    \
  238.    U = S * SIZE - 0.5F;                            \
  239.    I0 = IFLOOR(U) & (SIZE - 1);                        \
  240.    I1 = (I0 + 1) & (SIZE - 1);                        \
  241. }
  242.  
  243.  
  244. /*
  245.  * Compute linear mipmap levels for given lambda.
  246.  */
  247. #define COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda, level)    \
  248. {                                \
  249.    if (lambda < 0.0F)                        \
  250.       level = tObj->BaseLevel;                    \
  251.    else if (lambda > tObj->_MaxLambda)                \
  252.       level = (GLint) (tObj->BaseLevel + tObj->_MaxLambda);    \
  253.    else                                \
  254.       level = (GLint) (tObj->BaseLevel + lambda);        \
  255. }
  256.  
  257.  
  258. /*
  259.  * Compute nearest mipmap level for given lambda.
  260.  */
  261. #define COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda, level)    \
  262. {                                \
  263.    GLfloat l;                            \
  264.    if (lambda <= 0.5F)                        \
  265.       l = 0.0F;                            \
  266.    else if (lambda > tObj->_MaxLambda + 0.4999F)        \
  267.       l = tObj->_MaxLambda + 0.4999F;                \
  268.    else                                \
  269.       l = lambda;                        \
  270.    level = (GLint) (tObj->BaseLevel + l + 0.5F);        \
  271.    if (level > tObj->_MaxLevel)                    \
  272.       level = tObj->_MaxLevel;                    \
  273. }
  274.  
  275.  
  276.  
  277. /*
  278.  * Note, the FRAC macro has to work perfectly.  Otherwise you'll sometimes
  279.  * see 1-pixel bands of improperly weighted linear-sampled texels.  The
  280.  * tests/texwrap.c demo is a good test.
  281.  * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
  282.  * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
  283.  */
  284. #define FRAC(f)  ((f) - IFLOOR(f))
  285.  
  286.  
  287.  
  288. /*
  289.  * Bitflags for texture border color sampling.
  290.  */
  291. #define I0BIT   1
  292. #define I1BIT   2
  293. #define J0BIT   4
  294. #define J1BIT   8
  295. #define K0BIT  16
  296. #define K1BIT  32
  297.  
  298.  
  299.  
  300. /*
  301.  * Get texture palette entry.
  302.  */
  303. static void
  304. palette_sample(const GLcontext *ctx,
  305.                const struct gl_texture_object *tObj,
  306.                GLint index, GLchan rgba[4] )
  307. {
  308.    const GLchan *palette;
  309.    GLenum format;
  310.  
  311.    if (ctx->Texture.SharedPalette) {
  312.       ASSERT(!ctx->Texture.Palette.FloatTable);
  313.       palette = (const GLchan *) ctx->Texture.Palette.Table;
  314.       format = ctx->Texture.Palette.Format;
  315.    }
  316.    else {
  317.       ASSERT(!tObj->Palette.FloatTable);
  318.       palette = (const GLchan *) tObj->Palette.Table;
  319.       format = tObj->Palette.Format;
  320.    }
  321.  
  322.    switch (format) {
  323.       case GL_ALPHA:
  324.          rgba[ACOMP] = palette[index];
  325.          return;
  326.       case GL_LUMINANCE:
  327.       case GL_INTENSITY:
  328.          rgba[RCOMP] = palette[index];
  329.          return;
  330.       case GL_LUMINANCE_ALPHA:
  331.          rgba[RCOMP] = palette[(index << 1) + 0];
  332.          rgba[ACOMP] = palette[(index << 1) + 1];
  333.          return;
  334.       case GL_RGB:
  335.          rgba[RCOMP] = palette[index * 3 + 0];
  336.          rgba[GCOMP] = palette[index * 3 + 1];
  337.          rgba[BCOMP] = palette[index * 3 + 2];
  338.          return;
  339.       case GL_RGBA:
  340.          rgba[RCOMP] = palette[(index << 2) + 0];
  341.          rgba[GCOMP] = palette[(index << 2) + 1];
  342.          rgba[BCOMP] = palette[(index << 2) + 2];
  343.          rgba[ACOMP] = palette[(index << 2) + 3];
  344.          return;
  345.       default:
  346.          _mesa_problem(ctx, "Bad palette format in palette_sample");
  347.    }
  348. }
  349.  
  350.  
  351. /*
  352.  * The lambda[] array values are always monotonic.  Either the whole span
  353.  * will be minified, magnified, or split between the two.  This function
  354.  * determines the subranges in [0, n-1] that are to be minified or magnified.
  355.  */
  356. static INLINE void
  357. compute_min_mag_ranges( GLfloat minMagThresh, GLuint n, const GLfloat lambda[],
  358.                         GLuint *minStart, GLuint *minEnd,
  359.                         GLuint *magStart, GLuint *magEnd )
  360. {
  361.    ASSERT(lambda != NULL);
  362. #if 0
  363.    /* Verify that lambda[] is monotonous.
  364.     * We can't really use this because the inaccuracy in the LOG2 function
  365.     * causes this test to fail, yet the resulting texturing is correct.
  366.     */
  367.    if (n > 1) {
  368.       GLuint i;
  369.       printf("lambda delta = %g\n", lambda[0] - lambda[n-1]);
  370.       if (lambda[0] >= lambda[n-1]) { /* decreasing */
  371.          for (i = 0; i < n - 1; i++) {
  372.             ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10));
  373.          }
  374.       }
  375.       else { /* increasing */
  376.          for (i = 0; i < n - 1; i++) {
  377.             ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10));
  378.          }
  379.       }
  380.    }
  381. #endif /* DEBUG */
  382.  
  383.    /* since lambda is monotonous-array use this check first */
  384.    if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) {
  385.       /* magnification for whole span */
  386.       *magStart = 0;
  387.       *magEnd = n;
  388.       *minStart = *minEnd = 0;
  389.    }
  390.    else if (lambda[0] > minMagThresh && lambda[n-1] > minMagThresh) {
  391.       /* minification for whole span */
  392.       *minStart = 0;
  393.       *minEnd = n;
  394.       *magStart = *magEnd = 0;
  395.    }
  396.    else {
  397.       /* a mix of minification and magnification */
  398.       GLuint i;
  399.       if (lambda[0] > minMagThresh) {
  400.          /* start with minification */
  401.          for (i = 1; i < n; i++) {
  402.             if (lambda[i] <= minMagThresh)
  403.                break;
  404.          }
  405.          *minStart = 0;
  406.          *minEnd = i;
  407.          *magStart = i;
  408.          *magEnd = n;
  409.       }
  410.       else {
  411.          /* start with magnification */
  412.          for (i = 1; i < n; i++) {
  413.             if (lambda[i] > minMagThresh)
  414.                break;
  415.          }
  416.          *magStart = 0;
  417.          *magEnd = i;
  418.          *minStart = i;
  419.          *minEnd = n;
  420.       }
  421.    }
  422.  
  423. #if 0
  424.    /* Verify the min/mag Start/End values
  425.     * We don't use this either (see above)
  426.     */
  427.    {
  428.       GLint i;
  429.       for (i = 0; i < n; i++) {
  430.          if (lambda[i] > minMagThresh) {
  431.             /* minification */
  432.             ASSERT(i >= *minStart);
  433.             ASSERT(i < *minEnd);
  434.          }
  435.          else {
  436.             /* magnification */
  437.             ASSERT(i >= *magStart);
  438.             ASSERT(i < *magEnd);
  439.          }
  440.       }
  441.    }
  442. #endif
  443. }
  444.  
  445.  
  446. /**********************************************************************/
  447. /*                    1-D Texture Sampling Functions                  */
  448. /**********************************************************************/
  449.  
  450. /*
  451.  * Return the texture sample for coordinate (s) using GL_NEAREST filter.
  452.  */
  453. static void
  454. sample_1d_nearest(GLcontext *ctx,
  455.                   const struct gl_texture_object *tObj,
  456.                   const struct gl_texture_image *img,
  457.                   const GLfloat texcoord[4], GLchan rgba[4])
  458. {
  459.    const GLint width = img->Width2;  /* without border, power of two */
  460.    GLint i;
  461.  
  462.    COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width, i);
  463.  
  464.    /* skip over the border, if any */
  465.    i += img->Border;
  466.  
  467.    if (i < 0 || i >= (GLint) img->Width) {
  468.       /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
  469.       COPY_CHAN4(rgba, tObj->_BorderChan);
  470.    }
  471.    else {
  472.       (*img->FetchTexel)(img, i, 0, 0, (GLvoid *) rgba);
  473.       if (img->Format == GL_COLOR_INDEX) {
  474.          palette_sample(ctx, tObj, rgba[0], rgba);
  475.       }
  476.    }
  477. }
  478.  
  479.  
  480.  
  481. /*
  482.  * Return the texture sample for coordinate (s) using GL_LINEAR filter.
  483.  */
  484. static void
  485. sample_1d_linear(GLcontext *ctx,
  486.                  const struct gl_texture_object *tObj,
  487.                  const struct gl_texture_image *img,
  488.                  const GLfloat texcoord[4], GLchan rgba[4])
  489. {
  490.    const GLint width = img->Width2;
  491.    GLint i0, i1;
  492.    GLfloat u;
  493.    GLuint useBorderColor;
  494.  
  495.    COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width, i0, i1);
  496.  
  497.    useBorderColor = 0;
  498.    if (img->Border) {
  499.       i0 += img->Border;
  500.       i1 += img->Border;
  501.    }
  502.    else {
  503.       if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
  504.       if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
  505.    }
  506.  
  507.    {
  508.       const GLfloat a = FRAC(u);
  509.  
  510. #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
  511.       const GLfloat w0 = (1.0F-a);
  512.       const GLfloat w1 =       a ;
  513. #else /* CHAN_BITS == 8 */
  514.       /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
  515.       const GLint w0 = IROUND_POS((1.0F - a) * WEIGHT_SCALE);
  516.       const GLint w1 = IROUND_POS(        a  * WEIGHT_SCALE);
  517. #endif
  518.       GLchan t0[4], t1[4];  /* texels */
  519.  
  520.       if (useBorderColor & I0BIT) {
  521.          COPY_CHAN4(t0, tObj->_BorderChan);
  522.       }
  523.       else {
  524.          (*img->FetchTexel)(img, i0, 0, 0, (GLvoid *) t0);
  525.          if (img->Format == GL_COLOR_INDEX) {
  526.             palette_sample(ctx, tObj, t0[0], t0);
  527.          }
  528.       }
  529.       if (useBorderColor & I1BIT) {
  530.          COPY_CHAN4(t1, tObj->_BorderChan);
  531.       }
  532.       else {
  533.          (*img->FetchTexel)(img, i1, 0, 0, (GLvoid *) t1);
  534.          if (img->Format == GL_COLOR_INDEX) {
  535.             palette_sample(ctx, tObj, t1[0], t1);
  536.          }
  537.       }
  538.  
  539. #if CHAN_TYPE == GL_FLOAT
  540.       rgba[0] = w0 * t0[0] + w1 * t1[0];
  541.       rgba[1] = w0 * t0[1] + w1 * t1[1];
  542.       rgba[2] = w0 * t0[2] + w1 * t1[2];
  543.       rgba[3] = w0 * t0[3] + w1 * t1[3];
  544. #elif CHAN_TYPE == GL_UNSIGNED_SHORT
  545.       rgba[0] = (GLchan) (w0 * t0[0] + w1 * t1[0] + 0.5);
  546.       rgba[1] = (GLchan) (w0 * t0[1] + w1 * t1[1] + 0.5);
  547.       rgba[2] = (GLchan) (w0 * t0[2] + w1 * t1[2] + 0.5);
  548.       rgba[3] = (GLchan) (w0 * t0[3] + w1 * t1[3] + 0.5);
  549. #else /* CHAN_BITS == 8 */
  550.       rgba[0] = (GLchan) ((w0 * t0[0] + w1 * t1[0]) >> WEIGHT_SHIFT);
  551.       rgba[1] = (GLchan) ((w0 * t0[1] + w1 * t1[1]) >> WEIGHT_SHIFT);
  552.       rgba[2] = (GLchan) ((w0 * t0[2] + w1 * t1[2]) >> WEIGHT_SHIFT);
  553.       rgba[3] = (GLchan) ((w0 * t0[3] + w1 * t1[3]) >> WEIGHT_SHIFT);
  554. #endif
  555.  
  556.    }
  557. }
  558.  
  559.  
  560. static void
  561. sample_1d_nearest_mipmap_nearest(GLcontext *ctx,
  562.                                  const struct gl_texture_object *tObj,
  563.                                  GLuint n, GLfloat texcoord[][4],
  564.                                  const GLfloat lambda[], GLchan rgba[][4])
  565. {
  566.    GLuint i;
  567.    ASSERT(lambda != NULL);
  568.    for (i = 0; i < n; i++) {
  569.       GLint level;
  570.       COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
  571.       sample_1d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
  572.    }
  573. }
  574.  
  575.  
  576. static void
  577. sample_1d_linear_mipmap_nearest(GLcontext *ctx,
  578.                                 const struct gl_texture_object *tObj,
  579.                                 GLuint n, GLfloat texcoord[][4],
  580.                                 const GLfloat lambda[], GLchan rgba[][4])
  581. {
  582.    GLuint i;
  583.    ASSERT(lambda != NULL);
  584.    for (i = 0; i < n; i++) {
  585.       GLint level;
  586.       COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
  587.       sample_1d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
  588.    }
  589. }
  590.  
  591.  
  592.  
  593. /*
  594.  * This is really just needed in order to prevent warnings with some compilers.
  595.  */
  596. #if CHAN_TYPE == GL_FLOAT
  597. #define CHAN_CAST
  598. #else
  599. #define CHAN_CAST (GLchan) (GLint)
  600. #endif
  601.  
  602.  
  603. static void
  604. sample_1d_nearest_mipmap_linear(GLcontext *ctx,
  605.                                 const struct gl_texture_object *tObj,
  606.                                 GLuint n, GLfloat texcoord[][4],
  607.                                 const GLfloat lambda[], GLchan rgba[][4])
  608. {
  609.    GLuint i;
  610.    ASSERT(lambda != NULL);
  611.    for (i = 0; i < n; i++) {
  612.       GLint level;
  613.       COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
  614.       if (level >= tObj->_MaxLevel) {
  615.          sample_1d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
  616.                            texcoord[i], rgba[i]);
  617.       }
  618.       else {
  619.          GLchan t0[4], t1[4];
  620.          const GLfloat f = FRAC(lambda[i]);
  621.          sample_1d_nearest(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
  622.          sample_1d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
  623.          rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  624.          rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  625.          rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  626.          rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  627.       }
  628.    }
  629. }
  630.  
  631.  
  632.  
  633. static void
  634. sample_1d_linear_mipmap_linear(GLcontext *ctx,
  635.                                const struct gl_texture_object *tObj,
  636.                                GLuint n, GLfloat texcoord[][4],
  637.                                const GLfloat lambda[], GLchan rgba[][4])
  638. {
  639.    GLuint i;
  640.    ASSERT(lambda != NULL);
  641.    for (i = 0; i < n; i++) {
  642.       GLint level;
  643.       COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
  644.       if (level >= tObj->_MaxLevel) {
  645.          sample_1d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel],
  646.                           texcoord[i], rgba[i]);
  647.       }
  648.       else {
  649.          GLchan t0[4], t1[4];
  650.          const GLfloat f = FRAC(lambda[i]);
  651.          sample_1d_linear(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
  652.          sample_1d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
  653.          rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  654.          rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  655.          rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  656.          rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  657.       }
  658.    }
  659. }
  660.  
  661.  
  662.  
  663. static void
  664. sample_nearest_1d( GLcontext *ctx, GLuint texUnit,
  665.                    const struct gl_texture_object *tObj, GLuint n,
  666.                    GLfloat texcoords[][4], const GLfloat lambda[],
  667.                    GLchan rgba[][4] )
  668. {
  669.    GLuint i;
  670.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  671.    (void) lambda;
  672.    for (i=0;i<n;i++) {
  673.       sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
  674.    }
  675. }
  676.  
  677.  
  678.  
  679. static void
  680. sample_linear_1d( GLcontext *ctx, GLuint texUnit,
  681.                   const struct gl_texture_object *tObj, GLuint n,
  682.                   GLfloat texcoords[][4], const GLfloat lambda[],
  683.                   GLchan rgba[][4] )
  684. {
  685.    GLuint i;
  686.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  687.    (void) lambda;
  688.    for (i=0;i<n;i++) {
  689.       sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
  690.    }
  691. }
  692.  
  693.  
  694. /*
  695.  * Given an (s) texture coordinate and lambda (level of detail) value,
  696.  * return a texture sample.
  697.  *
  698.  */
  699. static void
  700. sample_lambda_1d( GLcontext *ctx, GLuint texUnit,
  701.                   const struct gl_texture_object *tObj, GLuint n,
  702.                   GLfloat texcoords[][4],
  703.                   const GLfloat lambda[], GLchan rgba[][4] )
  704. {
  705.    GLuint minStart, minEnd;  /* texels with minification */
  706.    GLuint magStart, magEnd;  /* texels with magnification */
  707.    GLuint i;
  708.  
  709.    ASSERT(lambda != NULL);
  710.    compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
  711.                           n, lambda, &minStart, &minEnd, &magStart, &magEnd);
  712.  
  713.    if (minStart < minEnd) {
  714.       /* do the minified texels */
  715.       const GLuint m = minEnd - minStart;
  716.       switch (tObj->MinFilter) {
  717.       case GL_NEAREST:
  718.          for (i = minStart; i < minEnd; i++)
  719.             sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
  720.                               texcoords[i], rgba[i]);
  721.          break;
  722.       case GL_LINEAR:
  723.          for (i = minStart; i < minEnd; i++)
  724.             sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
  725.                              texcoords[i], rgba[i]);
  726.          break;
  727.       case GL_NEAREST_MIPMAP_NEAREST:
  728.          sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  729.                                           lambda + minStart, rgba + minStart);
  730.          break;
  731.       case GL_LINEAR_MIPMAP_NEAREST:
  732.          sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  733.                                          lambda + minStart, rgba + minStart);
  734.          break;
  735.       case GL_NEAREST_MIPMAP_LINEAR:
  736.          sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  737.                                          lambda + minStart, rgba + minStart);
  738.          break;
  739.       case GL_LINEAR_MIPMAP_LINEAR:
  740.          sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  741.                                         lambda + minStart, rgba + minStart);
  742.          break;
  743.       default:
  744.          _mesa_problem(ctx, "Bad min filter in sample_1d_texture");
  745.          return;
  746.       }
  747.    }
  748.  
  749.    if (magStart < magEnd) {
  750.       /* do the magnified texels */
  751.       switch (tObj->MagFilter) {
  752.       case GL_NEAREST:
  753.          for (i = magStart; i < magEnd; i++)
  754.             sample_1d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
  755.                               texcoords[i], rgba[i]);
  756.          break;
  757.       case GL_LINEAR:
  758.          for (i = magStart; i < magEnd; i++)
  759.             sample_1d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
  760.                              texcoords[i], rgba[i]);
  761.          break;
  762.       default:
  763.          _mesa_problem(ctx, "Bad mag filter in sample_1d_texture");
  764.          return;
  765.       }
  766.    }
  767. }
  768.  
  769.  
  770. /**********************************************************************/
  771. /*                    2-D Texture Sampling Functions                  */
  772. /**********************************************************************/
  773.  
  774.  
  775. /*
  776.  * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
  777.  */
  778. static INLINE void
  779. sample_2d_nearest(GLcontext *ctx,
  780.                   const struct gl_texture_object *tObj,
  781.                   const struct gl_texture_image *img,
  782.                   const GLfloat texcoord[4],
  783.                   GLchan rgba[])
  784. {
  785.    const GLint width = img->Width2;    /* without border, power of two */
  786.    const GLint height = img->Height2;  /* without border, power of two */
  787.    GLint i, j;
  788.  
  789.    COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width,  i);
  790.    COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j);
  791.  
  792.    /* skip over the border, if any */
  793.    i += img->Border;
  794.    j += img->Border;
  795.  
  796.    if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
  797.       /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
  798.       COPY_CHAN4(rgba, tObj->_BorderChan);
  799.    }
  800.    else {
  801.       (*img->FetchTexel)(img, i, j, 0, (GLvoid *) rgba);
  802.       if (img->Format == GL_COLOR_INDEX) {
  803.          palette_sample(ctx, tObj, rgba[0], rgba);
  804.       }
  805.    }
  806. }
  807.  
  808.  
  809.  
  810. /*
  811.  * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
  812.  * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
  813.  */
  814. static INLINE void
  815. sample_2d_linear(GLcontext *ctx,
  816.                  const struct gl_texture_object *tObj,
  817.                  const struct gl_texture_image *img,
  818.                  const GLfloat texcoord[4],
  819.                  GLchan rgba[])
  820. {
  821.    const GLint width = img->Width2;
  822.    const GLint height = img->Height2;
  823.    GLint i0, j0, i1, j1;
  824.    GLuint useBorderColor;
  825.    GLfloat u, v;
  826.  
  827.    COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width,  i0, i1);
  828.    COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoord[1], v, height, j0, j1);
  829.  
  830.    useBorderColor = 0;
  831.    if (img->Border) {
  832.       i0 += img->Border;
  833.       i1 += img->Border;
  834.       j0 += img->Border;
  835.       j1 += img->Border;
  836.    }
  837.    else {
  838.       if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
  839.       if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
  840.       if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
  841.       if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
  842.    }
  843.  
  844.    {
  845.       const GLfloat a = FRAC(u);
  846.       const GLfloat b = FRAC(v);
  847.  
  848. #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
  849.       const GLfloat w00 = (1.0F-a) * (1.0F-b);
  850.       const GLfloat w10 =       a  * (1.0F-b);
  851.       const GLfloat w01 = (1.0F-a) *       b ;
  852.       const GLfloat w11 =       a  *       b ;
  853. #else /* CHAN_BITS == 8 */
  854.       /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
  855.       const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE);
  856.       const GLint w10 = IROUND_POS(      a  * (1.0F-b) * WEIGHT_SCALE);
  857.       const GLint w01 = IROUND_POS((1.0F-a) *       b  * WEIGHT_SCALE);
  858.       const GLint w11 = IROUND_POS(      a  *       b  * WEIGHT_SCALE);
  859. #endif
  860.       GLchan t00[4];
  861.       GLchan t10[4];
  862.       GLchan t01[4];
  863.       GLchan t11[4];
  864.  
  865.       if (useBorderColor & (I0BIT | J0BIT)) {
  866.          COPY_CHAN4(t00, tObj->_BorderChan);
  867.       }
  868.       else {
  869.          (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00);
  870.          if (img->Format == GL_COLOR_INDEX) {
  871.             palette_sample(ctx, tObj, t00[0], t00);
  872.          }
  873.       }
  874.       if (useBorderColor & (I1BIT | J0BIT)) {
  875.          COPY_CHAN4(t10, tObj->_BorderChan);
  876.       }
  877.       else {
  878.          (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10);
  879.          if (img->Format == GL_COLOR_INDEX) {
  880.             palette_sample(ctx, tObj, t10[0], t10);
  881.          }
  882.       }
  883.       if (useBorderColor & (I0BIT | J1BIT)) {
  884.          COPY_CHAN4(t01, tObj->_BorderChan);
  885.       }
  886.       else {
  887.          (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01);
  888.          if (img->Format == GL_COLOR_INDEX) {
  889.             palette_sample(ctx, tObj, t01[0], t01);
  890.          }
  891.       }
  892.       if (useBorderColor & (I1BIT | J1BIT)) {
  893.          COPY_CHAN4(t11, tObj->_BorderChan);
  894.       }
  895.       else {
  896.          (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11);
  897.          if (img->Format == GL_COLOR_INDEX) {
  898.             palette_sample(ctx, tObj, t11[0], t11);
  899.          }
  900.       }
  901. #if CHAN_TYPE == GL_FLOAT
  902.       rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0];
  903.       rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1];
  904.       rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2];
  905.       rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3];
  906. #elif CHAN_TYPE == GL_UNSIGNED_SHORT
  907.       rgba[0] = (GLchan) (w00 * t00[0] + w10 * t10[0] +
  908.                           w01 * t01[0] + w11 * t11[0] + 0.5);
  909.       rgba[1] = (GLchan) (w00 * t00[1] + w10 * t10[1] +
  910.                           w01 * t01[1] + w11 * t11[1] + 0.5);
  911.       rgba[2] = (GLchan) (w00 * t00[2] + w10 * t10[2] +
  912.                           w01 * t01[2] + w11 * t11[2] + 0.5);
  913.       rgba[3] = (GLchan) (w00 * t00[3] + w10 * t10[3] +
  914.                           w01 * t01[3] + w11 * t11[3] + 0.5);
  915. #else /* CHAN_BITS == 8 */
  916.       rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] +
  917.                            w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
  918.       rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] +
  919.                            w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT);
  920.       rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] +
  921.                            w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT);
  922.       rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] +
  923.                            w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT);
  924. #endif
  925.  
  926.    }
  927.  
  928. }
  929.  
  930.  
  931. /*
  932.  * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT
  933.  * and we're not using a paletted texture.
  934.  */
  935. static INLINE void
  936. sample_2d_linear_repeat(GLcontext *ctx,
  937.                         const struct gl_texture_object *tObj,
  938.                         const struct gl_texture_image *img,
  939.                         const GLfloat texcoord[4],
  940.                         GLchan rgba[])
  941. {
  942.    const GLint width = img->Width2;
  943.    const GLint height = img->Height2;
  944.    GLint i0, j0, i1, j1;
  945.    GLfloat u, v;
  946.  
  947.    ASSERT(tObj->WrapS == GL_REPEAT);
  948.    ASSERT(tObj->WrapT == GL_REPEAT);
  949.    ASSERT(img->Border == 0);
  950.    ASSERT(img->Format != GL_COLOR_INDEX);
  951.  
  952.    COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[0], u, width,  i0, i1);
  953.    COMPUTE_LINEAR_REPEAT_TEXEL_LOCATION(texcoord[1], v, height, j0, j1);
  954.  
  955.    {
  956.       const GLfloat a = FRAC(u);
  957.       const GLfloat b = FRAC(v);
  958.  
  959. #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
  960.       const GLfloat w00 = (1.0F-a) * (1.0F-b);
  961.       const GLfloat w10 =       a  * (1.0F-b);
  962.       const GLfloat w01 = (1.0F-a) *       b ;
  963.       const GLfloat w11 =       a  *       b ;
  964. #else /* CHAN_BITS == 8 */
  965.       /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
  966.       const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE);
  967.       const GLint w10 = IROUND_POS(      a  * (1.0F-b) * WEIGHT_SCALE);
  968.       const GLint w01 = IROUND_POS((1.0F-a) *       b  * WEIGHT_SCALE);
  969.       const GLint w11 = IROUND_POS(      a  *       b  * WEIGHT_SCALE);
  970. #endif
  971.       GLchan t00[4];
  972.       GLchan t10[4];
  973.       GLchan t01[4];
  974.       GLchan t11[4];
  975.  
  976.       (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00);
  977.       (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10);
  978.       (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01);
  979.       (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11);
  980.  
  981. #if CHAN_TYPE == GL_FLOAT
  982.       rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0];
  983.       rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1];
  984.       rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2];
  985.       rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3];
  986. #elif CHAN_TYPE == GL_UNSIGNED_SHORT
  987.       rgba[0] = (GLchan) (w00 * t00[0] + w10 * t10[0] +
  988.                           w01 * t01[0] + w11 * t11[0] + 0.5);
  989.       rgba[1] = (GLchan) (w00 * t00[1] + w10 * t10[1] +
  990.                           w01 * t01[1] + w11 * t11[1] + 0.5);
  991.       rgba[2] = (GLchan) (w00 * t00[2] + w10 * t10[2] +
  992.                           w01 * t01[2] + w11 * t11[2] + 0.5);
  993.       rgba[3] = (GLchan) (w00 * t00[3] + w10 * t10[3] +
  994.                           w01 * t01[3] + w11 * t11[3] + 0.5);
  995. #else /* CHAN_BITS == 8 */
  996.       rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] +
  997.                            w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
  998.       rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] +
  999.                            w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT);
  1000.       rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] +
  1001.                            w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT);
  1002.       rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] +
  1003.                            w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT);
  1004. #endif
  1005.  
  1006.    }
  1007.  
  1008. }
  1009.  
  1010.  
  1011.  
  1012. static void
  1013. sample_2d_nearest_mipmap_nearest(GLcontext *ctx,
  1014.                                  const struct gl_texture_object *tObj,
  1015.                                  GLuint n, GLfloat texcoord[][4],
  1016.                                  const GLfloat lambda[], GLchan rgba[][4])
  1017. {
  1018.    GLuint i;
  1019.    for (i = 0; i < n; i++) {
  1020.       GLint level;
  1021.       COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
  1022.       sample_2d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
  1023.    }
  1024. }
  1025.  
  1026.  
  1027.  
  1028. static void
  1029. sample_2d_linear_mipmap_nearest(GLcontext *ctx,
  1030.                                 const struct gl_texture_object *tObj,
  1031.                                 GLuint n, GLfloat texcoord[][4],
  1032.                                 const GLfloat lambda[], GLchan rgba[][4])
  1033. {
  1034.    GLuint i;
  1035.    ASSERT(lambda != NULL);
  1036.    for (i = 0; i < n; i++) {
  1037.       GLint level;
  1038.       COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
  1039.       sample_2d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
  1040.    }
  1041. }
  1042.  
  1043.  
  1044.  
  1045. static void
  1046. sample_2d_nearest_mipmap_linear(GLcontext *ctx,
  1047.                                 const struct gl_texture_object *tObj,
  1048.                                 GLuint n, GLfloat texcoord[][4],
  1049.                                 const GLfloat lambda[], GLchan rgba[][4])
  1050. {
  1051.    GLuint i;
  1052.    ASSERT(lambda != NULL);
  1053.    for (i = 0; i < n; i++) {
  1054.       GLint level;
  1055.       COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
  1056.       if (level >= tObj->_MaxLevel) {
  1057.          sample_2d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
  1058.                            texcoord[i], rgba[i]);
  1059.       }
  1060.       else {
  1061.          GLchan t0[4], t1[4];  /* texels */
  1062.          const GLfloat f = FRAC(lambda[i]);
  1063.          sample_2d_nearest(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
  1064.          sample_2d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
  1065.          rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1066.          rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1067.          rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1068.          rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1069.       }
  1070.    }
  1071. }
  1072.  
  1073.  
  1074.  
  1075. /* Trilinear filtering */
  1076. static void
  1077. sample_2d_linear_mipmap_linear( GLcontext *ctx,
  1078.                                 const struct gl_texture_object *tObj,
  1079.                                 GLuint n, GLfloat texcoord[][4],
  1080.                                 const GLfloat lambda[], GLchan rgba[][4] )
  1081. {
  1082.    GLuint i;
  1083.    ASSERT(lambda != NULL);
  1084.    for (i = 0; i < n; i++) {
  1085.       GLint level;
  1086.       COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
  1087.       if (level >= tObj->_MaxLevel) {
  1088.          sample_2d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel],
  1089.                           texcoord[i], rgba[i]);
  1090.       }
  1091.       else {
  1092.          GLchan t0[4], t1[4];  /* texels */
  1093.          const GLfloat f = FRAC(lambda[i]);
  1094.          sample_2d_linear(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
  1095.          sample_2d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
  1096.          rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1097.          rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1098.          rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1099.          rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1100.       }
  1101.    }
  1102. }
  1103.  
  1104.  
  1105. static void
  1106. sample_2d_linear_mipmap_linear_repeat( GLcontext *ctx,
  1107.                                        const struct gl_texture_object *tObj,
  1108.                                        GLuint n, GLfloat texcoord[][4],
  1109.                                        const GLfloat lambda[], GLchan rgba[][4] )
  1110. {
  1111.    GLuint i;
  1112.    ASSERT(lambda != NULL);
  1113.    ASSERT(tObj->WrapS == GL_REPEAT);
  1114.    ASSERT(tObj->WrapT == GL_REPEAT);
  1115.    for (i = 0; i < n; i++) {
  1116.       GLint level;
  1117.       COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
  1118.       if (level >= tObj->_MaxLevel) {
  1119.          sample_2d_linear_repeat(ctx, tObj, tObj->Image[tObj->_MaxLevel],
  1120.                                  texcoord[i], rgba[i]);
  1121.       }
  1122.       else {
  1123.          GLchan t0[4], t1[4];  /* texels */
  1124.          const GLfloat f = FRAC(lambda[i]);
  1125.          sample_2d_linear_repeat(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
  1126.          sample_2d_linear_repeat(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
  1127.          rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1128.          rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1129.          rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1130.          rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1131.       }
  1132.    }
  1133. }
  1134.  
  1135.  
  1136. static void
  1137. sample_nearest_2d( GLcontext *ctx, GLuint texUnit,
  1138.                    const struct gl_texture_object *tObj, GLuint n,
  1139.                    GLfloat texcoords[][4],
  1140.                    const GLfloat lambda[], GLchan rgba[][4] )
  1141. {
  1142.    GLuint i;
  1143.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  1144.    (void) lambda;
  1145.    for (i=0;i<n;i++) {
  1146.       sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
  1147.    }
  1148. }
  1149.  
  1150.  
  1151.  
  1152. static void
  1153. sample_linear_2d( GLcontext *ctx, GLuint texUnit,
  1154.                   const struct gl_texture_object *tObj, GLuint n,
  1155.                   GLfloat texcoords[][4],
  1156.                   const GLfloat lambda[], GLchan rgba[][4] )
  1157. {
  1158.    GLuint i;
  1159.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  1160.    (void) lambda;
  1161.    for (i=0;i<n;i++) {
  1162.       sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
  1163.    }
  1164. }
  1165.  
  1166.  
  1167. /*
  1168.  * Optimized 2-D texture sampling:
  1169.  *    S and T wrap mode == GL_REPEAT
  1170.  *    GL_NEAREST min/mag filter
  1171.  *    No border, 
  1172.  *    RowStride == Width,
  1173.  *    Format = GL_RGB
  1174.  */
  1175. static void
  1176. opt_sample_rgb_2d( GLcontext *ctx, GLuint texUnit,
  1177.                    const struct gl_texture_object *tObj,
  1178.                    GLuint n, GLfloat texcoords[][4],
  1179.                    const GLfloat lambda[], GLchan rgba[][4] )
  1180. {
  1181.    const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
  1182.    const GLfloat width = (GLfloat) img->Width;
  1183.    const GLfloat height = (GLfloat) img->Height;
  1184.    const GLint colMask = img->Width - 1;
  1185.    const GLint rowMask = img->Height - 1;
  1186.    const GLint shift = img->WidthLog2;
  1187.    GLuint k;
  1188.    (void) lambda;
  1189.    ASSERT(tObj->WrapS==GL_REPEAT);
  1190.    ASSERT(tObj->WrapT==GL_REPEAT);
  1191.    ASSERT(img->Border==0);
  1192.    ASSERT(img->Format==GL_RGB);
  1193.  
  1194.    for (k=0; k<n; k++) {
  1195.       GLint i = IFLOOR(texcoords[k][0] * width) & colMask;
  1196.       GLint j = IFLOOR(texcoords[k][1] * height) & rowMask;
  1197.       GLint pos = (j << shift) | i;
  1198.       GLchan *texel = ((GLchan *) img->Data) + 3*pos;
  1199.       rgba[k][RCOMP] = texel[0];
  1200.       rgba[k][GCOMP] = texel[1];
  1201.       rgba[k][BCOMP] = texel[2];
  1202.    }
  1203. }
  1204.  
  1205.  
  1206. /*
  1207.  * Optimized 2-D texture sampling:
  1208.  *    S and T wrap mode == GL_REPEAT
  1209.  *    GL_NEAREST min/mag filter
  1210.  *    No border
  1211.  *    RowStride == Width,
  1212.  *    Format = GL_RGBA
  1213.  */
  1214. static void
  1215. opt_sample_rgba_2d( GLcontext *ctx, GLuint texUnit,
  1216.                     const struct gl_texture_object *tObj,
  1217.                     GLuint n, GLfloat texcoords[][4],
  1218.                     const GLfloat lambda[], GLchan rgba[][4] )
  1219. {
  1220.    const struct gl_texture_image *img = tObj->Image[tObj->BaseLevel];
  1221.    const GLfloat width = (GLfloat) img->Width;
  1222.    const GLfloat height = (GLfloat) img->Height;
  1223.    const GLint colMask = img->Width - 1;
  1224.    const GLint rowMask = img->Height - 1;
  1225.    const GLint shift = img->WidthLog2;
  1226.    GLuint i;
  1227.    (void) lambda;
  1228.    ASSERT(tObj->WrapS==GL_REPEAT);
  1229.    ASSERT(tObj->WrapT==GL_REPEAT);
  1230.    ASSERT(img->Border==0);
  1231.    ASSERT(img->Format==GL_RGBA);
  1232.  
  1233.    for (i = 0; i < n; i++) {
  1234.       const GLint col = IFLOOR(texcoords[i][0] * width) & colMask;
  1235.       const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask;
  1236.       const GLint pos = (row << shift) | col;
  1237.       const GLchan *texel = ((GLchan *) img->Data) + (pos << 2);    /* pos*4 */
  1238.       COPY_CHAN4(rgba[i], texel);
  1239.    }
  1240. }
  1241.  
  1242.  
  1243. /*
  1244.  * Given an array of texture coordinate and lambda (level of detail)
  1245.  * values, return an array of texture sample.
  1246.  */
  1247. static void
  1248. sample_lambda_2d( GLcontext *ctx, GLuint texUnit,
  1249.                   const struct gl_texture_object *tObj,
  1250.                   GLuint n, GLfloat texcoords[][4],
  1251.                   const GLfloat lambda[], GLchan rgba[][4] )
  1252. {
  1253.    const struct gl_texture_image *tImg = tObj->Image[tObj->BaseLevel];
  1254.    GLuint minStart, minEnd;  /* texels with minification */
  1255.    GLuint magStart, magEnd;  /* texels with magnification */
  1256.  
  1257.    const GLboolean repeatNoBorder = (tObj->WrapS == GL_REPEAT)
  1258.       && (tObj->WrapT == GL_REPEAT)
  1259.       && (tImg->Border == 0 && (tImg->Width == tImg->RowStride))
  1260.       && (tImg->Format != GL_COLOR_INDEX);
  1261.  
  1262.    ASSERT(lambda != NULL);
  1263.    compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
  1264.                           n, lambda, &minStart, &minEnd, &magStart, &magEnd);
  1265.  
  1266.    if (minStart < minEnd) {
  1267.       /* do the minified texels */
  1268.       const GLuint m = minEnd - minStart;
  1269.       switch (tObj->MinFilter) {
  1270.       case GL_NEAREST:
  1271.          if (repeatNoBorder) {
  1272.             switch (tImg->Format) {
  1273.             case GL_RGB:
  1274.                opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + minStart,
  1275.                                  NULL, rgba + minStart);
  1276.                break;
  1277.             case GL_RGBA:
  1278.            opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + minStart,
  1279.                                   NULL, rgba + minStart);
  1280.                break;
  1281.             default:
  1282.                sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart,
  1283.                                  NULL, rgba + minStart );
  1284.             }
  1285.          }
  1286.          else {
  1287.             sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + minStart,
  1288.                               NULL, rgba + minStart);
  1289.          }
  1290.          break;
  1291.       case GL_LINEAR:
  1292.      sample_linear_2d(ctx, texUnit, tObj, m, texcoords + minStart,
  1293.               NULL, rgba + minStart);
  1294.          break;
  1295.       case GL_NEAREST_MIPMAP_NEAREST:
  1296.          sample_2d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  1297.                                           lambda + minStart, rgba + minStart);
  1298.          break;
  1299.       case GL_LINEAR_MIPMAP_NEAREST:
  1300.          sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  1301.                                          lambda + minStart, rgba + minStart);
  1302.          break;
  1303.       case GL_NEAREST_MIPMAP_LINEAR:
  1304.          sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1305.                                          lambda + minStart, rgba + minStart);
  1306.          break;
  1307.       case GL_LINEAR_MIPMAP_LINEAR:
  1308.          if (repeatNoBorder)
  1309.             sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m,
  1310.                   texcoords + minStart, lambda + minStart, rgba + minStart);
  1311.          else
  1312.             sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1313.                                         lambda + minStart, rgba + minStart);
  1314.          break;
  1315.       default:
  1316.          _mesa_problem(ctx, "Bad min filter in sample_2d_texture");
  1317.          return;
  1318.       }
  1319.    }
  1320.  
  1321.    if (magStart < magEnd) {
  1322.       /* do the magnified texels */
  1323.       const GLuint m = magEnd - magStart;
  1324.  
  1325.       switch (tObj->MagFilter) {
  1326.       case GL_NEAREST:
  1327.          if (repeatNoBorder) {
  1328.             switch (tImg->Format) {
  1329.             case GL_RGB:
  1330.                opt_sample_rgb_2d(ctx, texUnit, tObj, m, texcoords + magStart,
  1331.                                  NULL, rgba + magStart);
  1332.                break;
  1333.             case GL_RGBA:
  1334.            opt_sample_rgba_2d(ctx, texUnit, tObj, m, texcoords + magStart,
  1335.                                   NULL, rgba + magStart);
  1336.                break;
  1337.             default:
  1338.                sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart,
  1339.                                  NULL, rgba + magStart );
  1340.             }
  1341.          }
  1342.          else {
  1343.             sample_nearest_2d(ctx, texUnit, tObj, m, texcoords + magStart,
  1344.                               NULL, rgba + magStart);
  1345.          }
  1346.          break;
  1347.       case GL_LINEAR:
  1348.      sample_linear_2d(ctx, texUnit, tObj, m, texcoords + magStart,
  1349.               NULL, rgba + magStart);
  1350.          break;
  1351.       default:
  1352.          _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d");
  1353.       }
  1354.    }
  1355. }
  1356.  
  1357.  
  1358.  
  1359. /**********************************************************************/
  1360. /*                    3-D Texture Sampling Functions                  */
  1361. /**********************************************************************/
  1362.  
  1363. /*
  1364.  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  1365.  */
  1366. static void
  1367. sample_3d_nearest(GLcontext *ctx,
  1368.                   const struct gl_texture_object *tObj,
  1369.                   const struct gl_texture_image *img,
  1370.                   const GLfloat texcoord[4],
  1371.                   GLchan rgba[4])
  1372. {
  1373.    const GLint width = img->Width2;     /* without border, power of two */
  1374.    const GLint height = img->Height2;   /* without border, power of two */
  1375.    const GLint depth = img->Depth2;     /* without border, power of two */
  1376.    GLint i, j, k;
  1377.  
  1378.    COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoord[0], width,  i);
  1379.    COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoord[1], height, j);
  1380.    COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, texcoord[2], depth,  k);
  1381.  
  1382.    if (i < 0 || i >= (GLint) img->Width ||
  1383.        j < 0 || j >= (GLint) img->Height ||
  1384.        k < 0 || k >= (GLint) img->Depth) {
  1385.       /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
  1386.       COPY_CHAN4(rgba, tObj->_BorderChan);
  1387.    }
  1388.    else {
  1389.       (*img->FetchTexel)(img, i, j, k, (GLvoid *) rgba);
  1390.       if (img->Format == GL_COLOR_INDEX) {
  1391.          palette_sample(ctx, tObj, rgba[0], rgba);
  1392.       }
  1393.    }
  1394. }
  1395.  
  1396.  
  1397.  
  1398. /*
  1399.  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  1400.  */
  1401. static void
  1402. sample_3d_linear(GLcontext *ctx,
  1403.                  const struct gl_texture_object *tObj,
  1404.                  const struct gl_texture_image *img,
  1405.                  const GLfloat texcoord[4],
  1406.                  GLchan rgba[4])
  1407. {
  1408.    const GLint width = img->Width2;
  1409.    const GLint height = img->Height2;
  1410.    const GLint depth = img->Depth2;
  1411.    GLint i0, j0, k0, i1, j1, k1;
  1412.    GLuint useBorderColor;
  1413.    GLfloat u, v, w;
  1414.  
  1415.    COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoord[0], u, width,  i0, i1);
  1416.    COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoord[1], v, height, j0, j1);
  1417.    COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapR, texcoord[2], w, depth,  k0, k1);
  1418.  
  1419.    useBorderColor = 0;
  1420.    if (img->Border) {
  1421.       i0 += img->Border;
  1422.       i1 += img->Border;
  1423.       j0 += img->Border;
  1424.       j1 += img->Border;
  1425.       k0 += img->Border;
  1426.       k1 += img->Border;
  1427.    }
  1428.    else {
  1429.       /* check if sampling texture border color */
  1430.       if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
  1431.       if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
  1432.       if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
  1433.       if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
  1434.       if (k0 < 0 || k0 >= depth)   useBorderColor |= K0BIT;
  1435.       if (k1 < 0 || k1 >= depth)   useBorderColor |= K1BIT;
  1436.    }
  1437.  
  1438.    {
  1439.       const GLfloat a = FRAC(u);
  1440.       const GLfloat b = FRAC(v);
  1441.       const GLfloat c = FRAC(w);
  1442.  
  1443. #if CHAN_TYPE == GL_FLOAT || CHAN_TYPE == GL_UNSIGNED_SHORT
  1444.       /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
  1445.       GLfloat w000 = (1.0F-a) * (1.0F-b) * (1.0F-c);
  1446.       GLfloat w100 =       a  * (1.0F-b) * (1.0F-c);
  1447.       GLfloat w010 = (1.0F-a) *       b  * (1.0F-c);
  1448.       GLfloat w110 =       a  *       b  * (1.0F-c);
  1449.       GLfloat w001 = (1.0F-a) * (1.0F-b) *       c ;
  1450.       GLfloat w101 =       a  * (1.0F-b) *       c ;
  1451.       GLfloat w011 = (1.0F-a) *       b  *       c ;
  1452.       GLfloat w111 =       a  *       b  *       c ;
  1453. #else /* CHAN_BITS == 8 */
  1454.       /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
  1455.       GLint w000 = IROUND_POS((1.0F-a) * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
  1456.       GLint w100 = IROUND_POS(      a  * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
  1457.       GLint w010 = IROUND_POS((1.0F-a) *       b  * (1.0F-c) * WEIGHT_SCALE);
  1458.       GLint w110 = IROUND_POS(      a  *       b  * (1.0F-c) * WEIGHT_SCALE);
  1459.       GLint w001 = IROUND_POS((1.0F-a) * (1.0F-b) *       c  * WEIGHT_SCALE);
  1460.       GLint w101 = IROUND_POS(      a  * (1.0F-b) *       c  * WEIGHT_SCALE);
  1461.       GLint w011 = IROUND_POS((1.0F-a) *       b  *       c  * WEIGHT_SCALE);
  1462.       GLint w111 = IROUND_POS(      a  *       b  *       c  * WEIGHT_SCALE);
  1463. #endif
  1464.  
  1465.       GLchan t000[4], t010[4], t001[4], t011[4];
  1466.       GLchan t100[4], t110[4], t101[4], t111[4];
  1467.  
  1468.       if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
  1469.          COPY_CHAN4(t000, tObj->_BorderChan);
  1470.       }
  1471.       else {
  1472.          (*img->FetchTexel)(img, i0, j0, k0, (GLvoid *) t000);
  1473.          if (img->Format == GL_COLOR_INDEX) {
  1474.             palette_sample(ctx, tObj, t000[0], t000);
  1475.          }
  1476.       }
  1477.       if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
  1478.          COPY_CHAN4(t100, tObj->_BorderChan);
  1479.       }
  1480.       else {
  1481.          (*img->FetchTexel)(img, i1, j0, k0, (GLvoid *) t100);
  1482.          if (img->Format == GL_COLOR_INDEX) {
  1483.             palette_sample(ctx, tObj, t100[0], t100);
  1484.          }
  1485.       }
  1486.       if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
  1487.          COPY_CHAN4(t010, tObj->_BorderChan);
  1488.       }
  1489.       else {
  1490.          (*img->FetchTexel)(img, i0, j1, k0, (GLvoid *) t010);
  1491.          if (img->Format == GL_COLOR_INDEX) {
  1492.             palette_sample(ctx, tObj, t010[0], t010);
  1493.          }
  1494.       }
  1495.       if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
  1496.          COPY_CHAN4(t110, tObj->_BorderChan);
  1497.       }
  1498.       else {
  1499.          (*img->FetchTexel)(img, i1, j1, k0, (GLvoid *) t110);
  1500.          if (img->Format == GL_COLOR_INDEX) {
  1501.             palette_sample(ctx, tObj, t110[0], t110);
  1502.          }
  1503.       }
  1504.  
  1505.       if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
  1506.          COPY_CHAN4(t001, tObj->_BorderChan);
  1507.       }
  1508.       else {
  1509.          (*img->FetchTexel)(img, i0, j0, k1, (GLvoid *) t001);
  1510.          if (img->Format == GL_COLOR_INDEX) {
  1511.             palette_sample(ctx, tObj, t001[0], t001);
  1512.          }
  1513.       }
  1514.       if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
  1515.          COPY_CHAN4(t101, tObj->_BorderChan);
  1516.       }
  1517.       else {
  1518.          (*img->FetchTexel)(img, i1, j0, k1, (GLvoid *) t101);
  1519.          if (img->Format == GL_COLOR_INDEX) {
  1520.             palette_sample(ctx, tObj, t101[0], t101);
  1521.          }
  1522.       }
  1523.       if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
  1524.          COPY_CHAN4(t011, tObj->_BorderChan);
  1525.       }
  1526.       else {
  1527.          (*img->FetchTexel)(img, i0, j1, k1, (GLvoid *) t011);
  1528.          if (img->Format == GL_COLOR_INDEX) {
  1529.             palette_sample(ctx, tObj, t011[0], t011);
  1530.          }
  1531.       }
  1532.       if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
  1533.          COPY_CHAN4(t111, tObj->_BorderChan);
  1534.       }
  1535.       else {
  1536.          (*img->FetchTexel)(img, i1, j1, k1, (GLvoid *) t111);
  1537.          if (img->Format == GL_COLOR_INDEX) {
  1538.             palette_sample(ctx, tObj, t111[0], t111);
  1539.          }
  1540.       }
  1541.  
  1542. #if CHAN_TYPE == GL_FLOAT
  1543.       rgba[0] = w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
  1544.                 w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0];
  1545.       rgba[1] = w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
  1546.                 w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1];
  1547.       rgba[2] = w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
  1548.                 w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2];
  1549.       rgba[3] = w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
  1550.                 w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3];
  1551. #elif CHAN_TYPE == GL_UNSIGNED_SHORT
  1552.       rgba[0] = (GLchan) (w000*t000[0] + w010*t010[0] +
  1553.                           w001*t001[0] + w011*t011[0] +
  1554.                           w100*t100[0] + w110*t110[0] +
  1555.                           w101*t101[0] + w111*t111[0] + 0.5);
  1556.       rgba[1] = (GLchan) (w000*t000[1] + w010*t010[1] +
  1557.                           w001*t001[1] + w011*t011[1] +
  1558.                           w100*t100[1] + w110*t110[1] +
  1559.                           w101*t101[1] + w111*t111[1] + 0.5);
  1560.       rgba[2] = (GLchan) (w000*t000[2] + w010*t010[2] +
  1561.                           w001*t001[2] + w011*t011[2] +
  1562.                           w100*t100[2] + w110*t110[2] +
  1563.                           w101*t101[2] + w111*t111[2] + 0.5);
  1564.       rgba[3] = (GLchan) (w000*t000[3] + w010*t010[3] +
  1565.                           w001*t001[3] + w011*t011[3] +
  1566.                           w100*t100[3] + w110*t110[3] +
  1567.                           w101*t101[3] + w111*t111[3] + 0.5);
  1568. #else /* CHAN_BITS == 8 */
  1569.       rgba[0] = (GLchan) (
  1570.                  (w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
  1571.                   w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0] )
  1572.                  >> WEIGHT_SHIFT);
  1573.       rgba[1] = (GLchan) (
  1574.                  (w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
  1575.                   w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1] )
  1576.                  >> WEIGHT_SHIFT);
  1577.       rgba[2] = (GLchan) (
  1578.                  (w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
  1579.                   w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2] )
  1580.                  >> WEIGHT_SHIFT);
  1581.       rgba[3] = (GLchan) (
  1582.                  (w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
  1583.                   w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] )
  1584.                  >> WEIGHT_SHIFT);
  1585. #endif
  1586.  
  1587.    }
  1588. }
  1589.  
  1590.  
  1591.  
  1592. static void
  1593. sample_3d_nearest_mipmap_nearest(GLcontext *ctx,
  1594.                                  const struct gl_texture_object *tObj,
  1595.                                  GLuint n, GLfloat texcoord[][4],
  1596.                                  const GLfloat lambda[], GLchan rgba[][4] )
  1597. {
  1598.    GLuint i;
  1599.    for (i = 0; i < n; i++) {
  1600.       GLint level;
  1601.       COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
  1602.       sample_3d_nearest(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
  1603.    }
  1604. }
  1605.  
  1606.  
  1607. static void
  1608. sample_3d_linear_mipmap_nearest(GLcontext *ctx,
  1609.                                 const struct gl_texture_object *tObj,
  1610.                                 GLuint n, GLfloat texcoord[][4],
  1611.                                 const GLfloat lambda[], GLchan rgba[][4])
  1612. {
  1613.    GLuint i;
  1614.    ASSERT(lambda != NULL);
  1615.    for (i = 0; i < n; i++) {
  1616.       GLint level;
  1617.       COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
  1618.       sample_3d_linear(ctx, tObj, tObj->Image[level], texcoord[i], rgba[i]);
  1619.    }
  1620. }
  1621.  
  1622.  
  1623. static void
  1624. sample_3d_nearest_mipmap_linear(GLcontext *ctx,
  1625.                                 const struct gl_texture_object *tObj,
  1626.                                 GLuint n, GLfloat texcoord[][4],
  1627.                                 const GLfloat lambda[], GLchan rgba[][4])
  1628. {
  1629.    GLuint i;
  1630.    ASSERT(lambda != NULL);
  1631.    for (i = 0; i < n; i++) {
  1632.       GLint level;
  1633.       COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
  1634.       if (level >= tObj->_MaxLevel) {
  1635.          sample_3d_nearest(ctx, tObj, tObj->Image[tObj->_MaxLevel],
  1636.                            texcoord[i], rgba[i]);
  1637.       }
  1638.       else {
  1639.          GLchan t0[4], t1[4];  /* texels */
  1640.          const GLfloat f = FRAC(lambda[i]);
  1641.          sample_3d_nearest(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
  1642.          sample_3d_nearest(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
  1643.          rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1644.          rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1645.          rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1646.          rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1647.       }
  1648.    }
  1649. }
  1650.  
  1651.  
  1652. static void
  1653. sample_3d_linear_mipmap_linear(GLcontext *ctx,
  1654.                                const struct gl_texture_object *tObj,
  1655.                                GLuint n, GLfloat texcoord[][4],
  1656.                                const GLfloat lambda[], GLchan rgba[][4])
  1657. {
  1658.    GLuint i;
  1659.    ASSERT(lambda != NULL);
  1660.    for (i = 0; i < n; i++) {
  1661.       GLint level;
  1662.       COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
  1663.       if (level >= tObj->_MaxLevel) {
  1664.          sample_3d_linear(ctx, tObj, tObj->Image[tObj->_MaxLevel],
  1665.                           texcoord[i], rgba[i]);
  1666.       }
  1667.       else {
  1668.          GLchan t0[4], t1[4];  /* texels */
  1669.          const GLfloat f = FRAC(lambda[i]);
  1670.          sample_3d_linear(ctx, tObj, tObj->Image[level  ], texcoord[i], t0);
  1671.          sample_3d_linear(ctx, tObj, tObj->Image[level+1], texcoord[i], t1);
  1672.          rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1673.          rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1674.          rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1675.          rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1676.       }
  1677.    }
  1678. }
  1679.  
  1680.  
  1681. static void
  1682. sample_nearest_3d(GLcontext *ctx, GLuint texUnit,
  1683.                   const struct gl_texture_object *tObj, GLuint n,
  1684.                   GLfloat texcoords[][4], const GLfloat lambda[],
  1685.                   GLchan rgba[][4])
  1686. {
  1687.    GLuint i;
  1688.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  1689.    (void) lambda;
  1690.    for (i=0;i<n;i++) {
  1691.       sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
  1692.    }
  1693. }
  1694.  
  1695.  
  1696.  
  1697. static void
  1698. sample_linear_3d( GLcontext *ctx, GLuint texUnit,
  1699.                   const struct gl_texture_object *tObj, GLuint n,
  1700.                   GLfloat texcoords[][4],
  1701.           const GLfloat lambda[], GLchan rgba[][4] )
  1702. {
  1703.    GLuint i;
  1704.    struct gl_texture_image *image = tObj->Image[tObj->BaseLevel];
  1705.    (void) lambda;
  1706.    for (i=0;i<n;i++) {
  1707.       sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
  1708.    }
  1709. }
  1710.  
  1711.  
  1712. /*
  1713.  * Given an (s,t,r) texture coordinate and lambda (level of detail) value,
  1714.  * return a texture sample.
  1715.  */
  1716. static void
  1717. sample_lambda_3d( GLcontext *ctx, GLuint texUnit,
  1718.                   const struct gl_texture_object *tObj, GLuint n,
  1719.                   GLfloat texcoords[][4], const GLfloat lambda[],
  1720.                   GLchan rgba[][4] )
  1721. {
  1722.    GLuint minStart, minEnd;  /* texels with minification */
  1723.    GLuint magStart, magEnd;  /* texels with magnification */
  1724.    GLuint i;
  1725.  
  1726.    ASSERT(lambda != NULL);
  1727.    compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
  1728.                           n, lambda, &minStart, &minEnd, &magStart, &magEnd);
  1729.  
  1730.    if (minStart < minEnd) {
  1731.       /* do the minified texels */
  1732.       GLuint m = minEnd - minStart;
  1733.       switch (tObj->MinFilter) {
  1734.       case GL_NEAREST:
  1735.          for (i = minStart; i < minEnd; i++)
  1736.             sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
  1737.                               texcoords[i], rgba[i]);
  1738.          break;
  1739.       case GL_LINEAR:
  1740.          for (i = minStart; i < minEnd; i++)
  1741.             sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
  1742.                              texcoords[i], rgba[i]);
  1743.          break;
  1744.       case GL_NEAREST_MIPMAP_NEAREST:
  1745.          sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  1746.                                           lambda + minStart, rgba + minStart);
  1747.          break;
  1748.       case GL_LINEAR_MIPMAP_NEAREST:
  1749.          sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  1750.                                          lambda + minStart, rgba + minStart);
  1751.          break;
  1752.       case GL_NEAREST_MIPMAP_LINEAR:
  1753.          sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1754.                                          lambda + minStart, rgba + minStart);
  1755.          break;
  1756.       case GL_LINEAR_MIPMAP_LINEAR:
  1757.          sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1758.                                         lambda + minStart, rgba + minStart);
  1759.          break;
  1760.       default:
  1761.          _mesa_problem(ctx, "Bad min filter in sample_3d_texture");
  1762.          return;
  1763.       }
  1764.    }
  1765.  
  1766.    if (magStart < magEnd) {
  1767.       /* do the magnified texels */
  1768.       switch (tObj->MagFilter) {
  1769.       case GL_NEAREST:
  1770.          for (i = magStart; i < magEnd; i++)
  1771.             sample_3d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
  1772.                               texcoords[i], rgba[i]);
  1773.          break;
  1774.       case GL_LINEAR:
  1775.          for (i = magStart; i < magEnd; i++)
  1776.             sample_3d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
  1777.                              texcoords[i], rgba[i]);
  1778.          break;
  1779.       default:
  1780.          _mesa_problem(ctx, "Bad mag filter in sample_3d_texture");
  1781.          return;
  1782.       }
  1783.    }
  1784. }
  1785.  
  1786.  
  1787. /**********************************************************************/
  1788. /*                Texture Cube Map Sampling Functions                 */
  1789. /**********************************************************************/
  1790.  
  1791. /*
  1792.  * Choose one of six sides of a texture cube map given the texture
  1793.  * coord (rx,ry,rz).  Return pointer to corresponding array of texture
  1794.  * images.
  1795.  */
  1796. static const struct gl_texture_image **
  1797. choose_cube_face(const struct gl_texture_object *texObj,
  1798.                  const GLfloat texcoord[4], GLfloat newCoord[4])
  1799. {
  1800. /*
  1801.       major axis
  1802.       direction     target                             sc     tc    ma
  1803.       ----------    -------------------------------    ---    ---   ---
  1804.        +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
  1805.        -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
  1806.        +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
  1807.        -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
  1808.        +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
  1809.        -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
  1810. */
  1811.    const GLfloat rx = texcoord[0];
  1812.    const GLfloat ry = texcoord[1];
  1813.    const GLfloat rz = texcoord[2];
  1814.    const struct gl_texture_image **imgArray;
  1815.    const GLfloat arx = ABSF(rx),   ary = ABSF(ry),   arz = ABSF(rz);
  1816.    GLfloat sc, tc, ma;
  1817.  
  1818.    if (arx > ary && arx > arz) {
  1819.       if (rx >= 0.0F) {
  1820.          imgArray = (const struct gl_texture_image **) texObj->Image;
  1821.          sc = -rz;
  1822.          tc = -ry;
  1823.          ma = arx;
  1824.       }
  1825.       else {
  1826.          imgArray = (const struct gl_texture_image **) texObj->NegX;
  1827.          sc = rz;
  1828.          tc = -ry;
  1829.          ma = arx;
  1830.       }
  1831.    }
  1832.    else if (ary > arx && ary > arz) {
  1833.       if (ry >= 0.0F) {
  1834.          imgArray = (const struct gl_texture_image **) texObj->PosY;
  1835.          sc = rx;
  1836.          tc = rz;
  1837.          ma = ary;
  1838.       }
  1839.       else {
  1840.          imgArray = (const struct gl_texture_image **) texObj->NegY;
  1841.          sc = rx;
  1842.          tc = -rz;
  1843.          ma = ary;
  1844.       }
  1845.    }
  1846.    else {
  1847.       if (rz > 0.0F) {
  1848.          imgArray = (const struct gl_texture_image **) texObj->PosZ;
  1849.          sc = rx;
  1850.          tc = -ry;
  1851.          ma = arz;
  1852.       }
  1853.       else {
  1854.          imgArray = (const struct gl_texture_image **) texObj->NegZ;
  1855.          sc = -rx;
  1856.          tc = -ry;
  1857.          ma = arz;
  1858.       }
  1859.    }
  1860.  
  1861.    newCoord[0] = ( sc / ma + 1.0F ) * 0.5F;
  1862.    newCoord[1] = ( tc / ma + 1.0F ) * 0.5F;
  1863.    return imgArray;
  1864. }
  1865.  
  1866.  
  1867. static void
  1868. sample_nearest_cube(GLcontext *ctx, GLuint texUnit,
  1869.             const struct gl_texture_object *tObj, GLuint n,
  1870.                     GLfloat texcoords[][4], const GLfloat lambda[],
  1871.                     GLchan rgba[][4])
  1872. {
  1873.    GLuint i;
  1874.    (void) lambda;
  1875.    for (i = 0; i < n; i++) {
  1876.       const struct gl_texture_image **images;
  1877.       GLfloat newCoord[4];
  1878.       images = choose_cube_face(tObj, texcoords[i], newCoord);
  1879.       sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
  1880.                         newCoord, rgba[i]);
  1881.    }
  1882. }
  1883.  
  1884.  
  1885. static void
  1886. sample_linear_cube(GLcontext *ctx, GLuint texUnit,
  1887.            const struct gl_texture_object *tObj, GLuint n,
  1888.                    GLfloat texcoords[][4],
  1889.            const GLfloat lambda[], GLchan rgba[][4])
  1890. {
  1891.    GLuint i;
  1892.    (void) lambda;
  1893.    for (i = 0; i < n; i++) {
  1894.       const struct gl_texture_image **images;
  1895.       GLfloat newCoord[4];
  1896.       images = choose_cube_face(tObj, texcoords[i], newCoord);
  1897.       sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
  1898.                        newCoord, rgba[i]);
  1899.    }
  1900. }
  1901.  
  1902.  
  1903. static void
  1904. sample_cube_nearest_mipmap_nearest(GLcontext *ctx,
  1905.                                    const struct gl_texture_object *tObj,
  1906.                                    GLuint n, GLfloat texcoord[][4],
  1907.                                    const GLfloat lambda[], GLchan rgba[][4])
  1908. {
  1909.    GLuint i;
  1910.    ASSERT(lambda != NULL);
  1911.    for (i = 0; i < n; i++) {
  1912.       const struct gl_texture_image **images;
  1913.       GLfloat newCoord[4];
  1914.       GLint level;
  1915.       COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
  1916.       images = choose_cube_face(tObj, texcoord[i], newCoord);
  1917.       sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]);
  1918.    }
  1919. }
  1920.  
  1921.  
  1922. static void
  1923. sample_cube_linear_mipmap_nearest(GLcontext *ctx,
  1924.                                   const struct gl_texture_object *tObj,
  1925.                                   GLuint n, GLfloat texcoord[][4],
  1926.                                   const GLfloat lambda[], GLchan rgba[][4])
  1927. {
  1928.    GLuint i;
  1929.    ASSERT(lambda != NULL);
  1930.    for (i = 0; i < n; i++) {
  1931.       const struct gl_texture_image **images;
  1932.       GLfloat newCoord[4];
  1933.       GLint level;
  1934.       COMPUTE_NEAREST_MIPMAP_LEVEL(tObj, lambda[i], level);
  1935.       images = choose_cube_face(tObj, texcoord[i], newCoord);
  1936.       sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]);
  1937.    }
  1938. }
  1939.  
  1940.  
  1941. static void
  1942. sample_cube_nearest_mipmap_linear(GLcontext *ctx,
  1943.                                   const struct gl_texture_object *tObj,
  1944.                                   GLuint n, GLfloat texcoord[][4],
  1945.                                   const GLfloat lambda[], GLchan rgba[][4])
  1946. {
  1947.    GLuint i;
  1948.    ASSERT(lambda != NULL);
  1949.    for (i = 0; i < n; i++) {
  1950.       const struct gl_texture_image **images;
  1951.       GLfloat newCoord[4];
  1952.       GLint level;
  1953.       COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
  1954.       images = choose_cube_face(tObj, texcoord[i], newCoord);
  1955.       if (level >= tObj->_MaxLevel) {
  1956.          sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel],
  1957.                            newCoord, rgba[i]);
  1958.       }
  1959.       else {
  1960.          GLchan t0[4], t1[4];  /* texels */
  1961.          const GLfloat f = FRAC(lambda[i]);
  1962.          sample_2d_nearest(ctx, tObj, images[level  ], newCoord, t0);
  1963.          sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1);
  1964.          rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1965.          rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1966.          rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1967.          rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  1968.       }
  1969.    }
  1970. }
  1971.  
  1972.  
  1973. static void
  1974. sample_cube_linear_mipmap_linear(GLcontext *ctx,
  1975.                                  const struct gl_texture_object *tObj,
  1976.                                  GLuint n, GLfloat texcoord[][4],
  1977.                                  const GLfloat lambda[], GLchan rgba[][4])
  1978. {
  1979.    GLuint i;
  1980.    ASSERT(lambda != NULL);
  1981.    for (i = 0; i < n; i++) {
  1982.       const struct gl_texture_image **images;
  1983.       GLfloat newCoord[4];
  1984.       GLint level;
  1985.       COMPUTE_LINEAR_MIPMAP_LEVEL(tObj, lambda[i], level);
  1986.       images = choose_cube_face(tObj, texcoord[i], newCoord);
  1987.       if (level >= tObj->_MaxLevel) {
  1988.          sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel],
  1989.                           newCoord, rgba[i]);
  1990.       }
  1991.       else {
  1992.          GLchan t0[4], t1[4];
  1993.          const GLfloat f = FRAC(lambda[i]);
  1994.          sample_2d_linear(ctx, tObj, images[level  ], newCoord, t0);
  1995.          sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1);
  1996.          rgba[i][RCOMP] = CHAN_CAST ((1.0F-f) * t0[RCOMP] + f * t1[RCOMP]);
  1997.          rgba[i][GCOMP] = CHAN_CAST ((1.0F-f) * t0[GCOMP] + f * t1[GCOMP]);
  1998.          rgba[i][BCOMP] = CHAN_CAST ((1.0F-f) * t0[BCOMP] + f * t1[BCOMP]);
  1999.          rgba[i][ACOMP] = CHAN_CAST ((1.0F-f) * t0[ACOMP] + f * t1[ACOMP]);
  2000.       }
  2001.    }
  2002. }
  2003.  
  2004.  
  2005. static void
  2006. sample_lambda_cube( GLcontext *ctx, GLuint texUnit,
  2007.             const struct gl_texture_object *tObj, GLuint n,
  2008.             GLfloat texcoords[][4], const GLfloat lambda[],
  2009.             GLchan rgba[][4])
  2010. {
  2011.    GLuint minStart, minEnd;  /* texels with minification */
  2012.    GLuint magStart, magEnd;  /* texels with magnification */
  2013.  
  2014.    ASSERT(lambda != NULL);
  2015.    compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
  2016.                           n, lambda, &minStart, &minEnd, &magStart, &magEnd);
  2017.  
  2018.    if (minStart < minEnd) {
  2019.       /* do the minified texels */
  2020.       const GLuint m = minEnd - minStart;
  2021.       switch (tObj->MinFilter) {
  2022.       case GL_NEAREST:
  2023.          sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + minStart,
  2024.                              lambda + minStart, rgba + minStart);
  2025.          break;
  2026.       case GL_LINEAR:
  2027.          sample_linear_cube(ctx, texUnit, tObj, m, texcoords + minStart,
  2028.                             lambda + minStart, rgba + minStart);
  2029.          break;
  2030.       case GL_NEAREST_MIPMAP_NEAREST:
  2031.          sample_cube_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  2032.                                            lambda + minStart, rgba + minStart);
  2033.          break;
  2034.       case GL_LINEAR_MIPMAP_NEAREST:
  2035.          sample_cube_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  2036.                                            lambda + minStart, rgba + minStart);
  2037.          break;
  2038.       case GL_NEAREST_MIPMAP_LINEAR:
  2039.          sample_cube_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  2040.                                            lambda + minStart, rgba + minStart);
  2041.          break;
  2042.       case GL_LINEAR_MIPMAP_LINEAR:
  2043.          sample_cube_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  2044.                                           lambda + minStart, rgba + minStart);
  2045.          break;
  2046.       default:
  2047.          _mesa_problem(ctx, "Bad min filter in sample_lambda_cube");
  2048.       }
  2049.    }
  2050.  
  2051.    if (magStart < magEnd) {
  2052.       /* do the magnified texels */
  2053.       const GLuint m = magEnd - magStart;
  2054.       switch (tObj->MagFilter) {
  2055.       case GL_NEAREST:
  2056.          sample_nearest_cube(ctx, texUnit, tObj, m, texcoords + magStart,
  2057.                              lambda + magStart, rgba + magStart);
  2058.          break;
  2059.       case GL_LINEAR:
  2060.          sample_linear_cube(ctx, texUnit, tObj, m, texcoords + magStart,
  2061.                             lambda + magStart, rgba + magStart);
  2062.          break;
  2063.       default:
  2064.          _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube");
  2065.       }
  2066.    }
  2067. }
  2068.  
  2069.  
  2070. /**********************************************************************/
  2071. /*               Texture Rectangle Sampling Functions                 */
  2072. /**********************************************************************/
  2073.  
  2074. static void
  2075. sample_nearest_rect(GLcontext *ctx, GLuint texUnit,
  2076.             const struct gl_texture_object *tObj, GLuint n,
  2077.                     GLfloat texcoords[][4], const GLfloat lambda[],
  2078.                     GLchan rgba[][4])
  2079. {
  2080.    const struct gl_texture_image *img = tObj->Image[0];
  2081.    const GLfloat width = (GLfloat) img->Width;
  2082.    const GLfloat height = (GLfloat) img->Height;
  2083.    const GLint width_minus_1 = img->Width - 1;
  2084.    const GLint height_minus_1 = img->Height - 1;
  2085.    GLuint i;
  2086.  
  2087.    (void) texUnit;
  2088.    (void) lambda;
  2089.  
  2090.    ASSERT(tObj->WrapS == GL_CLAMP ||
  2091.           tObj->WrapS == GL_CLAMP_TO_EDGE ||
  2092.           tObj->WrapS == GL_CLAMP_TO_BORDER_ARB);
  2093.    ASSERT(tObj->WrapT == GL_CLAMP ||
  2094.           tObj->WrapT == GL_CLAMP_TO_EDGE ||
  2095.           tObj->WrapT == GL_CLAMP_TO_BORDER_ARB);
  2096.    ASSERT(img->Format != GL_COLOR_INDEX);
  2097.  
  2098.    /* XXX move Wrap mode tests outside of loops for common cases */
  2099.    for (i = 0; i < n; i++) {
  2100.       GLint row, col;
  2101.       /* NOTE: we DO NOT use [0, 1] texture coordinates! */
  2102.       if (tObj->WrapS == GL_CLAMP) {
  2103.          col = IFLOOR( CLAMP(texcoords[i][0], 0.0F, width) );
  2104.       }
  2105.       else if (tObj->WrapS == GL_CLAMP_TO_EDGE) {
  2106.          col = IFLOOR( CLAMP(texcoords[i][0], 0.5F, width - 0.5F) );
  2107.       }
  2108.       else {
  2109.          col = IFLOOR( CLAMP(texcoords[i][0], -0.5F, width + 0.5F) );
  2110.       }
  2111.       if (tObj->WrapT == GL_CLAMP) {
  2112.          row = IFLOOR( CLAMP(texcoords[i][1], 0.0F, height) );
  2113.       }
  2114.       else if (tObj->WrapT == GL_CLAMP_TO_EDGE) {
  2115.          row = IFLOOR( CLAMP(texcoords[i][1], 0.5F, height - 0.5F) );
  2116.       }
  2117.       else {
  2118.          row = IFLOOR( CLAMP(texcoords[i][1], -0.5F, height + 0.5F) );
  2119.       }
  2120.  
  2121.       col = CLAMP(col, 0, width_minus_1);
  2122.       row = CLAMP(row, 0, height_minus_1);
  2123.  
  2124.       (*img->FetchTexel)(img, col, row, 0, (GLvoid *) rgba[i]);
  2125.    }
  2126. }
  2127.  
  2128.  
  2129. static void
  2130. sample_linear_rect(GLcontext *ctx, GLuint texUnit,
  2131.            const struct gl_texture_object *tObj, GLuint n,
  2132.                    GLfloat texcoords[][4],
  2133.            const GLfloat lambda[], GLchan rgba[][4])
  2134. {
  2135.    const struct gl_texture_image *img = tObj->Image[0];
  2136.    const GLfloat width = (GLfloat) img->Width;
  2137.    const GLfloat height = (GLfloat) img->Height;
  2138.    const GLint width_minus_1 = img->Width - 1;
  2139.    const GLint height_minus_1 = img->Height - 1;
  2140.    GLuint i;
  2141.  
  2142.    (void) texUnit;
  2143.    (void) lambda;
  2144.  
  2145.    ASSERT(tObj->WrapS == GL_CLAMP ||
  2146.           tObj->WrapS == GL_CLAMP_TO_EDGE ||
  2147.           tObj->WrapS == GL_CLAMP_TO_BORDER_ARB);
  2148.    ASSERT(tObj->WrapT == GL_CLAMP ||
  2149.           tObj->WrapT == GL_CLAMP_TO_EDGE ||
  2150.           tObj->WrapT == GL_CLAMP_TO_BORDER_ARB);
  2151.    ASSERT(img->Format != GL_COLOR_INDEX);
  2152.  
  2153.    /* XXX lots of opportunity for optimization in this loop */
  2154.    for (i = 0; i < n; i++) {
  2155.       GLfloat frow, fcol;
  2156.       GLint row0, col0, row1, col1;
  2157.       GLchan t00[4], t01[4], t10[4], t11[4];
  2158.       GLfloat a, b, w00, w01, w10, w11;
  2159.  
  2160.       /* NOTE: we DO NOT use [0, 1] texture coordinates! */
  2161.       if (tObj->WrapS == GL_CLAMP) {
  2162.          fcol = CLAMP(texcoords[i][0], 0.0F, width);
  2163.       }
  2164.       else if (tObj->WrapS == GL_CLAMP_TO_EDGE) {
  2165.          fcol = CLAMP(texcoords[i][0], 0.5F, width - 0.5F);
  2166.       }
  2167.       else {
  2168.          fcol = CLAMP(texcoords[i][0], -0.5F, width + 0.5F);
  2169.       }
  2170.       if (tObj->WrapT == GL_CLAMP) {
  2171.          frow = CLAMP(texcoords[i][1], 0.0F, height);
  2172.       }
  2173.       else if (tObj->WrapT == GL_CLAMP_TO_EDGE) {
  2174.          frow = CLAMP(texcoords[i][1], 0.5F, height - 0.5F);
  2175.       }
  2176.       else {
  2177.          frow = CLAMP(texcoords[i][1], -0.5F, height + 0.5F);
  2178.       }
  2179.  
  2180.       /* compute integer rows/columns */
  2181.       col0 = IFLOOR(fcol);
  2182.       col1 = col0 + 1;
  2183.       col0 = CLAMP(col0, 0, width_minus_1);
  2184.       col1 = CLAMP(col1, 0, width_minus_1);
  2185.       row0 = IFLOOR(frow);
  2186.       row1 = row0 + 1;
  2187.       row0 = CLAMP(row0, 0, height_minus_1);
  2188.       row1 = CLAMP(row1, 0, height_minus_1);
  2189.  
  2190.       /* get four texel samples */
  2191.       (*img->FetchTexel)(img, col0, row0, 0, (GLvoid *) t00);
  2192.       (*img->FetchTexel)(img, col1, row0, 0, (GLvoid *) t10);
  2193.       (*img->FetchTexel)(img, col0, row1, 0, (GLvoid *) t01);
  2194.       (*img->FetchTexel)(img, col1, row1, 0, (GLvoid *) t11);
  2195.  
  2196.       /* compute sample weights */
  2197.       a = FRAC(fcol);
  2198.       b = FRAC(frow);
  2199.       w00 = (1.0F-a) * (1.0F-b);
  2200.       w10 =       a  * (1.0F-b);
  2201.       w01 = (1.0F-a) *       b ;
  2202.       w11 =       a  *       b ;
  2203.  
  2204.       /* compute weighted average of samples */
  2205.       rgba[i][0] = 
  2206.       (GLchan) (w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]);
  2207.       rgba[i][1] = 
  2208.       (GLchan) (w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]);
  2209.       rgba[i][2] = 
  2210.       (GLchan) (w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]);
  2211.       rgba[i][3] = 
  2212.       (GLchan) (w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]);
  2213.    }
  2214. }
  2215.  
  2216.  
  2217. static void
  2218. sample_lambda_rect( GLcontext *ctx, GLuint texUnit,
  2219.             const struct gl_texture_object *tObj, GLuint n,
  2220.             GLfloat texcoords[][4], const GLfloat lambda[],
  2221.             GLchan rgba[][4])
  2222. {
  2223.    GLuint minStart, minEnd, magStart, magEnd;
  2224.  
  2225.    /* We only need lambda to decide between minification and magnification.
  2226.     * There is no mipmapping with rectangular textures.
  2227.     */
  2228.    compute_min_mag_ranges(SWRAST_CONTEXT(ctx)->_MinMagThresh[texUnit],
  2229.                           n, lambda, &minStart, &minEnd, &magStart, &magEnd);
  2230.  
  2231.    if (minStart < minEnd) {
  2232.       if (tObj->MinFilter == GL_NEAREST) {
  2233.          sample_nearest_rect( ctx, texUnit, tObj, minEnd - minStart,
  2234.                               texcoords + minStart, NULL, rgba + minStart);
  2235.       }
  2236.       else {
  2237.          sample_linear_rect( ctx, texUnit, tObj, minEnd - minStart,
  2238.                              texcoords + minStart, NULL, rgba + minStart);
  2239.       }
  2240.    }
  2241.    if (magStart < magEnd) {
  2242.       if (tObj->MagFilter == GL_NEAREST) {
  2243.          sample_nearest_rect( ctx, texUnit, tObj, magEnd - magStart,
  2244.                               texcoords + magStart, NULL, rgba + magStart);
  2245.       }
  2246.       else {
  2247.          sample_linear_rect( ctx, texUnit, tObj, magEnd - magStart,
  2248.                              texcoords + magStart, NULL, rgba + magStart);
  2249.       }
  2250.    }
  2251. }
  2252.  
  2253.  
  2254.  
  2255. /*
  2256.  * Sample a shadow/depth texture.
  2257.  */
  2258. static void
  2259. sample_depth_texture( GLcontext *ctx, GLuint unit,
  2260.                       const struct gl_texture_object *tObj, GLuint n,
  2261.                       GLfloat texcoords[][4], const GLfloat lambda[],
  2262.                       GLchan texel[][4] )
  2263. {
  2264.    const GLint baseLevel = tObj->BaseLevel;
  2265.    const struct gl_texture_image *texImage = tObj->Image[baseLevel];
  2266.    const GLuint width = texImage->Width;
  2267.    const GLuint height = texImage->Height;
  2268.    GLchan ambient;
  2269.    GLenum function;
  2270.    GLchan result;
  2271.  
  2272.    (void) unit;
  2273.  
  2274.    ASSERT(tObj->Image[tObj->BaseLevel]->Format == GL_DEPTH_COMPONENT);
  2275.    ASSERT(tObj->Target == GL_TEXTURE_1D ||
  2276.           tObj->Target == GL_TEXTURE_2D ||
  2277.           tObj->Target == GL_TEXTURE_RECTANGLE_NV);
  2278.  
  2279.    UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient);
  2280.  
  2281.    /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
  2282.  
  2283.    /* XXX this could be precomputed and saved in the texture object */
  2284.    if (tObj->CompareFlag) {
  2285.       /* GL_SGIX_shadow */
  2286.       if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
  2287.          function = GL_LEQUAL;
  2288.       }
  2289.       else {
  2290.          ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX);
  2291.          function = GL_GEQUAL;
  2292.       }
  2293.    }
  2294.    else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
  2295.       /* GL_ARB_shadow */
  2296.       function = tObj->CompareFunc;
  2297.    }
  2298.    else {
  2299.       function = GL_NONE;  /* pass depth through as grayscale */
  2300.    }
  2301.  
  2302.    if (tObj->MagFilter == GL_NEAREST) {
  2303.       GLuint i;
  2304.       for (i = 0; i < n; i++) {
  2305.          GLfloat depthSample;
  2306.          GLint col, row;
  2307.          /* XXX fix for texture rectangle! */
  2308.          COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoords[i][0], width, col);
  2309.          COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoords[i][1], height, row);
  2310.          depthSample = *((const GLfloat *) texImage->Data + row * width + col);
  2311.  
  2312.          switch (function) {
  2313.          case GL_LEQUAL:
  2314.             result = (texcoords[i][2] <= depthSample) ? CHAN_MAX : ambient;
  2315.             break;
  2316.          case GL_GEQUAL:
  2317.             result = (texcoords[i][2] >= depthSample) ? CHAN_MAX : ambient;
  2318.             break;
  2319.          case GL_LESS:
  2320.             result = (texcoords[i][2] < depthSample) ? CHAN_MAX : ambient;
  2321.             break;
  2322.          case GL_GREATER:
  2323.             result = (texcoords[i][2] > depthSample) ? CHAN_MAX : ambient;
  2324.             break;
  2325.          case GL_EQUAL:
  2326.             result = (texcoords[i][2] == depthSample) ? CHAN_MAX : ambient;
  2327.             break;
  2328.          case GL_NOTEQUAL:
  2329.             result = (texcoords[i][2] != depthSample) ? CHAN_MAX : ambient;
  2330.             break;
  2331.          case GL_ALWAYS:
  2332.             result = CHAN_MAX;
  2333.             break;
  2334.          case GL_NEVER:
  2335.             result = ambient;
  2336.             break;
  2337.          case GL_NONE:
  2338.             CLAMPED_FLOAT_TO_CHAN(result, depthSample);
  2339.             break;
  2340.          default:
  2341.             _mesa_problem(ctx, "Bad compare func in sample_depth_texture");
  2342.             return;
  2343.          }
  2344.  
  2345.          switch (tObj->DepthMode) {
  2346.          case GL_LUMINANCE:
  2347.             texel[i][RCOMP] = result;
  2348.             texel[i][GCOMP] = result;
  2349.             texel[i][BCOMP] = result;
  2350.             texel[i][ACOMP] = CHAN_MAX;
  2351.             break;
  2352.          case GL_INTENSITY:
  2353.             texel[i][RCOMP] = result;
  2354.             texel[i][GCOMP] = result;
  2355.             texel[i][BCOMP] = result;
  2356.             texel[i][ACOMP] = result;
  2357.             break;
  2358.          case GL_ALPHA:
  2359.             texel[i][RCOMP] = 0;
  2360.             texel[i][GCOMP] = 0;
  2361.             texel[i][BCOMP] = 0;
  2362.             texel[i][ACOMP] = result;
  2363.             break;
  2364.          default:
  2365.             _mesa_problem(ctx, "Bad depth texture mode");
  2366.          }
  2367.       }
  2368.    }
  2369.    else {
  2370.       GLuint i;
  2371.       ASSERT(tObj->MagFilter == GL_LINEAR);
  2372.       for (i = 0; i < n; i++) {
  2373.          GLfloat depth00, depth01, depth10, depth11;
  2374.          GLint i0, i1, j0, j1;
  2375.          GLfloat u, v;
  2376.          GLuint useBorderTexel;
  2377.  
  2378.          /* XXX fix for texture rectangle! */
  2379.          COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoords[i][0], u, width, i0, i1);
  2380.          COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoords[i][1], v, height,j0, j1);
  2381.  
  2382.          useBorderTexel = 0;
  2383.          if (texImage->Border) {
  2384.             i0 += texImage->Border;
  2385.             i1 += texImage->Border;
  2386.             j0 += texImage->Border;
  2387.             j1 += texImage->Border;
  2388.          }
  2389.          else {
  2390.             if (i0 < 0 || i0 >= (GLint) width)   useBorderTexel |= I0BIT;
  2391.             if (i1 < 0 || i1 >= (GLint) width)   useBorderTexel |= I1BIT;
  2392.             if (j0 < 0 || j0 >= (GLint) height)  useBorderTexel |= J0BIT;
  2393.             if (j1 < 0 || j1 >= (GLint) height)  useBorderTexel |= J1BIT;
  2394.          }
  2395.  
  2396.          /* get four depth samples from the texture */
  2397.          if (useBorderTexel & (I0BIT | J0BIT)) {
  2398.             depth00 = 1.0;
  2399.          }
  2400.          else {
  2401.             depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0);
  2402.          }
  2403.          if (useBorderTexel & (I1BIT | J0BIT)) {
  2404.             depth10 = 1.0;
  2405.          }
  2406.          else {
  2407.             depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1);
  2408.          }
  2409.          if (useBorderTexel & (I0BIT | J1BIT)) {
  2410.             depth01 = 1.0;
  2411.          }
  2412.          else {
  2413.             depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0);
  2414.          }
  2415.          if (useBorderTexel & (I1BIT | J1BIT)) {
  2416.             depth11 = 1.0;
  2417.          }
  2418.          else {
  2419.             depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1);
  2420.          }
  2421.  
  2422.          if (0) {
  2423.             /* compute a single weighted depth sample and do one comparison */
  2424.             const GLfloat a = FRAC(u + 1.0F);
  2425.             const GLfloat b = FRAC(v + 1.0F);
  2426.             const GLfloat w00 = (1.0F - a) * (1.0F - b);
  2427.             const GLfloat w10 = (       a) * (1.0F - b);
  2428.             const GLfloat w01 = (1.0F - a) * (       b);
  2429.             const GLfloat w11 = (       a) * (       b);
  2430.             const GLfloat depthSample = w00 * depth00 + w10 * depth10
  2431.                                       + w01 * depth01 + w11 * depth11;
  2432.             if ((depthSample <= texcoords[i][2] && function == GL_LEQUAL) ||
  2433.                 (depthSample >= texcoords[i][2] && function == GL_GEQUAL)) {
  2434.                result  = ambient;
  2435.             }
  2436.             else {
  2437.                result = CHAN_MAX;
  2438.             }
  2439.          }
  2440.          else {
  2441.             /* Do four depth/R comparisons and compute a weighted result.
  2442.              * If this touches on somebody's I.P., I'll remove this code
  2443.              * upon request.
  2444.              */
  2445.             const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F;
  2446.             GLfloat luminance = CHAN_MAXF;
  2447.  
  2448.             switch (function) {
  2449.             case GL_LEQUAL:
  2450.                if (depth00 <= texcoords[i][2])  luminance -= d;
  2451.                if (depth01 <= texcoords[i][2])  luminance -= d;
  2452.                if (depth10 <= texcoords[i][2])  luminance -= d;
  2453.                if (depth11 <= texcoords[i][2])  luminance -= d;
  2454.                result = (GLchan) luminance;
  2455.                break;
  2456.             case GL_GEQUAL:
  2457.                if (depth00 >= texcoords[i][2])  luminance -= d;
  2458.                if (depth01 >= texcoords[i][2])  luminance -= d;
  2459.                if (depth10 >= texcoords[i][2])  luminance -= d;
  2460.                if (depth11 >= texcoords[i][2])  luminance -= d;
  2461.                result = (GLchan) luminance;
  2462.                break;
  2463.             case GL_LESS:
  2464.                if (depth00 < texcoords[i][2])  luminance -= d;
  2465.                if (depth01 < texcoords[i][2])  luminance -= d;
  2466.                if (depth10 < texcoords[i][2])  luminance -= d;
  2467.                if (depth11 < texcoords[i][2])  luminance -= d;
  2468.                result = (GLchan) luminance;
  2469.                break;
  2470.             case GL_GREATER:
  2471.                if (depth00 > texcoords[i][2])  luminance -= d;
  2472.                if (depth01 > texcoords[i][2])  luminance -= d;
  2473.                if (depth10 > texcoords[i][2])  luminance -= d;
  2474.                if (depth11 > texcoords[i][2])  luminance -= d;
  2475.                result = (GLchan) luminance;
  2476.                break;
  2477.             case GL_EQUAL:
  2478.                if (depth00 == texcoords[i][2])  luminance -= d;
  2479.                if (depth01 == texcoords[i][2])  luminance -= d;
  2480.                if (depth10 == texcoords[i][2])  luminance -= d;
  2481.                if (depth11 == texcoords[i][2])  luminance -= d;
  2482.                result = (GLchan) luminance;
  2483.                break;
  2484.             case GL_NOTEQUAL:
  2485.                if (depth00 != texcoords[i][2])  luminance -= d;
  2486.                if (depth01 != texcoords[i][2])  luminance -= d;
  2487.                if (depth10 != texcoords[i][2])  luminance -= d;
  2488.                if (depth11 != texcoords[i][2])  luminance -= d;
  2489.                result = (GLchan) luminance;
  2490.                break;
  2491.             case GL_ALWAYS:
  2492.                result = 0;
  2493.                break;
  2494.             case GL_NEVER:
  2495.                result = CHAN_MAX;
  2496.                break;
  2497.             case GL_NONE:
  2498.                /* ordinary bilinear filtering */
  2499.                {
  2500.                   const GLfloat a = FRAC(u + 1.0F);
  2501.                   const GLfloat b = FRAC(v + 1.0F);
  2502.                   const GLfloat w00 = (1.0F - a) * (1.0F - b);
  2503.                   const GLfloat w10 = (       a) * (1.0F - b);
  2504.                   const GLfloat w01 = (1.0F - a) * (       b);
  2505.                   const GLfloat w11 = (       a) * (       b);
  2506.                   const GLfloat depthSample = w00 * depth00 + w10 * depth10
  2507.                                             + w01 * depth01 + w11 * depth11;
  2508.                   CLAMPED_FLOAT_TO_CHAN(result, depthSample);
  2509.                }
  2510.                break;
  2511.             default:
  2512.                _mesa_problem(ctx, "Bad compare func in sample_depth_texture");
  2513.                return;
  2514.             }
  2515.          }
  2516.  
  2517.          switch (tObj->DepthMode) {
  2518.          case GL_LUMINANCE:
  2519.             texel[i][RCOMP] = result;
  2520.             texel[i][GCOMP] = result;
  2521.             texel[i][BCOMP] = result;
  2522.             texel[i][ACOMP] = CHAN_MAX;
  2523.             break;
  2524.          case GL_INTENSITY:
  2525.             texel[i][RCOMP] = result;
  2526.             texel[i][GCOMP] = result;
  2527.             texel[i][BCOMP] = result;
  2528.             texel[i][ACOMP] = result;
  2529.             break;
  2530.          case GL_ALPHA:
  2531.             texel[i][RCOMP] = 0;
  2532.             texel[i][GCOMP] = 0;
  2533.             texel[i][BCOMP] = 0;
  2534.             texel[i][ACOMP] = result;
  2535.             break;
  2536.          default:
  2537.             _mesa_problem(ctx, "Bad depth texture mode");
  2538.          }
  2539.       }  /* for */
  2540.    }  /* if filter */
  2541. }
  2542.  
  2543.  
  2544. #if 0
  2545. /*
  2546.  * Experimental depth texture sampling function.
  2547.  */
  2548. static void
  2549. sample_depth_texture2(const GLcontext *ctx,
  2550.                      const struct gl_texture_unit *texUnit,
  2551.                      GLuint n, GLfloat texcoords[][4],
  2552.                      GLchan texel[][4])
  2553. {
  2554.    const struct gl_texture_object *texObj = texUnit->_Current;
  2555.    const GLint baseLevel = texObj->BaseLevel;
  2556.    const struct gl_texture_image *texImage = texObj->Image[baseLevel];
  2557.    const GLuint width = texImage->Width;
  2558.    const GLuint height = texImage->Height;
  2559.    GLchan ambient;
  2560.    GLboolean lequal, gequal;
  2561.  
  2562.    if (texObj->Target != GL_TEXTURE_2D) {
  2563.       _mesa_problem(ctx, "only 2-D depth textures supported at this time");
  2564.       return;
  2565.    }
  2566.  
  2567.    if (texObj->MinFilter != texObj->MagFilter) {
  2568.       _mesa_problem(ctx, "mipmapped depth textures not supported at this time");
  2569.       return;
  2570.    }
  2571.  
  2572.    /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if
  2573.     * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object
  2574.     * isn't a depth texture.
  2575.     */
  2576.    if (texImage->Format != GL_DEPTH_COMPONENT) {
  2577.       _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture");
  2578.       return;
  2579.    }
  2580.  
  2581.    UNCLAMPED_FLOAT_TO_CHAN(ambient, tObj->ShadowAmbient);
  2582.  
  2583.    if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) {
  2584.       lequal = GL_TRUE;
  2585.       gequal = GL_FALSE;
  2586.    }
  2587.    else {
  2588.       lequal = GL_FALSE;
  2589.       gequal = GL_TRUE;
  2590.    }
  2591.  
  2592.    {
  2593.       GLuint i;
  2594.       for (i = 0; i < n; i++) {
  2595.          const GLint K = 3;
  2596.          GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count;
  2597.          GLfloat w;
  2598.          GLchan lum;
  2599.          COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, texcoords[i][0],
  2600.                     width, col);
  2601.          COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, texcoords[i][1],
  2602.                     height, row);
  2603.  
  2604.          imin = col - K;
  2605.          imax = col + K;
  2606.          jmin = row - K;
  2607.          jmax = row + K;
  2608.  
  2609.          if (imin < 0)  imin = 0;
  2610.          if (imax >= width)  imax = width - 1;
  2611.          if (jmin < 0)  jmin = 0;
  2612.          if (jmax >= height) jmax = height - 1;
  2613.  
  2614.          samples = (imax - imin + 1) * (jmax - jmin + 1);
  2615.          count = 0;
  2616.          for (jj = jmin; jj <= jmax; jj++) {
  2617.             for (ii = imin; ii <= imax; ii++) {
  2618.                GLfloat depthSample = *((const GLfloat *) texImage->Data
  2619.                                        + jj * width + ii);
  2620.                if ((depthSample <= r[i] && lequal) ||
  2621.                    (depthSample >= r[i] && gequal)) {
  2622.                   count++;
  2623.                }
  2624.             }
  2625.          }
  2626.  
  2627.          w = (GLfloat) count / (GLfloat) samples;
  2628.          w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient);
  2629.          lum = (GLint) w;
  2630.  
  2631.          texel[i][RCOMP] = lum;
  2632.          texel[i][GCOMP] = lum;
  2633.          texel[i][BCOMP] = lum;
  2634.          texel[i][ACOMP] = CHAN_MAX;
  2635.       }
  2636.    }
  2637. }
  2638. #endif
  2639.  
  2640.  
  2641. /**
  2642.  * We use this function when a texture object is in an "incomplete" state.
  2643.  */
  2644. static void
  2645. null_sample_func( GLcontext *ctx, GLuint texUnit,
  2646.           const struct gl_texture_object *tObj, GLuint n,
  2647.           GLfloat texcoords[][4], const GLfloat lambda[],
  2648.           GLchan rgba[][4])
  2649. {
  2650. }
  2651.  
  2652.  
  2653.  
  2654. /**
  2655.  * Setup the texture sampling function for this texture object.
  2656.  */
  2657. void
  2658. _swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit,
  2659.                     const struct gl_texture_object *t )
  2660. {
  2661.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  2662.  
  2663.    if (!t->Complete) {
  2664.       swrast->TextureSample[texUnit] = null_sample_func;
  2665.    }
  2666.    else {
  2667.       const GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter);
  2668.       const GLenum format = t->Image[t->BaseLevel]->Format;
  2669.  
  2670.       if (needLambda) {
  2671.          /* Compute min/mag filter threshold */
  2672.          if (t->MagFilter == GL_LINEAR
  2673.              && (t->MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
  2674.                  t->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
  2675.             swrast->_MinMagThresh[texUnit] = 0.5F;
  2676.          }
  2677.          else {
  2678.             swrast->_MinMagThresh[texUnit] = 0.0F;
  2679.          }
  2680.       }
  2681.  
  2682.       switch (t->Target) {
  2683.          case GL_TEXTURE_1D:
  2684.             if (format == GL_DEPTH_COMPONENT) {
  2685.                swrast->TextureSample[texUnit] = sample_depth_texture;
  2686.             }
  2687.             else if (needLambda) {
  2688.                swrast->TextureSample[texUnit] = sample_lambda_1d;
  2689.             }
  2690.             else if (t->MinFilter == GL_LINEAR) {
  2691.                swrast->TextureSample[texUnit] = sample_linear_1d;
  2692.             }
  2693.             else {
  2694.                ASSERT(t->MinFilter == GL_NEAREST);
  2695.                swrast->TextureSample[texUnit] = sample_nearest_1d;
  2696.             }
  2697.             break;
  2698.          case GL_TEXTURE_2D:
  2699.             if (format == GL_DEPTH_COMPONENT) {
  2700.                swrast->TextureSample[texUnit] = sample_depth_texture;
  2701.             }
  2702.             else if (needLambda) {
  2703.                swrast->TextureSample[texUnit] = sample_lambda_2d;
  2704.             }
  2705.             else if (t->MinFilter == GL_LINEAR) {
  2706.                swrast->TextureSample[texUnit] = sample_linear_2d;
  2707.             }
  2708.             else {
  2709.                GLint baseLevel = t->BaseLevel;
  2710.                ASSERT(t->MinFilter == GL_NEAREST);
  2711.                if (t->WrapS == GL_REPEAT &&
  2712.                    t->WrapT == GL_REPEAT &&
  2713.                    t->Image[baseLevel]->Border == 0 &&
  2714.                    t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGB) {
  2715.                   swrast->TextureSample[texUnit] = opt_sample_rgb_2d;
  2716.                }
  2717.                else if (t->WrapS == GL_REPEAT &&
  2718.                         t->WrapT == GL_REPEAT &&
  2719.                         t->Image[baseLevel]->Border == 0 &&
  2720.                         t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGBA) {
  2721.                   swrast->TextureSample[texUnit] = opt_sample_rgba_2d;
  2722.                }
  2723.                else
  2724.                   swrast->TextureSample[texUnit] = sample_nearest_2d;
  2725.             }
  2726.             break;
  2727.          case GL_TEXTURE_3D:
  2728.             if (needLambda) {
  2729.                swrast->TextureSample[texUnit] = sample_lambda_3d;
  2730.             }
  2731.             else if (t->MinFilter == GL_LINEAR) {
  2732.                swrast->TextureSample[texUnit] = sample_linear_3d;
  2733.             }
  2734.             else {
  2735.                ASSERT(t->MinFilter == GL_NEAREST);
  2736.                swrast->TextureSample[texUnit] = sample_nearest_3d;
  2737.             }
  2738.             break;
  2739.          case GL_TEXTURE_CUBE_MAP_ARB:
  2740.             if (needLambda) {
  2741.                swrast->TextureSample[texUnit] = sample_lambda_cube;
  2742.             }
  2743.             else if (t->MinFilter == GL_LINEAR) {
  2744.                swrast->TextureSample[texUnit] = sample_linear_cube;
  2745.             }
  2746.             else {
  2747.                ASSERT(t->MinFilter == GL_NEAREST);
  2748.                swrast->TextureSample[texUnit] = sample_nearest_cube;
  2749.             }
  2750.             break;
  2751.          case GL_TEXTURE_RECTANGLE_NV:
  2752.             if (needLambda) {
  2753.                swrast->TextureSample[texUnit] = sample_lambda_rect;
  2754.             }
  2755.             else if (t->MinFilter == GL_LINEAR) {
  2756.                swrast->TextureSample[texUnit] = sample_linear_rect;
  2757.             }
  2758.             else {
  2759.                ASSERT(t->MinFilter == GL_NEAREST);
  2760.                swrast->TextureSample[texUnit] = sample_nearest_rect;
  2761.             }
  2762.             break;
  2763.          default:
  2764.             _mesa_problem(ctx, "invalid target in _swrast_choose_texture_sample_func");
  2765.       }
  2766.    }
  2767. }
  2768.  
  2769.  
  2770. #define PROD(A,B)   ( (GLuint)(A) * ((GLuint)(B)+1) )
  2771. #define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
  2772.  
  2773.  
  2774. /**
  2775.  * Do texture application for GL_ARB/EXT_texture_env_combine.
  2776.  * Input:
  2777.  *     ctx - rendering context
  2778.  *     textureUnit - the texture unit to apply
  2779.  *     n - number of fragments to process (span width)
  2780.  *     primary_rgba - incoming fragment color array
  2781.  *     texelBuffer - pointer to texel colors for all texture units
  2782.  * Input/Output:
  2783.  *     rgba - incoming colors, which get modified here
  2784.  */
  2785. static INLINE void
  2786. texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
  2787.                  CONST GLchan (*primary_rgba)[4],
  2788.                  CONST GLchan *texelBuffer,
  2789.                  GLchan (*rgba)[4] )
  2790. {
  2791.    const struct gl_texture_unit *textureUnit = &(ctx->Texture.Unit[unit]);
  2792.    const GLchan (*argRGB [3])[4];
  2793.    const GLchan (*argA [3])[4];
  2794.    const GLuint RGBshift = textureUnit->CombineScaleShiftRGB;
  2795.    const GLuint Ashift   = textureUnit->CombineScaleShiftA;
  2796. #if CHAN_TYPE == GL_FLOAT
  2797.    const GLchan RGBmult = (GLfloat) (1 << RGBshift);
  2798.    const GLchan Amult = (GLfloat) (1 << Ashift);
  2799. #else
  2800.    const GLint half = (CHAN_MAX + 1) / 2;
  2801. #endif
  2802.    GLuint i, j;
  2803.  
  2804.    /* GLchan ccolor[3][4]; */
  2805.    DEFMNARRAY(GLchan, ccolor, 3, 3 * MAX_WIDTH, 4);  /* mac 32k limitation */
  2806.    CHECKARRAY(ccolor, return);  /* mac 32k limitation */
  2807.  
  2808.    ASSERT(ctx->Extensions.EXT_texture_env_combine ||
  2809.           ctx->Extensions.ARB_texture_env_combine);
  2810.    ASSERT(SWRAST_CONTEXT(ctx)->_AnyTextureCombine);
  2811.  
  2812.  
  2813.    /*
  2814.    printf("modeRGB 0x%x  modeA 0x%x  srcRGB1 0x%x  srcA1 0x%x  srcRGB2 0x%x  srcA2 0x%x\n",
  2815.           textureUnit->CombineModeRGB,
  2816.           textureUnit->CombineModeA,
  2817.           textureUnit->CombineSourceRGB[0],
  2818.           textureUnit->CombineSourceA[0],
  2819.           textureUnit->CombineSourceRGB[1],
  2820.           textureUnit->CombineSourceA[1]);
  2821.    */
  2822.  
  2823.    /*
  2824.     * Do operand setup for up to 3 operands.  Loop over the terms.
  2825.     */
  2826.    for (j = 0; j < 3; j++) {
  2827.       const GLenum srcA = textureUnit->CombineSourceA[j];
  2828.       const GLenum srcRGB = textureUnit->CombineSourceRGB[j];
  2829.  
  2830.       switch (srcA) {
  2831.          case GL_TEXTURE:
  2832.             argA[j] = (const GLchan (*)[4])
  2833.                (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
  2834.             break;
  2835.          case GL_PRIMARY_COLOR_EXT:
  2836.             argA[j] = primary_rgba;
  2837.             break;
  2838.          case GL_PREVIOUS_EXT:
  2839.             argA[j] = (const GLchan (*)[4]) rgba;
  2840.             break;
  2841.          case GL_CONSTANT_EXT:
  2842.             {
  2843.                GLchan alpha, (*c)[4] = ccolor[j];
  2844.                UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
  2845.                for (i = 0; i < n; i++)
  2846.                   c[i][ACOMP] = alpha;
  2847.                argA[j] = (const GLchan (*)[4]) ccolor[j];
  2848.             }
  2849.             break;
  2850.          default:
  2851.             /* ARB_texture_env_crossbar source */
  2852.             {
  2853.                const GLuint srcUnit = srcA - GL_TEXTURE0_ARB;
  2854.                ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
  2855.                if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
  2856.                   return;
  2857.                argA[j] = (const GLchan (*)[4])
  2858.                   (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
  2859.             }
  2860.       }
  2861.  
  2862.       switch (srcRGB) {
  2863.          case GL_TEXTURE:
  2864.             argRGB[j] = (const GLchan (*)[4])
  2865.                (texelBuffer + unit * (n * 4 * sizeof(GLchan)));
  2866.             break;
  2867.          case GL_PRIMARY_COLOR_EXT:
  2868.             argRGB[j] = primary_rgba;
  2869.             break;
  2870.          case GL_PREVIOUS_EXT:
  2871.             argRGB[j] = (const GLchan (*)[4]) rgba;
  2872.             break;
  2873.          case GL_CONSTANT_EXT:
  2874.             {
  2875.                GLchan (*c)[4] = ccolor[j];
  2876.                GLchan red, green, blue, alpha;
  2877.                UNCLAMPED_FLOAT_TO_CHAN(red,   textureUnit->EnvColor[0]);
  2878.                UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
  2879.                UNCLAMPED_FLOAT_TO_CHAN(blue,  textureUnit->EnvColor[2]);
  2880.                UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
  2881.                for (i = 0; i < n; i++) {
  2882.                   c[i][RCOMP] = red;
  2883.                   c[i][GCOMP] = green;
  2884.                   c[i][BCOMP] = blue;
  2885.                   c[i][ACOMP] = alpha;
  2886.                }
  2887.                argRGB[j] = (const GLchan (*)[4]) ccolor[j];
  2888.             }
  2889.             break;
  2890.          default:
  2891.             /* ARB_texture_env_crossbar source */
  2892.             {
  2893.                const GLuint srcUnit = srcRGB - GL_TEXTURE0_ARB;
  2894.                ASSERT(srcUnit < ctx->Const.MaxTextureUnits);
  2895.                if (!ctx->Texture.Unit[srcUnit]._ReallyEnabled)
  2896.                   return;
  2897.                argRGB[j] = (const GLchan (*)[4])
  2898.                   (texelBuffer + srcUnit * (n * 4 * sizeof(GLchan)));
  2899.             }
  2900.       }
  2901.  
  2902.       if (textureUnit->CombineOperandRGB[j] != GL_SRC_COLOR) {
  2903.          const GLchan (*src)[4] = argRGB[j];
  2904.          GLchan (*dst)[4] = ccolor[j];
  2905.  
  2906.          /* point to new arg[j] storage */
  2907.          argRGB[j] = (const GLchan (*)[4]) ccolor[j];
  2908.  
  2909.          if (textureUnit->CombineOperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
  2910.             for (i = 0; i < n; i++) {
  2911.                dst[i][RCOMP] = CHAN_MAX - src[i][RCOMP];
  2912.                dst[i][GCOMP] = CHAN_MAX - src[i][GCOMP];
  2913.                dst[i][BCOMP] = CHAN_MAX - src[i][BCOMP];
  2914.             }
  2915.          }
  2916.          else if (textureUnit->CombineOperandRGB[j] == GL_SRC_ALPHA) {
  2917.             for (i = 0; i < n; i++) {
  2918.                dst[i][RCOMP] = src[i][ACOMP];
  2919.                dst[i][GCOMP] = src[i][ACOMP];
  2920.                dst[i][BCOMP] = src[i][ACOMP];
  2921.             }
  2922.          }
  2923.          else {
  2924.             ASSERT(textureUnit->CombineOperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
  2925.             for (i = 0; i < n; i++) {
  2926.                dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
  2927.                dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
  2928.                dst[i][BCOMP] = CHAN_MAX - src[i][ACOMP];
  2929.             }
  2930.          }
  2931.       }
  2932.  
  2933.       if (textureUnit->CombineOperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
  2934.          const GLchan (*src)[4] = argA[j];
  2935.          GLchan (*dst)[4] = ccolor[j];
  2936.          argA[j] = (const GLchan (*)[4]) ccolor[j];
  2937.          for (i = 0; i < n; i++) {
  2938.             dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
  2939.          }
  2940.       }
  2941.  
  2942.       if (textureUnit->CombineModeRGB == GL_REPLACE &&
  2943.           textureUnit->CombineModeA == GL_REPLACE) {
  2944.          break;      /*  done, we need only arg0  */
  2945.       }
  2946.  
  2947.       if (j == 1 &&
  2948.           textureUnit->CombineModeRGB != GL_INTERPOLATE_EXT &&
  2949.           textureUnit->CombineModeA != GL_INTERPOLATE_EXT) {
  2950.          break;      /*  arg0 and arg1 are done. we don't need arg2. */
  2951.       }
  2952.    }
  2953.  
  2954.    /*
  2955.     * Do the texture combine.
  2956.     */
  2957.    switch (textureUnit->CombineModeRGB) {
  2958.       case GL_REPLACE:
  2959.          {
  2960.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
  2961.             if (RGBshift) {
  2962.                for (i = 0; i < n; i++) {
  2963. #if CHAN_TYPE == GL_FLOAT
  2964.                   rgba[i][RCOMP] = arg0[i][RCOMP] * RGBmult;
  2965.                   rgba[i][GCOMP] = arg0[i][GCOMP] * RGBmult;
  2966.                   rgba[i][BCOMP] = arg0[i][BCOMP] * RGBmult;
  2967. #else
  2968.                   GLuint r = (GLuint) arg0[i][RCOMP] << RGBshift;
  2969.                   GLuint g = (GLuint) arg0[i][GCOMP] << RGBshift;
  2970.                   GLuint b = (GLuint) arg0[i][BCOMP] << RGBshift;
  2971.                   rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
  2972.                   rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
  2973.                   rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
  2974. #endif
  2975.                }
  2976.             }
  2977.             else {
  2978.                for (i = 0; i < n; i++) {
  2979.                   rgba[i][RCOMP] = arg0[i][RCOMP];
  2980.                   rgba[i][GCOMP] = arg0[i][GCOMP];
  2981.                   rgba[i][BCOMP] = arg0[i][BCOMP];
  2982.                }
  2983.             }
  2984.          }
  2985.          break;
  2986.       case GL_MODULATE:
  2987.          {
  2988.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
  2989.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
  2990. #if CHAN_TYPE != GL_FLOAT
  2991.             const GLint shift = CHAN_BITS - RGBshift;
  2992. #endif
  2993.             for (i = 0; i < n; i++) {
  2994. #if CHAN_TYPE == GL_FLOAT
  2995.                rgba[i][RCOMP] = arg0[i][RCOMP] * arg1[i][RCOMP] * RGBmult;
  2996.                rgba[i][GCOMP] = arg0[i][GCOMP] * arg1[i][GCOMP] * RGBmult;
  2997.                rgba[i][BCOMP] = arg0[i][BCOMP] * arg1[i][BCOMP] * RGBmult;
  2998. #else
  2999.                GLuint r = PROD(arg0[i][RCOMP], arg1[i][RCOMP]) >> shift;
  3000.                GLuint g = PROD(arg0[i][GCOMP], arg1[i][GCOMP]) >> shift;
  3001.                GLuint b = PROD(arg0[i][BCOMP], arg1[i][BCOMP]) >> shift;
  3002.                rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
  3003.                rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
  3004.                rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
  3005. #endif
  3006.             }
  3007.          }
  3008.          break;
  3009.       case GL_ADD:
  3010.          {
  3011.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
  3012.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
  3013.             for (i = 0; i < n; i++) {
  3014. #if CHAN_TYPE == GL_FLOAT
  3015.                rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP]) * RGBmult;
  3016.                rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP]) * RGBmult;
  3017.                rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP]) * RGBmult;
  3018. #else
  3019.                GLint r = ((GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP]) << RGBshift;
  3020.                GLint g = ((GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP]) << RGBshift;
  3021.                GLint b = ((GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP]) << RGBshift;
  3022.                rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
  3023.                rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
  3024.                rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
  3025. #endif
  3026.             }
  3027.          }
  3028.          break;
  3029.       case GL_ADD_SIGNED_EXT:
  3030.          {
  3031.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
  3032.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
  3033.             for (i = 0; i < n; i++) {
  3034. #if CHAN_TYPE == GL_FLOAT
  3035.                rgba[i][RCOMP] = (arg0[i][RCOMP] + arg1[i][RCOMP] - 0.5) * RGBmult;
  3036.                rgba[i][GCOMP] = (arg0[i][GCOMP] + arg1[i][GCOMP] - 0.5) * RGBmult;
  3037.                rgba[i][BCOMP] = (arg0[i][BCOMP] + arg1[i][BCOMP] - 0.5) * RGBmult;
  3038. #else
  3039.                GLint r = (GLint) arg0[i][RCOMP] + (GLint) arg1[i][RCOMP] -half;
  3040.                GLint g = (GLint) arg0[i][GCOMP] + (GLint) arg1[i][GCOMP] -half;
  3041.                GLint b = (GLint) arg0[i][BCOMP] + (GLint) arg1[i][BCOMP] -half;
  3042.                r = (r < 0) ? 0 : r << RGBshift;
  3043.                g = (g < 0) ? 0 : g << RGBshift;
  3044.                b = (b < 0) ? 0 : b << RGBshift;
  3045.                rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
  3046.                rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
  3047.                rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
  3048. #endif
  3049.             }
  3050.          }
  3051.          break;
  3052.       case GL_INTERPOLATE_EXT:
  3053.          {
  3054.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
  3055.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
  3056.             const GLchan (*arg2)[4] = (const GLchan (*)[4]) argRGB[2];
  3057. #if CHAN_TYPE != GL_FLOAT
  3058.             const GLint shift = CHAN_BITS - RGBshift;
  3059. #endif
  3060.             for (i = 0; i < n; i++) {
  3061. #if CHAN_TYPE == GL_FLOAT
  3062.                rgba[i][RCOMP] = (arg0[i][RCOMP] * arg2[i][RCOMP] +
  3063.                       arg1[i][RCOMP] * (CHAN_MAXF - arg2[i][RCOMP])) * RGBmult;
  3064.                rgba[i][GCOMP] = (arg0[i][GCOMP] * arg2[i][GCOMP] +
  3065.                       arg1[i][GCOMP] * (CHAN_MAXF - arg2[i][GCOMP])) * RGBmult;
  3066.                rgba[i][BCOMP] = (arg0[i][BCOMP] * arg2[i][BCOMP] +
  3067.                       arg1[i][BCOMP] * (CHAN_MAXF - arg2[i][BCOMP])) * RGBmult;
  3068. #else
  3069.                GLuint r = (PROD(arg0[i][RCOMP], arg2[i][RCOMP])
  3070.                            + PROD(arg1[i][RCOMP], CHAN_MAX - arg2[i][RCOMP]))
  3071.                               >> shift;
  3072.                GLuint g = (PROD(arg0[i][GCOMP], arg2[i][GCOMP])
  3073.                            + PROD(arg1[i][GCOMP], CHAN_MAX - arg2[i][GCOMP]))
  3074.                               >> shift;
  3075.                GLuint b = (PROD(arg0[i][BCOMP], arg2[i][BCOMP])
  3076.                            + PROD(arg1[i][BCOMP], CHAN_MAX - arg2[i][BCOMP]))
  3077.                               >> shift;
  3078.                rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
  3079.                rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
  3080.                rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
  3081. #endif
  3082.             }
  3083.          }
  3084.          break;
  3085.       case GL_SUBTRACT_ARB:
  3086.          {
  3087.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
  3088.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
  3089.             for (i = 0; i < n; i++) {
  3090. #if CHAN_TYPE == GL_FLOAT
  3091.                rgba[i][RCOMP] = (arg0[i][RCOMP] - arg1[i][RCOMP]) * RGBmult;
  3092.                rgba[i][GCOMP] = (arg0[i][GCOMP] - arg1[i][GCOMP]) * RGBmult;
  3093.                rgba[i][BCOMP] = (arg0[i][BCOMP] - arg1[i][BCOMP]) * RGBmult;
  3094. #else
  3095.                GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift;
  3096.                GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift;
  3097.                GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift;
  3098.                rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
  3099.                rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
  3100.                rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
  3101. #endif
  3102.             }
  3103.          }
  3104.          break;
  3105.       case GL_DOT3_RGB_EXT:
  3106.       case GL_DOT3_RGBA_EXT:
  3107.          {
  3108.             /* Do not scale the result by 1 2 or 4 */
  3109.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
  3110.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
  3111.             for (i = 0; i < n; i++) {
  3112. #if CHAN_TYPE == GL_FLOAT
  3113.                GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
  3114.                              (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
  3115.                              (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
  3116.                             * 4.0F;
  3117.                dot = CLAMP(dot, 0.0F, CHAN_MAXF);
  3118. #else
  3119.                GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
  3120.                    (GLint)arg1[i][RCOMP] - half) +
  3121.                 S_PROD((GLint)arg0[i][GCOMP] - half,
  3122.                    (GLint)arg1[i][GCOMP] - half) +
  3123.                 S_PROD((GLint)arg0[i][BCOMP] - half,
  3124.                    (GLint)arg1[i][BCOMP] - half)) >> 6;
  3125.                dot = CLAMP(dot, 0, CHAN_MAX);
  3126. #endif
  3127.                rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
  3128.             }
  3129.          }
  3130.          break;
  3131.       case GL_DOT3_RGB_ARB:
  3132.       case GL_DOT3_RGBA_ARB:
  3133.          {
  3134.             /* DO scale the result by 1 2 or 4 */
  3135.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
  3136.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
  3137.             for (i = 0; i < n; i++) {
  3138. #if CHAN_TYPE == GL_FLOAT
  3139.                GLchan dot = ((arg0[i][RCOMP]-0.5F) * (arg1[i][RCOMP]-0.5F) +
  3140.                              (arg0[i][GCOMP]-0.5F) * (arg1[i][GCOMP]-0.5F) +
  3141.                              (arg0[i][BCOMP]-0.5F) * (arg1[i][BCOMP]-0.5F))
  3142.                             * 4.0F * RGBmult;
  3143.                dot = CLAMP(dot, 0.0, CHAN_MAXF);
  3144. #else
  3145.                GLint dot = (S_PROD((GLint)arg0[i][RCOMP] - half,
  3146.                    (GLint)arg1[i][RCOMP] - half) +
  3147.                 S_PROD((GLint)arg0[i][GCOMP] - half,
  3148.                    (GLint)arg1[i][GCOMP] - half) +
  3149.                 S_PROD((GLint)arg0[i][BCOMP] - half,
  3150.                    (GLint)arg1[i][BCOMP] - half)) >> 6;
  3151.                dot <<= RGBshift;
  3152.                dot = CLAMP(dot, 0, CHAN_MAX);
  3153. #endif
  3154.                rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
  3155.             }
  3156.          }
  3157.          break;
  3158.       default:
  3159.          _mesa_problem(ctx, "invalid combine mode");
  3160.    }
  3161.  
  3162.    switch (textureUnit->CombineModeA) {
  3163.       case GL_REPLACE:
  3164.          {
  3165.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
  3166.             if (Ashift) {
  3167.                for (i = 0; i < n; i++) {
  3168. #if CHAN_TYPE == GL_FLOAT
  3169.                   GLchan a = arg0[i][ACOMP] * Amult;
  3170. #else
  3171.                   GLuint a = (GLuint) arg0[i][ACOMP] << Ashift;
  3172. #endif
  3173.                   rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
  3174.                }
  3175.             }
  3176.             else {
  3177.                for (i = 0; i < n; i++) {
  3178.                   rgba[i][ACOMP] = arg0[i][ACOMP];
  3179.                }
  3180.             }
  3181.          }
  3182.          break;
  3183.       case GL_MODULATE:
  3184.          {
  3185.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
  3186.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
  3187. #if CHAN_TYPE != GL_FLOAT
  3188.             const GLint shift = CHAN_BITS - Ashift;
  3189. #endif
  3190.             for (i = 0; i < n; i++) {
  3191. #if CHAN_TYPE == GL_FLOAT
  3192.                rgba[i][ACOMP] = arg0[i][ACOMP] * arg1[i][ACOMP] * Amult;
  3193. #else
  3194.                GLuint a = (PROD(arg0[i][ACOMP], arg1[i][ACOMP]) >> shift);
  3195.                rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
  3196. #endif
  3197.             }
  3198.          }
  3199.          break;
  3200.       case GL_ADD:
  3201.          {
  3202.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
  3203.             const GLchan  (*arg1)[4] = (const GLchan (*)[4]) argA[1];
  3204.             for (i = 0; i < n; i++) {
  3205. #if CHAN_TYPE == GL_FLOAT
  3206.                rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP]) * Amult;
  3207. #else
  3208.                GLint a = ((GLint) arg0[i][ACOMP] + arg1[i][ACOMP]) << Ashift;
  3209.                rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
  3210. #endif
  3211.             }
  3212.          }
  3213.          break;
  3214.       case GL_ADD_SIGNED_EXT:
  3215.          {
  3216.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
  3217.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
  3218.             for (i = 0; i < n; i++) {
  3219. #if CHAN_TYPE == GL_FLOAT
  3220.                rgba[i][ACOMP] = (arg0[i][ACOMP] + arg1[i][ACOMP] - 0.5F) * Amult;
  3221. #else
  3222.                GLint a = (GLint) arg0[i][ACOMP] + (GLint) arg1[i][ACOMP] -half;
  3223.                a = (a < 0) ? 0 : a << Ashift;
  3224.                rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
  3225. #endif
  3226.             }
  3227.          }
  3228.          break;
  3229.       case GL_INTERPOLATE_EXT:
  3230.          {
  3231.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
  3232.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
  3233.             const GLchan (*arg2)[4] = (const GLchan (*)[4]) argA[2];
  3234. #if CHAN_TYPE != GL_FLOAT
  3235.             const GLint shift = CHAN_BITS - Ashift;
  3236. #endif
  3237.             for (i=0; i<n; i++) {
  3238. #if CHAN_TYPE == GL_FLOAT
  3239.                rgba[i][ACOMP] = (arg0[i][ACOMP] * arg2[i][ACOMP] +
  3240.                                  arg1[i][ACOMP] * (CHAN_MAXF - arg2[i][ACOMP]))
  3241.                                 * Amult;
  3242. #else
  3243.                GLuint a = (PROD(arg0[i][ACOMP], arg2[i][ACOMP])
  3244.                            + PROD(arg1[i][ACOMP], CHAN_MAX - arg2[i][ACOMP]))
  3245.                               >> shift;
  3246.                rgba[i][ACOMP] = (GLchan) MIN2(a, CHAN_MAX);
  3247. #endif
  3248.             }
  3249.          }
  3250.          break;
  3251.       case GL_SUBTRACT_ARB:
  3252.          {
  3253.             const GLchan (*arg0)[4] = (const GLchan (*)[4]) argA[0];
  3254.             const GLchan (*arg1)[4] = (const GLchan (*)[4]) argA[1];
  3255.             for (i = 0; i < n; i++) {
  3256. #if CHAN_TYPE == GL_FLOAT
  3257.                rgba[i][ACOMP] = (arg0[i][ACOMP] - arg1[i][ACOMP]) * Amult;
  3258. #else
  3259.                GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << Ashift;
  3260.                rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
  3261. #endif
  3262.             }
  3263.          }
  3264.          break;
  3265.  
  3266.       default:
  3267.          _mesa_problem(ctx, "invalid combine mode");
  3268.    }
  3269.  
  3270.    /* Fix the alpha component for GL_DOT3_RGBA_EXT/ARB combining.
  3271.     * This is kind of a kludge.  It would have been better if the spec
  3272.     * were written such that the GL_COMBINE_ALPHA value could be set to
  3273.     * GL_DOT3.
  3274.     */
  3275.    if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT ||
  3276.        textureUnit->CombineModeRGB == GL_DOT3_RGBA_ARB) {
  3277.       for (i = 0; i < n; i++) {
  3278.      rgba[i][ACOMP] = rgba[i][RCOMP];
  3279.       }
  3280.    }
  3281.    UNDEFARRAY(ccolor);  /* mac 32k limitation */
  3282. }
  3283. #undef PROD
  3284.  
  3285.  
  3286. /**
  3287.  * Implement NVIDIA's GL_NV_texture_env_combine4 extension when
  3288.  * texUnit->EnvMode == GL_COMBINE4_NV.
  3289.  */
  3290. static INLINE void
  3291. texture_combine4( const GLcontext *ctx, GLuint unit, GLuint n,
  3292.                   CONST GLchan (*primary_rgba)[4],
  3293.                   CONST GLchan *texelBuffer,
  3294.                   GLchan (*rgba)[4] )
  3295. {
  3296. }
  3297.  
  3298.  
  3299.  
  3300. /**
  3301.  * Apply a conventional OpenGL texture env mode (REPLACE, ADD, BLEND,
  3302.  * MODULATE, or DECAL) to an array of fragments.
  3303.  * Input:  textureUnit - pointer to texture unit to apply
  3304.  *         format - base internal texture format
  3305.  *         n - number of fragments
  3306.  *         primary_rgba - primary colors (may alias rgba for single texture)
  3307.  *         texels - array of texel colors
  3308.  * InOut:  rgba - incoming fragment colors modified by texel colors
  3309.  *                according to the texture environment mode.
  3310.  */
  3311. static void
  3312. texture_apply( const GLcontext *ctx,
  3313.                const struct gl_texture_unit *texUnit,
  3314.                GLuint n,
  3315.                CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
  3316.                GLchan rgba[][4] )
  3317. {
  3318.    GLint baseLevel;
  3319.    GLuint i;
  3320.    GLint Rc, Gc, Bc, Ac;
  3321.    GLenum format;
  3322.  
  3323.    ASSERT(texUnit);
  3324.    ASSERT(texUnit->_Current);
  3325.  
  3326.    baseLevel = texUnit->_Current->BaseLevel;
  3327.    ASSERT(texUnit->_Current->Image[baseLevel]);
  3328.  
  3329.    format = texUnit->_Current->Image[baseLevel]->Format;
  3330.  
  3331.    if (format == GL_COLOR_INDEX || format == GL_DEPTH_COMPONENT
  3332.        || format == GL_YCBCR_MESA) {
  3333.       format = GL_RGBA;  /* a bit of a hack */
  3334.    }
  3335.  
  3336.    switch (texUnit->EnvMode) {
  3337.       case GL_REPLACE:
  3338.      switch (format) {
  3339.         case GL_ALPHA:
  3340.            for (i=0;i<n;i++) {
  3341.           /* Cv = Cf */
  3342.                   /* Av = At */
  3343.                   rgba[i][ACOMP] = texel[i][ACOMP];
  3344.            }
  3345.            break;
  3346.         case GL_LUMINANCE:
  3347.            for (i=0;i<n;i++) {
  3348.           /* Cv = Lt */
  3349.                   GLchan Lt = texel[i][RCOMP];
  3350.                   rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
  3351.                   /* Av = Af */
  3352.            }
  3353.            break;
  3354.         case GL_LUMINANCE_ALPHA:
  3355.            for (i=0;i<n;i++) {
  3356.                   GLchan Lt = texel[i][RCOMP];
  3357.           /* Cv = Lt */
  3358.           rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = Lt;
  3359.           /* Av = At */
  3360.           rgba[i][ACOMP] = texel[i][ACOMP];
  3361.            }
  3362.            break;
  3363.         case GL_INTENSITY:
  3364.            for (i=0;i<n;i++) {
  3365.           /* Cv = It */
  3366.                   GLchan It = texel[i][RCOMP];
  3367.                   rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = It;
  3368.                   /* Av = It */
  3369.                   rgba[i][ACOMP] = It;
  3370.            }
  3371.            break;
  3372.         case GL_RGB:
  3373.            for (i=0;i<n;i++) {
  3374.           /* Cv = Ct */
  3375.           rgba[i][RCOMP] = texel[i][RCOMP];
  3376.           rgba[i][GCOMP] = texel[i][GCOMP];
  3377.           rgba[i][BCOMP] = texel[i][BCOMP];
  3378.           /* Av = Af */
  3379.            }
  3380.            break;
  3381.         case GL_RGBA:
  3382.            for (i=0;i<n;i++) {
  3383.           /* Cv = Ct */
  3384.           rgba[i][RCOMP] = texel[i][RCOMP];
  3385.           rgba[i][GCOMP] = texel[i][GCOMP];
  3386.           rgba[i][BCOMP] = texel[i][BCOMP];
  3387.           /* Av = At */
  3388.           rgba[i][ACOMP] = texel[i][ACOMP];
  3389.            }
  3390.            break;
  3391.             default:
  3392.                _mesa_problem(ctx, "Bad format (GL_REPLACE) in texture_apply");
  3393.                return;
  3394.      }
  3395.      break;
  3396.  
  3397.       case GL_MODULATE:
  3398.          switch (format) {
  3399.         case GL_ALPHA:
  3400.            for (i=0;i<n;i++) {
  3401.           /* Cv = Cf */
  3402.           /* Av = AfAt */
  3403.           rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
  3404.            }
  3405.            break;
  3406.         case GL_LUMINANCE:
  3407.            for (i=0;i<n;i++) {
  3408.           /* Cv = LtCf */
  3409.                   GLchan Lt = texel[i][RCOMP];
  3410.           rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
  3411.           rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
  3412.           rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
  3413.           /* Av = Af */
  3414.            }
  3415.            break;
  3416.         case GL_LUMINANCE_ALPHA:
  3417.            for (i=0;i<n;i++) {
  3418.           /* Cv = CfLt */
  3419.                   GLchan Lt = texel[i][RCOMP];
  3420.           rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], Lt );
  3421.           rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], Lt );
  3422.           rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], Lt );
  3423.           /* Av = AfAt */
  3424.           rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
  3425.            }
  3426.            break;
  3427.         case GL_INTENSITY:
  3428.            for (i=0;i<n;i++) {
  3429.           /* Cv = CfIt */
  3430.                   GLchan It = texel[i][RCOMP];
  3431.           rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It );
  3432.           rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It );
  3433.           rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It );
  3434.           /* Av = AfIt */
  3435.           rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It );
  3436.            }
  3437.            break;
  3438.         case GL_RGB:
  3439.            for (i=0;i<n;i++) {
  3440.           /* Cv = CfCt */
  3441.           rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
  3442.           rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
  3443.           rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
  3444.           /* Av = Af */
  3445.            }
  3446.            break;
  3447.         case GL_RGBA:
  3448.            for (i=0;i<n;i++) {
  3449.           /* Cv = CfCt */
  3450.           rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], texel[i][RCOMP] );
  3451.           rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], texel[i][GCOMP] );
  3452.           rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], texel[i][BCOMP] );
  3453.           /* Av = AfAt */
  3454.           rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], texel[i][ACOMP] );
  3455.            }
  3456.            break;
  3457.             default:
  3458.                _mesa_problem(ctx, "Bad format (GL_MODULATE) in texture_apply");
  3459.                return;
  3460.      }
  3461.      break;
  3462.  
  3463.       case GL_DECAL:
  3464.          switch (format) {
  3465.             case GL_ALPHA:
  3466.             case GL_LUMINANCE:
  3467.             case GL_LUMINANCE_ALPHA:
  3468.             case GL_INTENSITY:
  3469.                /* undefined */
  3470.                break;
  3471.         case GL_RGB:
  3472.            for (i=0;i<n;i++) {
  3473.           /* Cv = Ct */
  3474.           rgba[i][RCOMP] = texel[i][RCOMP];
  3475.           rgba[i][GCOMP] = texel[i][GCOMP];
  3476.           rgba[i][BCOMP] = texel[i][BCOMP];
  3477.           /* Av = Af */
  3478.            }
  3479.            break;
  3480.         case GL_RGBA:
  3481.            for (i=0;i<n;i++) {
  3482.           /* Cv = Cf(1-At) + CtAt */
  3483.           GLint t = texel[i][ACOMP], s = CHAN_MAX - t;
  3484.           rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(texel[i][RCOMP],t);
  3485.           rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(texel[i][GCOMP],t);
  3486.           rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(texel[i][BCOMP],t);
  3487.           /* Av = Af */
  3488.            }
  3489.            break;
  3490.             default:
  3491.                _mesa_problem(ctx, "Bad format (GL_DECAL) in texture_apply");
  3492.                return;
  3493.      }
  3494.      break;
  3495.  
  3496.       case GL_BLEND:
  3497.          Rc = (GLint) (texUnit->EnvColor[0] * CHAN_MAXF);
  3498.          Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF);
  3499.          Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF);
  3500.          Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF);
  3501.      switch (format) {
  3502.         case GL_ALPHA:
  3503.            for (i=0;i<n;i++) {
  3504.           /* Cv = Cf */
  3505.           /* Av = AfAt */
  3506.                   rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
  3507.            }
  3508.            break;
  3509.             case GL_LUMINANCE:
  3510.            for (i=0;i<n;i++) {
  3511.           /* Cv = Cf(1-Lt) + CcLt */
  3512.           GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
  3513.           rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
  3514.           rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
  3515.           rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
  3516.           /* Av = Af */
  3517.            }
  3518.            break;
  3519.         case GL_LUMINANCE_ALPHA:
  3520.            for (i=0;i<n;i++) {
  3521.           /* Cv = Cf(1-Lt) + CcLt */
  3522.           GLchan Lt = texel[i][RCOMP], s = CHAN_MAX - Lt;
  3523.           rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, Lt);
  3524.           rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, Lt);
  3525.           rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, Lt);
  3526.           /* Av = AfAt */
  3527.           rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
  3528.            }
  3529.            break;
  3530.             case GL_INTENSITY:
  3531.            for (i=0;i<n;i++) {
  3532.           /* Cv = Cf(1-It) + CcLt */
  3533.           GLchan It = texel[i][RCOMP], s = CHAN_MAX - It;
  3534.           rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], s) + CHAN_PRODUCT(Rc, It);
  3535.           rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], s) + CHAN_PRODUCT(Gc, It);
  3536.           rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], s) + CHAN_PRODUCT(Bc, It);
  3537.                   /* Av = Af(1-It) + Ac*It */
  3538.                   rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], s) + CHAN_PRODUCT(Ac, It);
  3539.                }
  3540.                break;
  3541.         case GL_RGB:
  3542.            for (i=0;i<n;i++) {
  3543.           /* Cv = Cf(1-Ct) + CcCt */
  3544.           rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
  3545.           rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
  3546.           rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
  3547.           /* Av = Af */
  3548.            }
  3549.            break;
  3550.         case GL_RGBA:
  3551.            for (i=0;i<n;i++) {
  3552.           /* Cv = Cf(1-Ct) + CcCt */
  3553.           rgba[i][RCOMP] = CHAN_PRODUCT(rgba[i][RCOMP], (CHAN_MAX-texel[i][RCOMP])) + CHAN_PRODUCT(Rc,texel[i][RCOMP]);
  3554.           rgba[i][GCOMP] = CHAN_PRODUCT(rgba[i][GCOMP], (CHAN_MAX-texel[i][GCOMP])) + CHAN_PRODUCT(Gc,texel[i][GCOMP]);
  3555.           rgba[i][BCOMP] = CHAN_PRODUCT(rgba[i][BCOMP], (CHAN_MAX-texel[i][BCOMP])) + CHAN_PRODUCT(Bc,texel[i][BCOMP]);
  3556.           /* Av = AfAt */
  3557.           rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP],texel[i][ACOMP]);
  3558.            }
  3559.            break;
  3560.             default:
  3561.                _mesa_problem(ctx, "Bad format (GL_BLEND) in texture_apply");
  3562.                return;
  3563.      }
  3564.      break;
  3565.  
  3566.      /* XXX don't clamp results if GLchan is float??? */
  3567.  
  3568.       case GL_ADD:  /* GL_EXT_texture_add_env */
  3569.          switch (format) {
  3570.             case GL_ALPHA:
  3571.                for (i=0;i<n;i++) {
  3572.                   /* Rv = Rf */
  3573.                   /* Gv = Gf */
  3574.                   /* Bv = Bf */
  3575.                   rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
  3576.                }
  3577.                break;
  3578.             case GL_LUMINANCE:
  3579.                for (i=0;i<n;i++) {
  3580.                   GLuint Lt = texel[i][RCOMP];
  3581.                   GLuint r = rgba[i][RCOMP] + Lt;
  3582.                   GLuint g = rgba[i][GCOMP] + Lt;
  3583.                   GLuint b = rgba[i][BCOMP] + Lt;
  3584.                   rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
  3585.                   rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
  3586.                   rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
  3587.                   /* Av = Af */
  3588.                }
  3589.                break;
  3590.             case GL_LUMINANCE_ALPHA:
  3591.                for (i=0;i<n;i++) {
  3592.                   GLuint Lt = texel[i][RCOMP];
  3593.                   GLuint r = rgba[i][RCOMP] + Lt;
  3594.                   GLuint g = rgba[i][GCOMP] + Lt;
  3595.                   GLuint b = rgba[i][BCOMP] + Lt;
  3596.                   rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
  3597.                   rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
  3598.                   rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
  3599.                   rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
  3600.                }
  3601.                break;
  3602.             case GL_INTENSITY:
  3603.                for (i=0;i<n;i++) {
  3604.                   GLchan It = texel[i][RCOMP];
  3605.                   GLuint r = rgba[i][RCOMP] + It;
  3606.                   GLuint g = rgba[i][GCOMP] + It;
  3607.                   GLuint b = rgba[i][BCOMP] + It;
  3608.                   GLuint a = rgba[i][ACOMP] + It;
  3609.                   rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
  3610.                   rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
  3611.                   rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
  3612.                   rgba[i][ACOMP] = MIN2(a, CHAN_MAX);
  3613.                }
  3614.                break;
  3615.         case GL_RGB:
  3616.            for (i=0;i<n;i++) {
  3617.                   GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
  3618.                   GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
  3619.                   GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
  3620.           rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
  3621.           rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
  3622.           rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
  3623.           /* Av = Af */
  3624.            }
  3625.            break;
  3626.         case GL_RGBA:
  3627.            for (i=0;i<n;i++) {
  3628.                   GLuint r = rgba[i][RCOMP] + texel[i][RCOMP];
  3629.                   GLuint g = rgba[i][GCOMP] + texel[i][GCOMP];
  3630.                   GLuint b = rgba[i][BCOMP] + texel[i][BCOMP];
  3631.           rgba[i][RCOMP] = MIN2(r, CHAN_MAX);
  3632.           rgba[i][GCOMP] = MIN2(g, CHAN_MAX);
  3633.           rgba[i][BCOMP] = MIN2(b, CHAN_MAX);
  3634.                   rgba[i][ACOMP] = CHAN_PRODUCT(rgba[i][ACOMP], texel[i][ACOMP]);
  3635.                }
  3636.                break;
  3637.             default:
  3638.                _mesa_problem(ctx, "Bad format (GL_ADD) in texture_apply");
  3639.                return;
  3640.      }
  3641.      break;
  3642.  
  3643.       default:
  3644.          _mesa_problem(ctx, "Bad env mode in texture_apply");
  3645.          return;
  3646.    }
  3647. }
  3648.  
  3649.  
  3650.  
  3651. /**
  3652.  * Apply texture mapping to a span of fragments.
  3653.  */
  3654. void
  3655. _swrast_texture_span( GLcontext *ctx, struct sw_span *span )
  3656. {
  3657.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  3658.    GLchan primary_rgba[MAX_WIDTH][4];
  3659.    GLuint unit;
  3660.  
  3661.    ASSERT(span->end < MAX_WIDTH);
  3662.    ASSERT(span->arrayMask & SPAN_TEXTURE);
  3663.  
  3664.    /*
  3665.     * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
  3666.     */
  3667.    if (swrast->_AnyTextureCombine)
  3668.       MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan));
  3669.  
  3670.    /*
  3671.     * Must do all texture sampling before combining in order to
  3672.     * accomodate GL_ARB_texture_env_crossbar.
  3673.     */
  3674.    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
  3675.       if (ctx->Texture.Unit[unit]._ReallyEnabled) {
  3676.          const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  3677.          const struct gl_texture_object *curObj = texUnit->_Current;
  3678.          GLfloat *lambda = span->array->lambda[unit];
  3679.          GLchan (*texels)[4] = (GLchan (*)[4])
  3680.             (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan)));
  3681.  
  3682.          /* adjust texture lod (lambda) */
  3683.          if (span->arrayMask | SPAN_LAMBDA) {
  3684.             if (texUnit->LodBias != 0.0F) {
  3685.                /* apply LOD bias, but don't clamp yet */
  3686.                GLuint i;
  3687.                for (i = 0; i < span->end; i++) {
  3688.                   lambda[i] += texUnit->LodBias;
  3689.                }
  3690.             }
  3691.  
  3692.             if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
  3693.                /* apply LOD clamping to lambda */
  3694.                const GLfloat min = curObj->MinLod;
  3695.                const GLfloat max = curObj->MaxLod;
  3696.                GLuint i;
  3697.                for (i = 0; i < span->end; i++) {
  3698.                   GLfloat l = lambda[i];
  3699.                   lambda[i] = CLAMP(l, min, max);
  3700.                }
  3701.             }
  3702.          }
  3703.  
  3704.          /* Sample the texture (span->end fragments) */
  3705.          swrast->TextureSample[unit]( ctx, unit, texUnit->_Current,
  3706.                                       span->end, span->array->texcoords[unit],
  3707.                                       lambda, texels );
  3708.       }
  3709.    }
  3710.  
  3711.    /*
  3712.     * OK, now apply the texture (aka texture combine/blend).
  3713.     * We modify the span->color.rgba values.
  3714.     */
  3715.    for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
  3716.       if (ctx->Texture.Unit[unit]._ReallyEnabled) {
  3717.          const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  3718.          if (texUnit->EnvMode == GL_COMBINE_EXT) {
  3719.             /* GL_ARB/EXT_texture_env_combine */
  3720.             texture_combine( ctx, unit, span->end,
  3721.                              (CONST GLchan (*)[4]) primary_rgba,
  3722.                              swrast->TexelBuffer,
  3723.                              span->array->rgba );
  3724.          }
  3725.          else if (texUnit->EnvMode == GL_COMBINE4_NV) {
  3726.             /* GL_NV_texture_env_combine4 */
  3727.             texture_combine4( ctx, unit, span->end,
  3728.                               (CONST GLchan (*)[4]) primary_rgba,
  3729.                               swrast->TexelBuffer,
  3730.                               span->array->rgba );
  3731.          }
  3732.          else {
  3733.             /* conventional texture blend */
  3734.             const GLchan (*texels)[4] = (const GLchan (*)[4])
  3735.                (swrast->TexelBuffer + unit *
  3736.                 (span->end * 4 * sizeof(GLchan)));
  3737.             texture_apply( ctx, texUnit, span->end,
  3738.                            (CONST GLchan (*)[4]) primary_rgba, texels,
  3739.                            span->array->rgba );
  3740.          }
  3741.       }
  3742.    }
  3743. }
  3744.