Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.3
  4.  *
  5.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25.  
  26. #include "main/glheader.h"
  27. #include "main/context.h"
  28. #include "main/colormac.h"
  29. #include "main/imports.h"
  30. #include "main/texformat.h"
  31.  
  32. #include "s_context.h"
  33. #include "s_texfilter.h"
  34.  
  35.  
  36. /*
  37.  * Note, the FRAC macro has to work perfectly.  Otherwise you'll sometimes
  38.  * see 1-pixel bands of improperly weighted linear-filtered textures.
  39.  * The tests/texwrap.c demo is a good test.
  40.  * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
  41.  * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
  42.  */
  43. #define FRAC(f)  ((f) - IFLOOR(f))
  44.  
  45.  
  46.  
  47. /**
  48.  * Linear interpolation macro
  49.  */
  50. #define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) )
  51.  
  52.  
  53. /**
  54.  * Do 2D/biliner interpolation of float values.
  55.  * v00, v10, v01 and v11 are typically four texture samples in a square/box.
  56.  * a and b are the horizontal and vertical interpolants.
  57.  * It's important that this function is inlined when compiled with
  58.  * optimization!  If we find that's not true on some systems, convert
  59.  * to a macro.
  60.  */
  61. static INLINE GLfloat
  62. lerp_2d(GLfloat a, GLfloat b,
  63.         GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
  64. {
  65.    const GLfloat temp0 = LERP(a, v00, v10);
  66.    const GLfloat temp1 = LERP(a, v01, v11);
  67.    return LERP(b, temp0, temp1);
  68. }
  69.  
  70.  
  71. /**
  72.  * Do 3D/trilinear interpolation of float values.
  73.  * \sa lerp_2d
  74.  */
  75. static INLINE GLfloat
  76. lerp_3d(GLfloat a, GLfloat b, GLfloat c,
  77.         GLfloat v000, GLfloat v100, GLfloat v010, GLfloat v110,
  78.         GLfloat v001, GLfloat v101, GLfloat v011, GLfloat v111)
  79. {
  80.    const GLfloat temp00 = LERP(a, v000, v100);
  81.    const GLfloat temp10 = LERP(a, v010, v110);
  82.    const GLfloat temp01 = LERP(a, v001, v101);
  83.    const GLfloat temp11 = LERP(a, v011, v111);
  84.    const GLfloat temp0 = LERP(b, temp00, temp10);
  85.    const GLfloat temp1 = LERP(b, temp01, temp11);
  86.    return LERP(c, temp0, temp1);
  87. }
  88.  
  89.  
  90. /**
  91.  * Do linear interpolation of colors.
  92.  */
  93. static INLINE void
  94. lerp_rgba(GLfloat result[4], GLfloat t, const GLfloat a[4], const GLfloat b[4])
  95. {
  96.    result[0] = LERP(t, a[0], b[0]);
  97.    result[1] = LERP(t, a[1], b[1]);
  98.    result[2] = LERP(t, a[2], b[2]);
  99.    result[3] = LERP(t, a[3], b[3]);
  100. }
  101.  
  102.  
  103. /**
  104.  * Do bilinear interpolation of colors.
  105.  */
  106. static INLINE void
  107. lerp_rgba_2d(GLfloat result[4], GLfloat a, GLfloat b,
  108.              const GLfloat t00[4], const GLfloat t10[4],
  109.              const GLfloat t01[4], const GLfloat t11[4])
  110. {
  111.    result[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]);
  112.    result[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]);
  113.    result[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]);
  114.    result[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]);
  115. }
  116.  
  117.  
  118. /**
  119.  * Do trilinear interpolation of colors.
  120.  */
  121. static INLINE void
  122. lerp_rgba_3d(GLfloat result[4], GLfloat a, GLfloat b, GLfloat c,
  123.              const GLfloat t000[4], const GLfloat t100[4],
  124.              const GLfloat t010[4], const GLfloat t110[4],
  125.              const GLfloat t001[4], const GLfloat t101[4],
  126.              const GLfloat t011[4], const GLfloat t111[4])
  127. {
  128.    GLuint k;
  129.    /* compiler should unroll these short loops */
  130.    for (k = 0; k < 4; k++) {
  131.       result[k] = lerp_3d(a, b, c, t000[k], t100[k], t010[k], t110[k],
  132.                                    t001[k], t101[k], t011[k], t111[k]);
  133.    }
  134. }
  135.  
  136.  
  137. /**
  138.  * Used for GL_REPEAT wrap mode.  Using A % B doesn't produce the
  139.  * right results for A<0.  Casting to A to be unsigned only works if B
  140.  * is a power of two.  Adding a bias to A (which is a multiple of B)
  141.  * avoids the problems with A < 0 (for reasonable A) without using a
  142.  * conditional.
  143.  */
  144. #define REMAINDER(A, B) (((A) + (B) * 1024) % (B))
  145.  
  146.  
  147. /**
  148.  * Used to compute texel locations for linear sampling.
  149.  * Input:
  150.  *    wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
  151.  *    s = texcoord in [0,1]
  152.  *    size = width (or height or depth) of texture
  153.  * Output:
  154.  *    i0, i1 = returns two nearest texel indexes
  155.  *    weight = returns blend factor between texels
  156.  */
  157. static INLINE void
  158. linear_texel_locations(GLenum wrapMode,
  159.                        const struct gl_texture_image *img,
  160.                        GLint size, GLfloat s,
  161.                        GLint *i0, GLint *i1, GLfloat *weight)
  162. {
  163.    GLfloat u;
  164.    switch (wrapMode) {
  165.    case GL_REPEAT:
  166.       u = s * size - 0.5F;
  167.       if (img->_IsPowerOfTwo) {
  168.          *i0 = IFLOOR(u) & (size - 1);
  169.          *i1 = (*i0 + 1) & (size - 1);
  170.       }
  171.       else {
  172.          *i0 = REMAINDER(IFLOOR(u), size);
  173.          *i1 = REMAINDER(*i0 + 1, size);
  174.       }
  175.       break;
  176.    case GL_CLAMP_TO_EDGE:
  177.       if (s <= 0.0F)
  178.          u = 0.0F;
  179.       else if (s >= 1.0F)
  180.          u = (GLfloat) size;
  181.       else
  182.          u = s * size;
  183.       u -= 0.5F;
  184.       *i0 = IFLOOR(u);
  185.       *i1 = *i0 + 1;
  186.       if (*i0 < 0)
  187.          *i0 = 0;
  188.       if (*i1 >= (GLint) size)
  189.          *i1 = size - 1;
  190.       break;
  191.    case GL_CLAMP_TO_BORDER:
  192.       {
  193.          const GLfloat min = -1.0F / (2.0F * size);
  194.          const GLfloat max = 1.0F - min;
  195.          if (s <= min)
  196.             u = min * size;
  197.          else if (s >= max)
  198.             u = max * size;
  199.          else
  200.             u = s * size;
  201.          u -= 0.5F;
  202.          *i0 = IFLOOR(u);
  203.          *i1 = *i0 + 1;
  204.       }
  205.       break;
  206.    case GL_MIRRORED_REPEAT:
  207.       {
  208.          const GLint flr = IFLOOR(s);
  209.          if (flr & 1)
  210.             u = 1.0F - (s - (GLfloat) flr);
  211.          else
  212.             u = s - (GLfloat) flr;
  213.          u = (u * size) - 0.5F;
  214.          *i0 = IFLOOR(u);
  215.          *i1 = *i0 + 1;
  216.          if (*i0 < 0)
  217.             *i0 = 0;
  218.          if (*i1 >= (GLint) size)
  219.             *i1 = size - 1;
  220.       }
  221.       break;
  222.    case GL_MIRROR_CLAMP_EXT:
  223.       u = FABSF(s);
  224.       if (u >= 1.0F)
  225.          u = (GLfloat) size;
  226.       else
  227.          u *= size;
  228.       u -= 0.5F;
  229.       *i0 = IFLOOR(u);
  230.       *i1 = *i0 + 1;
  231.       break;
  232.    case GL_MIRROR_CLAMP_TO_EDGE_EXT:
  233.       u = FABSF(s);
  234.       if (u >= 1.0F)
  235.          u = (GLfloat) size;
  236.       else
  237.          u *= size;
  238.       u -= 0.5F;
  239.       *i0 = IFLOOR(u);
  240.       *i1 = *i0 + 1;
  241.       if (*i0 < 0)
  242.          *i0 = 0;
  243.       if (*i1 >= (GLint) size)
  244.          *i1 = size - 1;
  245.       break;
  246.    case GL_MIRROR_CLAMP_TO_BORDER_EXT:
  247.       {
  248.          const GLfloat min = -1.0F / (2.0F * size);
  249.          const GLfloat max = 1.0F - min;
  250.          u = FABSF(s);
  251.          if (u <= min)
  252.             u = min * size;
  253.          else if (u >= max)
  254.             u = max * size;
  255.          else
  256.             u *= size;
  257.          u -= 0.5F;
  258.          *i0 = IFLOOR(u);
  259.          *i1 = *i0 + 1;
  260.       }
  261.       break;
  262.    case GL_CLAMP:
  263.       if (s <= 0.0F)
  264.          u = 0.0F;
  265.       else if (s >= 1.0F)
  266.          u = (GLfloat) size;
  267.       else
  268.          u = s * size;
  269.       u -= 0.5F;
  270.       *i0 = IFLOOR(u);
  271.       *i1 = *i0 + 1;
  272.       break;
  273.    default:
  274.       _mesa_problem(NULL, "Bad wrap mode");
  275.       u = 0.0F;
  276.    }
  277.    *weight = FRAC(u);
  278. }
  279.  
  280.  
  281. /**
  282.  * Used to compute texel location for nearest sampling.
  283.  */
  284. static INLINE GLint
  285. nearest_texel_location(GLenum wrapMode,
  286.                        const struct gl_texture_image *img,
  287.                        GLint size, GLfloat s)
  288. {
  289.    GLint i;
  290.  
  291.    switch (wrapMode) {
  292.    case GL_REPEAT:
  293.       /* s limited to [0,1) */
  294.       /* i limited to [0,size-1] */
  295.       i = IFLOOR(s * size);
  296.       if (img->_IsPowerOfTwo)
  297.          i &= (size - 1);
  298.       else
  299.          i = REMAINDER(i, size);
  300.       return i;
  301.    case GL_CLAMP_TO_EDGE:
  302.       {
  303.          /* s limited to [min,max] */
  304.          /* i limited to [0, size-1] */
  305.          const GLfloat min = 1.0F / (2.0F * size);
  306.          const GLfloat max = 1.0F - min;
  307.          if (s < min)
  308.             i = 0;
  309.          else if (s > max)
  310.             i = size - 1;
  311.          else
  312.             i = IFLOOR(s * size);
  313.       }
  314.       return i;
  315.    case GL_CLAMP_TO_BORDER:
  316.       {
  317.          /* s limited to [min,max] */
  318.          /* i limited to [-1, size] */
  319.          const GLfloat min = -1.0F / (2.0F * size);
  320.          const GLfloat max = 1.0F - min;
  321.          if (s <= min)
  322.             i = -1;
  323.          else if (s >= max)
  324.             i = size;
  325.          else
  326.             i = IFLOOR(s * size);
  327.       }
  328.       return i;
  329.    case GL_MIRRORED_REPEAT:
  330.       {
  331.          const GLfloat min = 1.0F / (2.0F * size);
  332.          const GLfloat max = 1.0F - min;
  333.          const GLint flr = IFLOOR(s);
  334.          GLfloat u;
  335.          if (flr & 1)
  336.             u = 1.0F - (s - (GLfloat) flr);
  337.          else
  338.             u = s - (GLfloat) flr;
  339.          if (u < min)
  340.             i = 0;
  341.          else if (u > max)
  342.             i = size - 1;
  343.          else
  344.             i = IFLOOR(u * size);
  345.       }
  346.       return i;
  347.    case GL_MIRROR_CLAMP_EXT:
  348.       {
  349.          /* s limited to [0,1] */
  350.          /* i limited to [0,size-1] */
  351.          const GLfloat u = FABSF(s);
  352.          if (u <= 0.0F)
  353.             i = 0;
  354.          else if (u >= 1.0F)
  355.             i = size - 1;
  356.          else
  357.             i = IFLOOR(u * size);
  358.       }
  359.       return i;
  360.    case GL_MIRROR_CLAMP_TO_EDGE_EXT:
  361.       {
  362.          /* s limited to [min,max] */
  363.          /* i limited to [0, size-1] */
  364.          const GLfloat min = 1.0F / (2.0F * size);
  365.          const GLfloat max = 1.0F - min;
  366.          const GLfloat u = FABSF(s);
  367.          if (u < min)
  368.             i = 0;
  369.          else if (u > max)
  370.             i = size - 1;
  371.          else
  372.             i = IFLOOR(u * size);
  373.       }
  374.       return i;
  375.    case GL_MIRROR_CLAMP_TO_BORDER_EXT:
  376.       {
  377.          /* s limited to [min,max] */
  378.          /* i limited to [0, size-1] */
  379.          const GLfloat min = -1.0F / (2.0F * size);
  380.          const GLfloat max = 1.0F - min;
  381.          const GLfloat u = FABSF(s);
  382.          if (u < min)
  383.             i = -1;
  384.          else if (u > max)
  385.             i = size;
  386.          else
  387.             i = IFLOOR(u * size);
  388.       }
  389.       return i;
  390.    case GL_CLAMP:
  391.       /* s limited to [0,1] */
  392.       /* i limited to [0,size-1] */
  393.       if (s <= 0.0F)
  394.          i = 0;
  395.       else if (s >= 1.0F)
  396.          i = size - 1;
  397.       else
  398.          i = IFLOOR(s * size);
  399.       return i;
  400.    default:
  401.       _mesa_problem(NULL, "Bad wrap mode");
  402.       return 0;
  403.    }
  404. }
  405.  
  406.  
  407. /* Power of two image sizes only */
  408. static INLINE void
  409. linear_repeat_texel_location(GLuint size, GLfloat s,
  410.                              GLint *i0, GLint *i1, GLfloat *weight)
  411. {
  412.    GLfloat u = s * size - 0.5F;
  413.    *i0 = IFLOOR(u) & (size - 1);
  414.    *i1 = (*i0 + 1) & (size - 1);
  415.    *weight = FRAC(u);
  416. }
  417.  
  418.  
  419. /**
  420.  * Do clamp/wrap for a texture rectangle coord, GL_NEAREST filter mode.
  421.  */
  422. static INLINE GLint
  423. clamp_rect_coord_nearest(GLenum wrapMode, GLfloat coord, GLint max)
  424. {
  425.    switch (wrapMode) {
  426.    case GL_CLAMP:
  427.       return IFLOOR( CLAMP(coord, 0.0F, max - 1) );
  428.    case GL_CLAMP_TO_EDGE:
  429.       return IFLOOR( CLAMP(coord, 0.5F, max - 0.5F) );
  430.    case GL_CLAMP_TO_BORDER:
  431.       return IFLOOR( CLAMP(coord, -0.5F, max + 0.5F) );
  432.    default:
  433.       _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_nearest");
  434.       return 0;
  435.    }
  436. }
  437.  
  438.  
  439. /**
  440.  * As above, but GL_LINEAR filtering.
  441.  */
  442. static INLINE void
  443. clamp_rect_coord_linear(GLenum wrapMode, GLfloat coord, GLint max,
  444.                         GLint *i0out, GLint *i1out, GLfloat *weight)
  445. {
  446.    GLfloat fcol;
  447.    GLint i0, i1;
  448.    switch (wrapMode) {
  449.    case GL_CLAMP:
  450.       /* Not exactly what the spec says, but it matches NVIDIA output */
  451.       fcol = CLAMP(coord - 0.5F, 0.0F, max - 1);
  452.       i0 = IFLOOR(fcol);
  453.       i1 = i0 + 1;
  454.       break;
  455.    case GL_CLAMP_TO_EDGE:
  456.       fcol = CLAMP(coord, 0.5F, max - 0.5F);
  457.       fcol -= 0.5F;
  458.       i0 = IFLOOR(fcol);
  459.       i1 = i0 + 1;
  460.       if (i1 > max - 1)
  461.          i1 = max - 1;
  462.       break;
  463.    case GL_CLAMP_TO_BORDER:
  464.       fcol = CLAMP(coord, -0.5F, max + 0.5F);
  465.       fcol -= 0.5F;
  466.       i0 = IFLOOR(fcol);
  467.       i1 = i0 + 1;
  468.       break;
  469.    default:
  470.       _mesa_problem(NULL, "bad wrapMode in clamp_rect_coord_linear");
  471.       i0 = i1 = 0;
  472.       fcol = 0.0F;
  473.    }
  474.    *i0out = i0;
  475.    *i1out = i1;
  476.    *weight = FRAC(fcol);
  477. }
  478.  
  479.  
  480. /**
  481.  * Compute slice/image to use for 1D or 2D array texture.
  482.  */
  483. static INLINE GLint
  484. tex_array_slice(GLfloat coord, GLsizei size)
  485. {
  486.    GLint slice = IFLOOR(coord + 0.5f);
  487.    slice = CLAMP(slice, 0, size - 1);
  488.    return slice;
  489. }
  490.  
  491.  
  492. /**
  493.  * Compute nearest integer texcoords for given texobj and coordinate.
  494.  * NOTE: only used for depth texture sampling.
  495.  */
  496. static INLINE void
  497. nearest_texcoord(const struct gl_texture_object *texObj,
  498.                  GLuint level,
  499.                  const GLfloat texcoord[4],
  500.                  GLint *i, GLint *j, GLint *k)
  501. {
  502.    const struct gl_texture_image *img = texObj->Image[0][level];
  503.    const GLint width = img->Width;
  504.    const GLint height = img->Height;
  505.    const GLint depth = img->Depth;
  506.  
  507.    switch (texObj->Target) {
  508.    case GL_TEXTURE_RECTANGLE_ARB:
  509.       *i = clamp_rect_coord_nearest(texObj->WrapS, texcoord[0], width);
  510.       *j = clamp_rect_coord_nearest(texObj->WrapT, texcoord[1], height);
  511.       *k = 0;
  512.       break;
  513.    case GL_TEXTURE_1D:
  514.       *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
  515.       *j = 0;
  516.       *k = 0;
  517.       break;
  518.    case GL_TEXTURE_2D:
  519.       *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
  520.       *j = nearest_texel_location(texObj->WrapT, img, height, texcoord[1]);
  521.       *k = 0;
  522.       break;
  523.    case GL_TEXTURE_1D_ARRAY_EXT:
  524.       *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
  525.       *j = tex_array_slice(texcoord[1], height);
  526.       *k = 0;
  527.       break;
  528.    case GL_TEXTURE_2D_ARRAY_EXT:
  529.       *i = nearest_texel_location(texObj->WrapS, img, width, texcoord[0]);
  530.       *j = nearest_texel_location(texObj->WrapT, img, height, texcoord[1]);
  531.       *k = tex_array_slice(texcoord[2], depth);
  532.       break;
  533.    default:
  534.       *i = *j = *k = 0;
  535.    }
  536. }
  537.  
  538.  
  539. /**
  540.  * Compute linear integer texcoords for given texobj and coordinate.
  541.  * NOTE: only used for depth texture sampling.
  542.  */
  543. static INLINE void
  544. linear_texcoord(const struct gl_texture_object *texObj,
  545.                 GLuint level,
  546.                 const GLfloat texcoord[4],
  547.                 GLint *i0, GLint *i1, GLint *j0, GLint *j1, GLint *slice,
  548.                 GLfloat *wi, GLfloat *wj)
  549. {
  550.    const struct gl_texture_image *img = texObj->Image[0][level];
  551.    const GLint width = img->Width;
  552.    const GLint height = img->Height;
  553.    const GLint depth = img->Depth;
  554.  
  555.    switch (texObj->Target) {
  556.    case GL_TEXTURE_RECTANGLE_ARB:
  557.       clamp_rect_coord_linear(texObj->WrapS, texcoord[0],
  558.                               width, i0, i1, wi);
  559.       clamp_rect_coord_linear(texObj->WrapT, texcoord[1],
  560.                               height, j0, j1, wj);
  561.       *slice = 0;
  562.       break;
  563.  
  564.    case GL_TEXTURE_1D:
  565.    case GL_TEXTURE_2D:
  566.       linear_texel_locations(texObj->WrapS, img, width,
  567.                              texcoord[0], i0, i1, wi);
  568.       linear_texel_locations(texObj->WrapT, img, height,
  569.                              texcoord[1], j0, j1, wj);
  570.       *slice = 0;
  571.       break;
  572.  
  573.    case GL_TEXTURE_1D_ARRAY_EXT:
  574.       linear_texel_locations(texObj->WrapS, img, width,
  575.                              texcoord[0], i0, i1, wi);
  576.       *j0 = tex_array_slice(texcoord[1], height);
  577.       *j1 = *j0;
  578.       *slice = 0;
  579.       break;
  580.  
  581.    case GL_TEXTURE_2D_ARRAY_EXT:
  582.       linear_texel_locations(texObj->WrapS, img, width,
  583.                              texcoord[0], i0, i1, wi);
  584.       linear_texel_locations(texObj->WrapT, img, height,
  585.                              texcoord[1], j0, j1, wj);
  586.       *slice = tex_array_slice(texcoord[2], depth);
  587.       break;
  588.  
  589.    default:
  590.       *slice = 0;
  591.    }
  592. }
  593.  
  594.  
  595.  
  596. /**
  597.  * For linear interpolation between mipmap levels N and N+1, this function
  598.  * computes N.
  599.  */
  600. static INLINE GLint
  601. linear_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda)
  602. {
  603.    if (lambda < 0.0F)
  604.       return tObj->BaseLevel;
  605.    else if (lambda > tObj->_MaxLambda)
  606.       return (GLint) (tObj->BaseLevel + tObj->_MaxLambda);
  607.    else
  608.       return (GLint) (tObj->BaseLevel + lambda);
  609. }
  610.  
  611.  
  612. /**
  613.  * Compute the nearest mipmap level to take texels from.
  614.  */
  615. static INLINE GLint
  616. nearest_mipmap_level(const struct gl_texture_object *tObj, GLfloat lambda)
  617. {
  618.    GLfloat l;
  619.    GLint level;
  620.    if (lambda <= 0.5F)
  621.       l = 0.0F;
  622.    else if (lambda > tObj->_MaxLambda + 0.4999F)
  623.       l = tObj->_MaxLambda + 0.4999F;
  624.    else
  625.       l = lambda;
  626.    level = (GLint) (tObj->BaseLevel + l + 0.5F);
  627.    if (level > tObj->_MaxLevel)
  628.       level = tObj->_MaxLevel;
  629.    return level;
  630. }
  631.  
  632.  
  633.  
  634. /*
  635.  * Bitflags for texture border color sampling.
  636.  */
  637. #define I0BIT   1
  638. #define I1BIT   2
  639. #define J0BIT   4
  640. #define J1BIT   8
  641. #define K0BIT  16
  642. #define K1BIT  32
  643.  
  644.  
  645.  
  646. /**
  647.  * The lambda[] array values are always monotonic.  Either the whole span
  648.  * will be minified, magnified, or split between the two.  This function
  649.  * determines the subranges in [0, n-1] that are to be minified or magnified.
  650.  */
  651. static INLINE void
  652. compute_min_mag_ranges(const struct gl_texture_object *tObj,
  653.                        GLuint n, const GLfloat lambda[],
  654.                        GLuint *minStart, GLuint *minEnd,
  655.                        GLuint *magStart, GLuint *magEnd)
  656. {
  657.    GLfloat minMagThresh;
  658.  
  659.    /* we shouldn't be here if minfilter == magfilter */
  660.    ASSERT(tObj->MinFilter != tObj->MagFilter);
  661.  
  662.    /* This bit comes from the OpenGL spec: */
  663.    if (tObj->MagFilter == GL_LINEAR
  664.        && (tObj->MinFilter == GL_NEAREST_MIPMAP_NEAREST ||
  665.            tObj->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) {
  666.       minMagThresh = 0.5F;
  667.    }
  668.    else {
  669.       minMagThresh = 0.0F;
  670.    }
  671.  
  672. #if 0
  673.    /* DEBUG CODE: Verify that lambda[] is monotonic.
  674.     * We can't really use this because the inaccuracy in the LOG2 function
  675.     * causes this test to fail, yet the resulting texturing is correct.
  676.     */
  677.    if (n > 1) {
  678.       GLuint i;
  679.       printf("lambda delta = %g\n", lambda[0] - lambda[n-1]);
  680.       if (lambda[0] >= lambda[n-1]) { /* decreasing */
  681.          for (i = 0; i < n - 1; i++) {
  682.             ASSERT((GLint) (lambda[i] * 10) >= (GLint) (lambda[i+1] * 10));
  683.          }
  684.       }
  685.       else { /* increasing */
  686.          for (i = 0; i < n - 1; i++) {
  687.             ASSERT((GLint) (lambda[i] * 10) <= (GLint) (lambda[i+1] * 10));
  688.          }
  689.       }
  690.    }
  691. #endif /* DEBUG */
  692.  
  693.    if (lambda[0] <= minMagThresh && (n <= 1 || lambda[n-1] <= minMagThresh)) {
  694.       /* magnification for whole span */
  695.       *magStart = 0;
  696.       *magEnd = n;
  697.       *minStart = *minEnd = 0;
  698.    }
  699.    else if (lambda[0] > minMagThresh && (n <=1 || lambda[n-1] > minMagThresh)) {
  700.       /* minification for whole span */
  701.       *minStart = 0;
  702.       *minEnd = n;
  703.       *magStart = *magEnd = 0;
  704.    }
  705.    else {
  706.       /* a mix of minification and magnification */
  707.       GLuint i;
  708.       if (lambda[0] > minMagThresh) {
  709.          /* start with minification */
  710.          for (i = 1; i < n; i++) {
  711.             if (lambda[i] <= minMagThresh)
  712.                break;
  713.          }
  714.          *minStart = 0;
  715.          *minEnd = i;
  716.          *magStart = i;
  717.          *magEnd = n;
  718.       }
  719.       else {
  720.          /* start with magnification */
  721.          for (i = 1; i < n; i++) {
  722.             if (lambda[i] > minMagThresh)
  723.                break;
  724.          }
  725.          *magStart = 0;
  726.          *magEnd = i;
  727.          *minStart = i;
  728.          *minEnd = n;
  729.       }
  730.    }
  731.  
  732. #if 0
  733.    /* Verify the min/mag Start/End values
  734.     * We don't use this either (see above)
  735.     */
  736.    {
  737.       GLint i;
  738.       for (i = 0; i < n; i++) {
  739.          if (lambda[i] > minMagThresh) {
  740.             /* minification */
  741.             ASSERT(i >= *minStart);
  742.             ASSERT(i < *minEnd);
  743.          }
  744.          else {
  745.             /* magnification */
  746.             ASSERT(i >= *magStart);
  747.             ASSERT(i < *magEnd);
  748.          }
  749.       }
  750.    }
  751. #endif
  752. }
  753.  
  754.  
  755. /**
  756.  * When we sample the border color, it must be interpreted according to
  757.  * the base texture format.  Ex: if the texture base format it GL_ALPHA,
  758.  * we return (0,0,0,BorderAlpha).
  759.  */
  760. static INLINE void
  761. get_border_color(const struct gl_texture_object *tObj,
  762.                  const struct gl_texture_image *img,
  763.                  GLfloat rgba[4])
  764. {
  765.    switch (img->_BaseFormat) {
  766.    case GL_RGB:
  767.       rgba[0] = tObj->BorderColor.f[0];
  768.       rgba[1] = tObj->BorderColor.f[1];
  769.       rgba[2] = tObj->BorderColor.f[2];
  770.       rgba[3] = 1.0F;
  771.       break;
  772.    case GL_ALPHA:
  773.       rgba[0] = rgba[1] = rgba[2] = 0.0;
  774.       rgba[3] = tObj->BorderColor.f[3];
  775.       break;
  776.    case GL_LUMINANCE:
  777.       rgba[0] = rgba[1] = rgba[2] = tObj->BorderColor.f[0];
  778.       rgba[3] = 1.0;
  779.       break;
  780.    case GL_LUMINANCE_ALPHA:
  781.       rgba[0] = rgba[1] = rgba[2] = tObj->BorderColor.f[0];
  782.       rgba[3] = tObj->BorderColor.f[3];
  783.       break;
  784.    case GL_INTENSITY:
  785.       rgba[0] = rgba[1] = rgba[2] = rgba[3] = tObj->BorderColor.f[0];
  786.       break;
  787.    default:
  788.       COPY_4V(rgba, tObj->BorderColor.f);
  789.    }
  790. }
  791.  
  792.  
  793. /**********************************************************************/
  794. /*                    1-D Texture Sampling Functions                  */
  795. /**********************************************************************/
  796.  
  797. /**
  798.  * Return the texture sample for coordinate (s) using GL_NEAREST filter.
  799.  */
  800. static INLINE void
  801. sample_1d_nearest(struct gl_context *ctx,
  802.                   const struct gl_texture_object *tObj,
  803.                   const struct gl_texture_image *img,
  804.                   const GLfloat texcoord[4], GLfloat rgba[4])
  805. {
  806.    const GLint width = img->Width2;  /* without border, power of two */
  807.    GLint i;
  808.    i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
  809.    /* skip over the border, if any */
  810.    i += img->Border;
  811.    if (i < 0 || i >= (GLint) img->Width) {
  812.       /* Need this test for GL_CLAMP_TO_BORDER mode */
  813.       get_border_color(tObj, img, rgba);
  814.    }
  815.    else {
  816.       img->FetchTexelf(img, i, 0, 0, rgba);
  817.    }
  818. }
  819.  
  820.  
  821. /**
  822.  * Return the texture sample for coordinate (s) using GL_LINEAR filter.
  823.  */
  824. static INLINE void
  825. sample_1d_linear(struct gl_context *ctx,
  826.                  const struct gl_texture_object *tObj,
  827.                  const struct gl_texture_image *img,
  828.                  const GLfloat texcoord[4], GLfloat rgba[4])
  829. {
  830.    const GLint width = img->Width2;
  831.    GLint i0, i1;
  832.    GLbitfield useBorderColor = 0x0;
  833.    GLfloat a;
  834.    GLfloat t0[4], t1[4];  /* texels */
  835.  
  836.    linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
  837.  
  838.    if (img->Border) {
  839.       i0 += img->Border;
  840.       i1 += img->Border;
  841.    }
  842.    else {
  843.       if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
  844.       if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
  845.    }
  846.  
  847.    /* fetch texel colors */
  848.    if (useBorderColor & I0BIT) {
  849.       get_border_color(tObj, img, t0);
  850.    }
  851.    else {
  852.       img->FetchTexelf(img, i0, 0, 0, t0);
  853.    }
  854.    if (useBorderColor & I1BIT) {
  855.       get_border_color(tObj, img, t1);
  856.    }
  857.    else {
  858.       img->FetchTexelf(img, i1, 0, 0, t1);
  859.    }
  860.  
  861.    lerp_rgba(rgba, a, t0, t1);
  862. }
  863.  
  864.  
  865. static void
  866. sample_1d_nearest_mipmap_nearest(struct gl_context *ctx,
  867.                                  const struct gl_texture_object *tObj,
  868.                                  GLuint n, const GLfloat texcoord[][4],
  869.                                  const GLfloat lambda[], GLfloat rgba[][4])
  870. {
  871.    GLuint i;
  872.    ASSERT(lambda != NULL);
  873.    for (i = 0; i < n; i++) {
  874.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  875.       sample_1d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
  876.    }
  877. }
  878.  
  879.  
  880. static void
  881. sample_1d_linear_mipmap_nearest(struct gl_context *ctx,
  882.                                 const struct gl_texture_object *tObj,
  883.                                 GLuint n, const GLfloat texcoord[][4],
  884.                                 const GLfloat lambda[], GLfloat rgba[][4])
  885. {
  886.    GLuint i;
  887.    ASSERT(lambda != NULL);
  888.    for (i = 0; i < n; i++) {
  889.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  890.       sample_1d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
  891.    }
  892. }
  893.  
  894.  
  895. static void
  896. sample_1d_nearest_mipmap_linear(struct gl_context *ctx,
  897.                                 const struct gl_texture_object *tObj,
  898.                                 GLuint n, const GLfloat texcoord[][4],
  899.                                 const GLfloat lambda[], GLfloat rgba[][4])
  900. {
  901.    GLuint i;
  902.    ASSERT(lambda != NULL);
  903.    for (i = 0; i < n; i++) {
  904.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  905.       if (level >= tObj->_MaxLevel) {
  906.          sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  907.                            texcoord[i], rgba[i]);
  908.       }
  909.       else {
  910.          GLfloat t0[4], t1[4];
  911.          const GLfloat f = FRAC(lambda[i]);
  912.          sample_1d_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
  913.          sample_1d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
  914.          lerp_rgba(rgba[i], f, t0, t1);
  915.       }
  916.    }
  917. }
  918.  
  919.  
  920. static void
  921. sample_1d_linear_mipmap_linear(struct gl_context *ctx,
  922.                                const struct gl_texture_object *tObj,
  923.                                GLuint n, const GLfloat texcoord[][4],
  924.                                const GLfloat lambda[], GLfloat rgba[][4])
  925. {
  926.    GLuint i;
  927.    ASSERT(lambda != NULL);
  928.    for (i = 0; i < n; i++) {
  929.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  930.       if (level >= tObj->_MaxLevel) {
  931.          sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  932.                           texcoord[i], rgba[i]);
  933.       }
  934.       else {
  935.          GLfloat t0[4], t1[4];
  936.          const GLfloat f = FRAC(lambda[i]);
  937.          sample_1d_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
  938.          sample_1d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
  939.          lerp_rgba(rgba[i], f, t0, t1);
  940.       }
  941.    }
  942. }
  943.  
  944.  
  945. /** Sample 1D texture, nearest filtering for both min/magnification */
  946. static void
  947. sample_nearest_1d( struct gl_context *ctx,
  948.                    const struct gl_texture_object *tObj, GLuint n,
  949.                    const GLfloat texcoords[][4], const GLfloat lambda[],
  950.                    GLfloat rgba[][4] )
  951. {
  952.    GLuint i;
  953.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  954.    (void) lambda;
  955.    for (i = 0; i < n; i++) {
  956.       sample_1d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
  957.    }
  958. }
  959.  
  960.  
  961. /** Sample 1D texture, linear filtering for both min/magnification */
  962. static void
  963. sample_linear_1d( struct gl_context *ctx,
  964.                   const struct gl_texture_object *tObj, GLuint n,
  965.                   const GLfloat texcoords[][4], const GLfloat lambda[],
  966.                   GLfloat rgba[][4] )
  967. {
  968.    GLuint i;
  969.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  970.    (void) lambda;
  971.    for (i = 0; i < n; i++) {
  972.       sample_1d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
  973.    }
  974. }
  975.  
  976.  
  977. /** Sample 1D texture, using lambda to choose between min/magnification */
  978. static void
  979. sample_lambda_1d( struct gl_context *ctx,
  980.                   const struct gl_texture_object *tObj, GLuint n,
  981.                   const GLfloat texcoords[][4],
  982.                   const GLfloat lambda[], GLfloat rgba[][4] )
  983. {
  984.    GLuint minStart, minEnd;  /* texels with minification */
  985.    GLuint magStart, magEnd;  /* texels with magnification */
  986.    GLuint i;
  987.  
  988.    ASSERT(lambda != NULL);
  989.    compute_min_mag_ranges(tObj, n, lambda,
  990.                           &minStart, &minEnd, &magStart, &magEnd);
  991.  
  992.    if (minStart < minEnd) {
  993.       /* do the minified texels */
  994.       const GLuint m = minEnd - minStart;
  995.       switch (tObj->MinFilter) {
  996.       case GL_NEAREST:
  997.          for (i = minStart; i < minEnd; i++)
  998.             sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  999.                               texcoords[i], rgba[i]);
  1000.          break;
  1001.       case GL_LINEAR:
  1002.          for (i = minStart; i < minEnd; i++)
  1003.             sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  1004.                              texcoords[i], rgba[i]);
  1005.          break;
  1006.       case GL_NEAREST_MIPMAP_NEAREST:
  1007.          sample_1d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  1008.                                           lambda + minStart, rgba + minStart);
  1009.          break;
  1010.       case GL_LINEAR_MIPMAP_NEAREST:
  1011.          sample_1d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  1012.                                          lambda + minStart, rgba + minStart);
  1013.          break;
  1014.       case GL_NEAREST_MIPMAP_LINEAR:
  1015.          sample_1d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1016.                                          lambda + minStart, rgba + minStart);
  1017.          break;
  1018.       case GL_LINEAR_MIPMAP_LINEAR:
  1019.          sample_1d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1020.                                         lambda + minStart, rgba + minStart);
  1021.          break;
  1022.       default:
  1023.          _mesa_problem(ctx, "Bad min filter in sample_1d_texture");
  1024.          return;
  1025.       }
  1026.    }
  1027.  
  1028.    if (magStart < magEnd) {
  1029.       /* do the magnified texels */
  1030.       switch (tObj->MagFilter) {
  1031.       case GL_NEAREST:
  1032.          for (i = magStart; i < magEnd; i++)
  1033.             sample_1d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  1034.                               texcoords[i], rgba[i]);
  1035.          break;
  1036.       case GL_LINEAR:
  1037.          for (i = magStart; i < magEnd; i++)
  1038.             sample_1d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  1039.                              texcoords[i], rgba[i]);
  1040.          break;
  1041.       default:
  1042.          _mesa_problem(ctx, "Bad mag filter in sample_1d_texture");
  1043.          return;
  1044.       }
  1045.    }
  1046. }
  1047.  
  1048.  
  1049. /**********************************************************************/
  1050. /*                    2-D Texture Sampling Functions                  */
  1051. /**********************************************************************/
  1052.  
  1053.  
  1054. /**
  1055.  * Return the texture sample for coordinate (s,t) using GL_NEAREST filter.
  1056.  */
  1057. static INLINE void
  1058. sample_2d_nearest(struct gl_context *ctx,
  1059.                   const struct gl_texture_object *tObj,
  1060.                   const struct gl_texture_image *img,
  1061.                   const GLfloat texcoord[4],
  1062.                   GLfloat rgba[])
  1063. {
  1064.    const GLint width = img->Width2;    /* without border, power of two */
  1065.    const GLint height = img->Height2;  /* without border, power of two */
  1066.    GLint i, j;
  1067.    (void) ctx;
  1068.  
  1069.    i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
  1070.    j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]);
  1071.  
  1072.    /* skip over the border, if any */
  1073.    i += img->Border;
  1074.    j += img->Border;
  1075.  
  1076.    if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
  1077.       /* Need this test for GL_CLAMP_TO_BORDER mode */
  1078.       get_border_color(tObj, img, rgba);
  1079.    }
  1080.    else {
  1081.       img->FetchTexelf(img, i, j, 0, rgba);
  1082.    }
  1083. }
  1084.  
  1085.  
  1086. /**
  1087.  * Return the texture sample for coordinate (s,t) using GL_LINEAR filter.
  1088.  * New sampling code contributed by Lynn Quam <quam@ai.sri.com>.
  1089.  */
  1090. static INLINE void
  1091. sample_2d_linear(struct gl_context *ctx,
  1092.                  const struct gl_texture_object *tObj,
  1093.                  const struct gl_texture_image *img,
  1094.                  const GLfloat texcoord[4],
  1095.                  GLfloat rgba[])
  1096. {
  1097.    const GLint width = img->Width2;
  1098.    const GLint height = img->Height2;
  1099.    GLint i0, j0, i1, j1;
  1100.    GLbitfield useBorderColor = 0x0;
  1101.    GLfloat a, b;
  1102.    GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
  1103.  
  1104.    linear_texel_locations(tObj->WrapS, img, width, texcoord[0],  &i0, &i1, &a);
  1105.    linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
  1106.  
  1107.    if (img->Border) {
  1108.       i0 += img->Border;
  1109.       i1 += img->Border;
  1110.       j0 += img->Border;
  1111.       j1 += img->Border;
  1112.    }
  1113.    else {
  1114.       if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
  1115.       if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
  1116.       if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
  1117.       if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
  1118.    }
  1119.  
  1120.    /* fetch four texel colors */
  1121.    if (useBorderColor & (I0BIT | J0BIT)) {
  1122.       get_border_color(tObj, img, t00);
  1123.    }
  1124.    else {
  1125.       img->FetchTexelf(img, i0, j0, 0, t00);
  1126.    }
  1127.    if (useBorderColor & (I1BIT | J0BIT)) {
  1128.       get_border_color(tObj, img, t10);
  1129.    }
  1130.    else {
  1131.       img->FetchTexelf(img, i1, j0, 0, t10);
  1132.    }
  1133.    if (useBorderColor & (I0BIT | J1BIT)) {
  1134.       get_border_color(tObj, img, t01);
  1135.    }
  1136.    else {
  1137.       img->FetchTexelf(img, i0, j1, 0, t01);
  1138.    }
  1139.    if (useBorderColor & (I1BIT | J1BIT)) {
  1140.       get_border_color(tObj, img, t11);
  1141.    }
  1142.    else {
  1143.       img->FetchTexelf(img, i1, j1, 0, t11);
  1144.    }
  1145.  
  1146.    lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11);
  1147. }
  1148.  
  1149.  
  1150. /**
  1151.  * As above, but we know WRAP_S == REPEAT and WRAP_T == REPEAT.
  1152.  * We don't have to worry about the texture border.
  1153.  */
  1154. static INLINE void
  1155. sample_2d_linear_repeat(struct gl_context *ctx,
  1156.                         const struct gl_texture_object *tObj,
  1157.                         const struct gl_texture_image *img,
  1158.                         const GLfloat texcoord[4],
  1159.                         GLfloat rgba[])
  1160. {
  1161.    const GLint width = img->Width2;
  1162.    const GLint height = img->Height2;
  1163.    GLint i0, j0, i1, j1;
  1164.    GLfloat wi, wj;
  1165.    GLfloat t00[4], t10[4], t01[4], t11[4]; /* sampled texel colors */
  1166.  
  1167.    (void) ctx;
  1168.  
  1169.    ASSERT(tObj->WrapS == GL_REPEAT);
  1170.    ASSERT(tObj->WrapT == GL_REPEAT);
  1171.    ASSERT(img->Border == 0);
  1172.    ASSERT(img->_BaseFormat != GL_COLOR_INDEX);
  1173.    ASSERT(img->_IsPowerOfTwo);
  1174.  
  1175.    linear_repeat_texel_location(width,  texcoord[0], &i0, &i1, &wi);
  1176.    linear_repeat_texel_location(height, texcoord[1], &j0, &j1, &wj);
  1177.  
  1178.    img->FetchTexelf(img, i0, j0, 0, t00);
  1179.    img->FetchTexelf(img, i1, j0, 0, t10);
  1180.    img->FetchTexelf(img, i0, j1, 0, t01);
  1181.    img->FetchTexelf(img, i1, j1, 0, t11);
  1182.  
  1183.    lerp_rgba_2d(rgba, wi, wj, t00, t10, t01, t11);
  1184. }
  1185.  
  1186.  
  1187. static void
  1188. sample_2d_nearest_mipmap_nearest(struct gl_context *ctx,
  1189.                                  const struct gl_texture_object *tObj,
  1190.                                  GLuint n, const GLfloat texcoord[][4],
  1191.                                  const GLfloat lambda[], GLfloat rgba[][4])
  1192. {
  1193.    GLuint i;
  1194.    for (i = 0; i < n; i++) {
  1195.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  1196.       sample_2d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
  1197.    }
  1198. }
  1199.  
  1200.  
  1201. static void
  1202. sample_2d_linear_mipmap_nearest(struct gl_context *ctx,
  1203.                                 const struct gl_texture_object *tObj,
  1204.                                 GLuint n, const GLfloat texcoord[][4],
  1205.                                 const GLfloat lambda[], GLfloat rgba[][4])
  1206. {
  1207.    GLuint i;
  1208.    ASSERT(lambda != NULL);
  1209.    for (i = 0; i < n; i++) {
  1210.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  1211.       sample_2d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
  1212.    }
  1213. }
  1214.  
  1215.  
  1216. static void
  1217. sample_2d_nearest_mipmap_linear(struct gl_context *ctx,
  1218.                                 const struct gl_texture_object *tObj,
  1219.                                 GLuint n, const GLfloat texcoord[][4],
  1220.                                 const GLfloat lambda[], GLfloat rgba[][4])
  1221. {
  1222.    GLuint i;
  1223.    ASSERT(lambda != NULL);
  1224.    for (i = 0; i < n; i++) {
  1225.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  1226.       if (level >= tObj->_MaxLevel) {
  1227.          sample_2d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  1228.                            texcoord[i], rgba[i]);
  1229.       }
  1230.       else {
  1231.          GLfloat t0[4], t1[4];  /* texels */
  1232.          const GLfloat f = FRAC(lambda[i]);
  1233.          sample_2d_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
  1234.          sample_2d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
  1235.          lerp_rgba(rgba[i], f, t0, t1);
  1236.       }
  1237.    }
  1238. }
  1239.  
  1240.  
  1241. static void
  1242. sample_2d_linear_mipmap_linear( struct gl_context *ctx,
  1243.                                 const struct gl_texture_object *tObj,
  1244.                                 GLuint n, const GLfloat texcoord[][4],
  1245.                                 const GLfloat lambda[], GLfloat rgba[][4] )
  1246. {
  1247.    GLuint i;
  1248.    ASSERT(lambda != NULL);
  1249.    for (i = 0; i < n; i++) {
  1250.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  1251.       if (level >= tObj->_MaxLevel) {
  1252.          sample_2d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  1253.                           texcoord[i], rgba[i]);
  1254.       }
  1255.       else {
  1256.          GLfloat t0[4], t1[4];  /* texels */
  1257.          const GLfloat f = FRAC(lambda[i]);
  1258.          sample_2d_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
  1259.          sample_2d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
  1260.          lerp_rgba(rgba[i], f, t0, t1);
  1261.       }
  1262.    }
  1263. }
  1264.  
  1265.  
  1266. static void
  1267. sample_2d_linear_mipmap_linear_repeat(struct gl_context *ctx,
  1268.                                       const struct gl_texture_object *tObj,
  1269.                                       GLuint n, const GLfloat texcoord[][4],
  1270.                                       const GLfloat lambda[], GLfloat rgba[][4])
  1271. {
  1272.    GLuint i;
  1273.    ASSERT(lambda != NULL);
  1274.    ASSERT(tObj->WrapS == GL_REPEAT);
  1275.    ASSERT(tObj->WrapT == GL_REPEAT);
  1276.    for (i = 0; i < n; i++) {
  1277.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  1278.       if (level >= tObj->_MaxLevel) {
  1279.          sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  1280.                                  texcoord[i], rgba[i]);
  1281.       }
  1282.       else {
  1283.          GLfloat t0[4], t1[4];  /* texels */
  1284.          const GLfloat f = FRAC(lambda[i]);
  1285.          sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level  ],
  1286.                                  texcoord[i], t0);
  1287.          sample_2d_linear_repeat(ctx, tObj, tObj->Image[0][level+1],
  1288.                                  texcoord[i], t1);
  1289.          lerp_rgba(rgba[i], f, t0, t1);
  1290.       }
  1291.    }
  1292. }
  1293.  
  1294.  
  1295. /** Sample 2D texture, nearest filtering for both min/magnification */
  1296. static void
  1297. sample_nearest_2d(struct gl_context *ctx,
  1298.                   const struct gl_texture_object *tObj, GLuint n,
  1299.                   const GLfloat texcoords[][4],
  1300.                   const GLfloat lambda[], GLfloat rgba[][4])
  1301. {
  1302.    GLuint i;
  1303.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  1304.    (void) lambda;
  1305.    for (i = 0; i < n; i++) {
  1306.       sample_2d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
  1307.    }
  1308. }
  1309.  
  1310.  
  1311. /** Sample 2D texture, linear filtering for both min/magnification */
  1312. static void
  1313. sample_linear_2d(struct gl_context *ctx,
  1314.                  const struct gl_texture_object *tObj, GLuint n,
  1315.                  const GLfloat texcoords[][4],
  1316.                  const GLfloat lambda[], GLfloat rgba[][4])
  1317. {
  1318.    GLuint i;
  1319.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  1320.    (void) lambda;
  1321.    if (tObj->WrapS == GL_REPEAT &&
  1322.        tObj->WrapT == GL_REPEAT &&
  1323.        image->_IsPowerOfTwo &&
  1324.        image->Border == 0) {
  1325.       for (i = 0; i < n; i++) {
  1326.          sample_2d_linear_repeat(ctx, tObj, image, texcoords[i], rgba[i]);
  1327.       }
  1328.    }
  1329.    else {
  1330.       for (i = 0; i < n; i++) {
  1331.          sample_2d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
  1332.       }
  1333.    }
  1334. }
  1335.  
  1336.  
  1337. /**
  1338.  * Optimized 2-D texture sampling:
  1339.  *    S and T wrap mode == GL_REPEAT
  1340.  *    GL_NEAREST min/mag filter
  1341.  *    No border,
  1342.  *    RowStride == Width,
  1343.  *    Format = GL_RGB
  1344.  */
  1345. static void
  1346. opt_sample_rgb_2d(struct gl_context *ctx,
  1347.                   const struct gl_texture_object *tObj,
  1348.                   GLuint n, const GLfloat texcoords[][4],
  1349.                   const GLfloat lambda[], GLfloat rgba[][4])
  1350. {
  1351.    const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
  1352.    const GLfloat width = (GLfloat) img->Width;
  1353.    const GLfloat height = (GLfloat) img->Height;
  1354.    const GLint colMask = img->Width - 1;
  1355.    const GLint rowMask = img->Height - 1;
  1356.    const GLint shift = img->WidthLog2;
  1357.    GLuint k;
  1358.    (void) ctx;
  1359.    (void) lambda;
  1360.    ASSERT(tObj->WrapS==GL_REPEAT);
  1361.    ASSERT(tObj->WrapT==GL_REPEAT);
  1362.    ASSERT(img->Border==0);
  1363.    ASSERT(img->TexFormat == MESA_FORMAT_RGB888);
  1364.    ASSERT(img->_IsPowerOfTwo);
  1365.  
  1366.    for (k=0; k<n; k++) {
  1367.       GLint i = IFLOOR(texcoords[k][0] * width) & colMask;
  1368.       GLint j = IFLOOR(texcoords[k][1] * height) & rowMask;
  1369.       GLint pos = (j << shift) | i;
  1370.       GLubyte *texel = ((GLubyte *) img->Data) + 3*pos;
  1371.       rgba[k][RCOMP] = UBYTE_TO_FLOAT(texel[2]);
  1372.       rgba[k][GCOMP] = UBYTE_TO_FLOAT(texel[1]);
  1373.       rgba[k][BCOMP] = UBYTE_TO_FLOAT(texel[0]);
  1374.       rgba[k][ACOMP] = 1.0F;
  1375.    }
  1376. }
  1377.  
  1378.  
  1379. /**
  1380.  * Optimized 2-D texture sampling:
  1381.  *    S and T wrap mode == GL_REPEAT
  1382.  *    GL_NEAREST min/mag filter
  1383.  *    No border
  1384.  *    RowStride == Width,
  1385.  *    Format = GL_RGBA
  1386.  */
  1387. static void
  1388. opt_sample_rgba_2d(struct gl_context *ctx,
  1389.                    const struct gl_texture_object *tObj,
  1390.                    GLuint n, const GLfloat texcoords[][4],
  1391.                    const GLfloat lambda[], GLfloat rgba[][4])
  1392. {
  1393.    const struct gl_texture_image *img = tObj->Image[0][tObj->BaseLevel];
  1394.    const GLfloat width = (GLfloat) img->Width;
  1395.    const GLfloat height = (GLfloat) img->Height;
  1396.    const GLint colMask = img->Width - 1;
  1397.    const GLint rowMask = img->Height - 1;
  1398.    const GLint shift = img->WidthLog2;
  1399.    GLuint i;
  1400.    (void) ctx;
  1401.    (void) lambda;
  1402.    ASSERT(tObj->WrapS==GL_REPEAT);
  1403.    ASSERT(tObj->WrapT==GL_REPEAT);
  1404.    ASSERT(img->Border==0);
  1405.    ASSERT(img->TexFormat == MESA_FORMAT_RGBA8888);
  1406.    ASSERT(img->_IsPowerOfTwo);
  1407.  
  1408.    for (i = 0; i < n; i++) {
  1409.       const GLint col = IFLOOR(texcoords[i][0] * width) & colMask;
  1410.       const GLint row = IFLOOR(texcoords[i][1] * height) & rowMask;
  1411.       const GLint pos = (row << shift) | col;
  1412.       const GLuint texel = *((GLuint *) img->Data + pos);
  1413.       rgba[i][RCOMP] = UBYTE_TO_FLOAT( (texel >> 24)        );
  1414.       rgba[i][GCOMP] = UBYTE_TO_FLOAT( (texel >> 16) & 0xff );
  1415.       rgba[i][BCOMP] = UBYTE_TO_FLOAT( (texel >>  8) & 0xff );
  1416.       rgba[i][ACOMP] = UBYTE_TO_FLOAT( (texel      ) & 0xff );
  1417.    }
  1418. }
  1419.  
  1420.  
  1421. /** Sample 2D texture, using lambda to choose between min/magnification */
  1422. static void
  1423. sample_lambda_2d(struct gl_context *ctx,
  1424.                  const struct gl_texture_object *tObj,
  1425.                  GLuint n, const GLfloat texcoords[][4],
  1426.                  const GLfloat lambda[], GLfloat rgba[][4])
  1427. {
  1428.    const struct gl_texture_image *tImg = tObj->Image[0][tObj->BaseLevel];
  1429.    GLuint minStart, minEnd;  /* texels with minification */
  1430.    GLuint magStart, magEnd;  /* texels with magnification */
  1431.  
  1432.    const GLboolean repeatNoBorderPOT = (tObj->WrapS == GL_REPEAT)
  1433.       && (tObj->WrapT == GL_REPEAT)
  1434.       && (tImg->Border == 0 && (tImg->Width == tImg->RowStride))
  1435.       && (tImg->_BaseFormat != GL_COLOR_INDEX)
  1436.       && tImg->_IsPowerOfTwo;
  1437.  
  1438.    ASSERT(lambda != NULL);
  1439.    compute_min_mag_ranges(tObj, n, lambda,
  1440.                           &minStart, &minEnd, &magStart, &magEnd);
  1441.  
  1442.    if (minStart < minEnd) {
  1443.       /* do the minified texels */
  1444.       const GLuint m = minEnd - minStart;
  1445.       switch (tObj->MinFilter) {
  1446.       case GL_NEAREST:
  1447.          if (repeatNoBorderPOT) {
  1448.             switch (tImg->TexFormat) {
  1449.             case MESA_FORMAT_RGB888:
  1450.                opt_sample_rgb_2d(ctx, tObj, m, texcoords + minStart,
  1451.                                  NULL, rgba + minStart);
  1452.                break;
  1453.             case MESA_FORMAT_RGBA8888:
  1454.                opt_sample_rgba_2d(ctx, tObj, m, texcoords + minStart,
  1455.                                   NULL, rgba + minStart);
  1456.                break;
  1457.             default:
  1458.                sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
  1459.                                  NULL, rgba + minStart );
  1460.             }
  1461.          }
  1462.          else {
  1463.             sample_nearest_2d(ctx, tObj, m, texcoords + minStart,
  1464.                               NULL, rgba + minStart);
  1465.          }
  1466.          break;
  1467.       case GL_LINEAR:
  1468.          sample_linear_2d(ctx, tObj, m, texcoords + minStart,
  1469.                           NULL, rgba + minStart);
  1470.          break;
  1471.       case GL_NEAREST_MIPMAP_NEAREST:
  1472.          sample_2d_nearest_mipmap_nearest(ctx, tObj, m,
  1473.                                           texcoords + minStart,
  1474.                                           lambda + minStart, rgba + minStart);
  1475.          break;
  1476.       case GL_LINEAR_MIPMAP_NEAREST:
  1477.          sample_2d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  1478.                                          lambda + minStart, rgba + minStart);
  1479.          break;
  1480.       case GL_NEAREST_MIPMAP_LINEAR:
  1481.          sample_2d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1482.                                          lambda + minStart, rgba + minStart);
  1483.          break;
  1484.       case GL_LINEAR_MIPMAP_LINEAR:
  1485.          if (repeatNoBorderPOT)
  1486.             sample_2d_linear_mipmap_linear_repeat(ctx, tObj, m,
  1487.                   texcoords + minStart, lambda + minStart, rgba + minStart);
  1488.          else
  1489.             sample_2d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1490.                                         lambda + minStart, rgba + minStart);
  1491.          break;
  1492.       default:
  1493.          _mesa_problem(ctx, "Bad min filter in sample_2d_texture");
  1494.          return;
  1495.       }
  1496.    }
  1497.  
  1498.    if (magStart < magEnd) {
  1499.       /* do the magnified texels */
  1500.       const GLuint m = magEnd - magStart;
  1501.  
  1502.       switch (tObj->MagFilter) {
  1503.       case GL_NEAREST:
  1504.          if (repeatNoBorderPOT) {
  1505.             switch (tImg->TexFormat) {
  1506.             case MESA_FORMAT_RGB888:
  1507.                opt_sample_rgb_2d(ctx, tObj, m, texcoords + magStart,
  1508.                                  NULL, rgba + magStart);
  1509.                break;
  1510.             case MESA_FORMAT_RGBA8888:
  1511.                opt_sample_rgba_2d(ctx, tObj, m, texcoords + magStart,
  1512.                                   NULL, rgba + magStart);
  1513.                break;
  1514.             default:
  1515.                sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
  1516.                                  NULL, rgba + magStart );
  1517.             }
  1518.          }
  1519.          else {
  1520.             sample_nearest_2d(ctx, tObj, m, texcoords + magStart,
  1521.                               NULL, rgba + magStart);
  1522.          }
  1523.          break;
  1524.       case GL_LINEAR:
  1525.          sample_linear_2d(ctx, tObj, m, texcoords + magStart,
  1526.                           NULL, rgba + magStart);
  1527.          break;
  1528.       default:
  1529.          _mesa_problem(ctx, "Bad mag filter in sample_lambda_2d");
  1530.       }
  1531.    }
  1532. }
  1533.  
  1534.  
  1535.  
  1536. /**********************************************************************/
  1537. /*                    3-D Texture Sampling Functions                  */
  1538. /**********************************************************************/
  1539.  
  1540. /**
  1541.  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  1542.  */
  1543. static INLINE void
  1544. sample_3d_nearest(struct gl_context *ctx,
  1545.                   const struct gl_texture_object *tObj,
  1546.                   const struct gl_texture_image *img,
  1547.                   const GLfloat texcoord[4],
  1548.                   GLfloat rgba[4])
  1549. {
  1550.    const GLint width = img->Width2;     /* without border, power of two */
  1551.    const GLint height = img->Height2;   /* without border, power of two */
  1552.    const GLint depth = img->Depth2;     /* without border, power of two */
  1553.    GLint i, j, k;
  1554.    (void) ctx;
  1555.  
  1556.    i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
  1557.    j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]);
  1558.    k = nearest_texel_location(tObj->WrapR, img, depth, texcoord[2]);
  1559.  
  1560.    if (i < 0 || i >= (GLint) img->Width ||
  1561.        j < 0 || j >= (GLint) img->Height ||
  1562.        k < 0 || k >= (GLint) img->Depth) {
  1563.       /* Need this test for GL_CLAMP_TO_BORDER mode */
  1564.       get_border_color(tObj, img, rgba);
  1565.    }
  1566.    else {
  1567.       img->FetchTexelf(img, i, j, k, rgba);
  1568.    }
  1569. }
  1570.  
  1571.  
  1572. /**
  1573.  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  1574.  */
  1575. static void
  1576. sample_3d_linear(struct gl_context *ctx,
  1577.                  const struct gl_texture_object *tObj,
  1578.                  const struct gl_texture_image *img,
  1579.                  const GLfloat texcoord[4],
  1580.                  GLfloat rgba[4])
  1581. {
  1582.    const GLint width = img->Width2;
  1583.    const GLint height = img->Height2;
  1584.    const GLint depth = img->Depth2;
  1585.    GLint i0, j0, k0, i1, j1, k1;
  1586.    GLbitfield useBorderColor = 0x0;
  1587.    GLfloat a, b, c;
  1588.    GLfloat t000[4], t010[4], t001[4], t011[4];
  1589.    GLfloat t100[4], t110[4], t101[4], t111[4];
  1590.  
  1591.    linear_texel_locations(tObj->WrapS, img, width, texcoord[0],  &i0, &i1, &a);
  1592.    linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
  1593.    linear_texel_locations(tObj->WrapR, img, depth, texcoord[2],  &k0, &k1, &c);
  1594.  
  1595.    if (img->Border) {
  1596.       i0 += img->Border;
  1597.       i1 += img->Border;
  1598.       j0 += img->Border;
  1599.       j1 += img->Border;
  1600.       k0 += img->Border;
  1601.       k1 += img->Border;
  1602.    }
  1603.    else {
  1604.       /* check if sampling texture border color */
  1605.       if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
  1606.       if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
  1607.       if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
  1608.       if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
  1609.       if (k0 < 0 || k0 >= depth)   useBorderColor |= K0BIT;
  1610.       if (k1 < 0 || k1 >= depth)   useBorderColor |= K1BIT;
  1611.    }
  1612.  
  1613.    /* Fetch texels */
  1614.    if (useBorderColor & (I0BIT | J0BIT | K0BIT)) {
  1615.       get_border_color(tObj, img, t000);
  1616.    }
  1617.    else {
  1618.       img->FetchTexelf(img, i0, j0, k0, t000);
  1619.    }
  1620.    if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
  1621.       get_border_color(tObj, img, t100);
  1622.    }
  1623.    else {
  1624.       img->FetchTexelf(img, i1, j0, k0, t100);
  1625.    }
  1626.    if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
  1627.       get_border_color(tObj, img, t010);
  1628.    }
  1629.    else {
  1630.       img->FetchTexelf(img, i0, j1, k0, t010);
  1631.    }
  1632.    if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
  1633.       get_border_color(tObj, img, t110);
  1634.    }
  1635.    else {
  1636.       img->FetchTexelf(img, i1, j1, k0, t110);
  1637.    }
  1638.  
  1639.    if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
  1640.       get_border_color(tObj, img, t001);
  1641.    }
  1642.    else {
  1643.       img->FetchTexelf(img, i0, j0, k1, t001);
  1644.    }
  1645.    if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
  1646.       get_border_color(tObj, img, t101);
  1647.    }
  1648.    else {
  1649.       img->FetchTexelf(img, i1, j0, k1, t101);
  1650.    }
  1651.    if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
  1652.       get_border_color(tObj, img, t011);
  1653.    }
  1654.    else {
  1655.       img->FetchTexelf(img, i0, j1, k1, t011);
  1656.    }
  1657.    if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
  1658.       get_border_color(tObj, img, t111);
  1659.    }
  1660.    else {
  1661.       img->FetchTexelf(img, i1, j1, k1, t111);
  1662.    }
  1663.  
  1664.    /* trilinear interpolation of samples */
  1665.    lerp_rgba_3d(rgba, a, b, c, t000, t100, t010, t110, t001, t101, t011, t111);
  1666. }
  1667.  
  1668.  
  1669. static void
  1670. sample_3d_nearest_mipmap_nearest(struct gl_context *ctx,
  1671.                                  const struct gl_texture_object *tObj,
  1672.                                  GLuint n, const GLfloat texcoord[][4],
  1673.                                  const GLfloat lambda[], GLfloat rgba[][4] )
  1674. {
  1675.    GLuint i;
  1676.    for (i = 0; i < n; i++) {
  1677.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  1678.       sample_3d_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
  1679.    }
  1680. }
  1681.  
  1682.  
  1683. static void
  1684. sample_3d_linear_mipmap_nearest(struct gl_context *ctx,
  1685.                                 const struct gl_texture_object *tObj,
  1686.                                 GLuint n, const GLfloat texcoord[][4],
  1687.                                 const GLfloat lambda[], GLfloat rgba[][4])
  1688. {
  1689.    GLuint i;
  1690.    ASSERT(lambda != NULL);
  1691.    for (i = 0; i < n; i++) {
  1692.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  1693.       sample_3d_linear(ctx, tObj, tObj->Image[0][level], texcoord[i], rgba[i]);
  1694.    }
  1695. }
  1696.  
  1697.  
  1698. static void
  1699. sample_3d_nearest_mipmap_linear(struct gl_context *ctx,
  1700.                                 const struct gl_texture_object *tObj,
  1701.                                 GLuint n, const GLfloat texcoord[][4],
  1702.                                 const GLfloat lambda[], GLfloat rgba[][4])
  1703. {
  1704.    GLuint i;
  1705.    ASSERT(lambda != NULL);
  1706.    for (i = 0; i < n; i++) {
  1707.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  1708.       if (level >= tObj->_MaxLevel) {
  1709.          sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  1710.                            texcoord[i], rgba[i]);
  1711.       }
  1712.       else {
  1713.          GLfloat t0[4], t1[4];  /* texels */
  1714.          const GLfloat f = FRAC(lambda[i]);
  1715.          sample_3d_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
  1716.          sample_3d_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
  1717.          lerp_rgba(rgba[i], f, t0, t1);
  1718.       }
  1719.    }
  1720. }
  1721.  
  1722.  
  1723. static void
  1724. sample_3d_linear_mipmap_linear(struct gl_context *ctx,
  1725.                                const struct gl_texture_object *tObj,
  1726.                                GLuint n, const GLfloat texcoord[][4],
  1727.                                const GLfloat lambda[], GLfloat rgba[][4])
  1728. {
  1729.    GLuint i;
  1730.    ASSERT(lambda != NULL);
  1731.    for (i = 0; i < n; i++) {
  1732.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  1733.       if (level >= tObj->_MaxLevel) {
  1734.          sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  1735.                           texcoord[i], rgba[i]);
  1736.       }
  1737.       else {
  1738.          GLfloat t0[4], t1[4];  /* texels */
  1739.          const GLfloat f = FRAC(lambda[i]);
  1740.          sample_3d_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
  1741.          sample_3d_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
  1742.          lerp_rgba(rgba[i], f, t0, t1);
  1743.       }
  1744.    }
  1745. }
  1746.  
  1747.  
  1748. /** Sample 3D texture, nearest filtering for both min/magnification */
  1749. static void
  1750. sample_nearest_3d(struct gl_context *ctx,
  1751.                   const struct gl_texture_object *tObj, GLuint n,
  1752.                   const GLfloat texcoords[][4], const GLfloat lambda[],
  1753.                   GLfloat rgba[][4])
  1754. {
  1755.    GLuint i;
  1756.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  1757.    (void) lambda;
  1758.    for (i = 0; i < n; i++) {
  1759.       sample_3d_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
  1760.    }
  1761. }
  1762.  
  1763.  
  1764. /** Sample 3D texture, linear filtering for both min/magnification */
  1765. static void
  1766. sample_linear_3d(struct gl_context *ctx,
  1767.                  const struct gl_texture_object *tObj, GLuint n,
  1768.                  const GLfloat texcoords[][4],
  1769.                  const GLfloat lambda[], GLfloat rgba[][4])
  1770. {
  1771.    GLuint i;
  1772.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  1773.    (void) lambda;
  1774.    for (i = 0; i < n; i++) {
  1775.       sample_3d_linear(ctx, tObj, image, texcoords[i], rgba[i]);
  1776.    }
  1777. }
  1778.  
  1779.  
  1780. /** Sample 3D texture, using lambda to choose between min/magnification */
  1781. static void
  1782. sample_lambda_3d(struct gl_context *ctx,
  1783.                  const struct gl_texture_object *tObj, GLuint n,
  1784.                  const GLfloat texcoords[][4], const GLfloat lambda[],
  1785.                  GLfloat rgba[][4])
  1786. {
  1787.    GLuint minStart, minEnd;  /* texels with minification */
  1788.    GLuint magStart, magEnd;  /* texels with magnification */
  1789.    GLuint i;
  1790.  
  1791.    ASSERT(lambda != NULL);
  1792.    compute_min_mag_ranges(tObj, n, lambda,
  1793.                           &minStart, &minEnd, &magStart, &magEnd);
  1794.  
  1795.    if (minStart < minEnd) {
  1796.       /* do the minified texels */
  1797.       GLuint m = minEnd - minStart;
  1798.       switch (tObj->MinFilter) {
  1799.       case GL_NEAREST:
  1800.          for (i = minStart; i < minEnd; i++)
  1801.             sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  1802.                               texcoords[i], rgba[i]);
  1803.          break;
  1804.       case GL_LINEAR:
  1805.          for (i = minStart; i < minEnd; i++)
  1806.             sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  1807.                              texcoords[i], rgba[i]);
  1808.          break;
  1809.       case GL_NEAREST_MIPMAP_NEAREST:
  1810.          sample_3d_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  1811.                                           lambda + minStart, rgba + minStart);
  1812.          break;
  1813.       case GL_LINEAR_MIPMAP_NEAREST:
  1814.          sample_3d_linear_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  1815.                                          lambda + minStart, rgba + minStart);
  1816.          break;
  1817.       case GL_NEAREST_MIPMAP_LINEAR:
  1818.          sample_3d_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1819.                                          lambda + minStart, rgba + minStart);
  1820.          break;
  1821.       case GL_LINEAR_MIPMAP_LINEAR:
  1822.          sample_3d_linear_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  1823.                                         lambda + minStart, rgba + minStart);
  1824.          break;
  1825.       default:
  1826.          _mesa_problem(ctx, "Bad min filter in sample_3d_texture");
  1827.          return;
  1828.       }
  1829.    }
  1830.  
  1831.    if (magStart < magEnd) {
  1832.       /* do the magnified texels */
  1833.       switch (tObj->MagFilter) {
  1834.       case GL_NEAREST:
  1835.          for (i = magStart; i < magEnd; i++)
  1836.             sample_3d_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  1837.                               texcoords[i], rgba[i]);
  1838.          break;
  1839.       case GL_LINEAR:
  1840.          for (i = magStart; i < magEnd; i++)
  1841.             sample_3d_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  1842.                              texcoords[i], rgba[i]);
  1843.          break;
  1844.       default:
  1845.          _mesa_problem(ctx, "Bad mag filter in sample_3d_texture");
  1846.          return;
  1847.       }
  1848.    }
  1849. }
  1850.  
  1851.  
  1852. /**********************************************************************/
  1853. /*                Texture Cube Map Sampling Functions                 */
  1854. /**********************************************************************/
  1855.  
  1856. /**
  1857.  * Choose one of six sides of a texture cube map given the texture
  1858.  * coord (rx,ry,rz).  Return pointer to corresponding array of texture
  1859.  * images.
  1860.  */
  1861. static const struct gl_texture_image **
  1862. choose_cube_face(const struct gl_texture_object *texObj,
  1863.                  const GLfloat texcoord[4], GLfloat newCoord[4])
  1864. {
  1865.    /*
  1866.       major axis
  1867.       direction     target                             sc     tc    ma
  1868.       ----------    -------------------------------    ---    ---   ---
  1869.        +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
  1870.        -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
  1871.        +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
  1872.        -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
  1873.        +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
  1874.        -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
  1875.    */
  1876.    const GLfloat rx = texcoord[0];
  1877.    const GLfloat ry = texcoord[1];
  1878.    const GLfloat rz = texcoord[2];
  1879.    const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz);
  1880.    GLuint face;
  1881.    GLfloat sc, tc, ma;
  1882.  
  1883.    if (arx >= ary && arx >= arz) {
  1884.       if (rx >= 0.0F) {
  1885.          face = FACE_POS_X;
  1886.          sc = -rz;
  1887.          tc = -ry;
  1888.          ma = arx;
  1889.       }
  1890.       else {
  1891.          face = FACE_NEG_X;
  1892.          sc = rz;
  1893.          tc = -ry;
  1894.          ma = arx;
  1895.       }
  1896.    }
  1897.    else if (ary >= arx && ary >= arz) {
  1898.       if (ry >= 0.0F) {
  1899.          face = FACE_POS_Y;
  1900.          sc = rx;
  1901.          tc = rz;
  1902.          ma = ary;
  1903.       }
  1904.       else {
  1905.          face = FACE_NEG_Y;
  1906.          sc = rx;
  1907.          tc = -rz;
  1908.          ma = ary;
  1909.       }
  1910.    }
  1911.    else {
  1912.       if (rz > 0.0F) {
  1913.          face = FACE_POS_Z;
  1914.          sc = rx;
  1915.          tc = -ry;
  1916.          ma = arz;
  1917.       }
  1918.       else {
  1919.          face = FACE_NEG_Z;
  1920.          sc = -rx;
  1921.          tc = -ry;
  1922.          ma = arz;
  1923.       }
  1924.    }
  1925.  
  1926.    {
  1927.       const float ima = 1.0F / ma;
  1928.       newCoord[0] = ( sc * ima + 1.0F ) * 0.5F;
  1929.       newCoord[1] = ( tc * ima + 1.0F ) * 0.5F;
  1930.    }
  1931.  
  1932.    return (const struct gl_texture_image **) texObj->Image[face];
  1933. }
  1934.  
  1935.  
  1936. static void
  1937. sample_nearest_cube(struct gl_context *ctx,
  1938.                     const struct gl_texture_object *tObj, GLuint n,
  1939.                     const GLfloat texcoords[][4], const GLfloat lambda[],
  1940.                     GLfloat rgba[][4])
  1941. {
  1942.    GLuint i;
  1943.    (void) lambda;
  1944.    for (i = 0; i < n; i++) {
  1945.       const struct gl_texture_image **images;
  1946.       GLfloat newCoord[4];
  1947.       images = choose_cube_face(tObj, texcoords[i], newCoord);
  1948.       sample_2d_nearest(ctx, tObj, images[tObj->BaseLevel],
  1949.                         newCoord, rgba[i]);
  1950.    }
  1951. }
  1952.  
  1953.  
  1954. static void
  1955. sample_linear_cube(struct gl_context *ctx,
  1956.                    const struct gl_texture_object *tObj, GLuint n,
  1957.                    const GLfloat texcoords[][4],
  1958.                    const GLfloat lambda[], GLfloat rgba[][4])
  1959. {
  1960.    GLuint i;
  1961.    (void) lambda;
  1962.    for (i = 0; i < n; i++) {
  1963.       const struct gl_texture_image **images;
  1964.       GLfloat newCoord[4];
  1965.       images = choose_cube_face(tObj, texcoords[i], newCoord);
  1966.       sample_2d_linear(ctx, tObj, images[tObj->BaseLevel],
  1967.                        newCoord, rgba[i]);
  1968.    }
  1969. }
  1970.  
  1971.  
  1972. static void
  1973. sample_cube_nearest_mipmap_nearest(struct gl_context *ctx,
  1974.                                    const struct gl_texture_object *tObj,
  1975.                                    GLuint n, const GLfloat texcoord[][4],
  1976.                                    const GLfloat lambda[], GLfloat rgba[][4])
  1977. {
  1978.    GLuint i;
  1979.    ASSERT(lambda != NULL);
  1980.    for (i = 0; i < n; i++) {
  1981.       const struct gl_texture_image **images;
  1982.       GLfloat newCoord[4];
  1983.       GLint level;
  1984.       images = choose_cube_face(tObj, texcoord[i], newCoord);
  1985.  
  1986.       /* XXX we actually need to recompute lambda here based on the newCoords.
  1987.        * But we would need the texcoords of adjacent fragments to compute that
  1988.        * properly, and we don't have those here.
  1989.        * For now, do an approximation:  subtracting 1 from the chosen mipmap
  1990.        * level seems to work in some test cases.
  1991.        * The same adjustment is done in the next few functions.
  1992.       */
  1993.       level = nearest_mipmap_level(tObj, lambda[i]);
  1994.       level = MAX2(level - 1, 0);
  1995.  
  1996.       sample_2d_nearest(ctx, tObj, images[level], newCoord, rgba[i]);
  1997.    }
  1998. }
  1999.  
  2000.  
  2001. static void
  2002. sample_cube_linear_mipmap_nearest(struct gl_context *ctx,
  2003.                                   const struct gl_texture_object *tObj,
  2004.                                   GLuint n, const GLfloat texcoord[][4],
  2005.                                   const GLfloat lambda[], GLfloat rgba[][4])
  2006. {
  2007.    GLuint i;
  2008.    ASSERT(lambda != NULL);
  2009.    for (i = 0; i < n; i++) {
  2010.       const struct gl_texture_image **images;
  2011.       GLfloat newCoord[4];
  2012.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  2013.       level = MAX2(level - 1, 0); /* see comment above */
  2014.       images = choose_cube_face(tObj, texcoord[i], newCoord);
  2015.       sample_2d_linear(ctx, tObj, images[level], newCoord, rgba[i]);
  2016.    }
  2017. }
  2018.  
  2019.  
  2020. static void
  2021. sample_cube_nearest_mipmap_linear(struct gl_context *ctx,
  2022.                                   const struct gl_texture_object *tObj,
  2023.                                   GLuint n, const GLfloat texcoord[][4],
  2024.                                   const GLfloat lambda[], GLfloat rgba[][4])
  2025. {
  2026.    GLuint i;
  2027.    ASSERT(lambda != NULL);
  2028.    for (i = 0; i < n; i++) {
  2029.       const struct gl_texture_image **images;
  2030.       GLfloat newCoord[4];
  2031.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  2032.       level = MAX2(level - 1, 0); /* see comment above */
  2033.       images = choose_cube_face(tObj, texcoord[i], newCoord);
  2034.       if (level >= tObj->_MaxLevel) {
  2035.          sample_2d_nearest(ctx, tObj, images[tObj->_MaxLevel],
  2036.                            newCoord, rgba[i]);
  2037.       }
  2038.       else {
  2039.          GLfloat t0[4], t1[4];  /* texels */
  2040.          const GLfloat f = FRAC(lambda[i]);
  2041.          sample_2d_nearest(ctx, tObj, images[level  ], newCoord, t0);
  2042.          sample_2d_nearest(ctx, tObj, images[level+1], newCoord, t1);
  2043.          lerp_rgba(rgba[i], f, t0, t1);
  2044.       }
  2045.    }
  2046. }
  2047.  
  2048.  
  2049. static void
  2050. sample_cube_linear_mipmap_linear(struct gl_context *ctx,
  2051.                                  const struct gl_texture_object *tObj,
  2052.                                  GLuint n, const GLfloat texcoord[][4],
  2053.                                  const GLfloat lambda[], GLfloat rgba[][4])
  2054. {
  2055.    GLuint i;
  2056.    ASSERT(lambda != NULL);
  2057.    for (i = 0; i < n; i++) {
  2058.       const struct gl_texture_image **images;
  2059.       GLfloat newCoord[4];
  2060.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  2061.       level = MAX2(level - 1, 0); /* see comment above */
  2062.       images = choose_cube_face(tObj, texcoord[i], newCoord);
  2063.       if (level >= tObj->_MaxLevel) {
  2064.          sample_2d_linear(ctx, tObj, images[tObj->_MaxLevel],
  2065.                           newCoord, rgba[i]);
  2066.       }
  2067.       else {
  2068.          GLfloat t0[4], t1[4];
  2069.          const GLfloat f = FRAC(lambda[i]);
  2070.          sample_2d_linear(ctx, tObj, images[level  ], newCoord, t0);
  2071.          sample_2d_linear(ctx, tObj, images[level+1], newCoord, t1);
  2072.          lerp_rgba(rgba[i], f, t0, t1);
  2073.       }
  2074.    }
  2075. }
  2076.  
  2077.  
  2078. /** Sample cube texture, using lambda to choose between min/magnification */
  2079. static void
  2080. sample_lambda_cube(struct gl_context *ctx,
  2081.                    const struct gl_texture_object *tObj, GLuint n,
  2082.                    const GLfloat texcoords[][4], const GLfloat lambda[],
  2083.                    GLfloat rgba[][4])
  2084. {
  2085.    GLuint minStart, minEnd;  /* texels with minification */
  2086.    GLuint magStart, magEnd;  /* texels with magnification */
  2087.  
  2088.    ASSERT(lambda != NULL);
  2089.    compute_min_mag_ranges(tObj, n, lambda,
  2090.                           &minStart, &minEnd, &magStart, &magEnd);
  2091.  
  2092.    if (minStart < minEnd) {
  2093.       /* do the minified texels */
  2094.       const GLuint m = minEnd - minStart;
  2095.       switch (tObj->MinFilter) {
  2096.       case GL_NEAREST:
  2097.          sample_nearest_cube(ctx, tObj, m, texcoords + minStart,
  2098.                              lambda + minStart, rgba + minStart);
  2099.          break;
  2100.       case GL_LINEAR:
  2101.          sample_linear_cube(ctx, tObj, m, texcoords + minStart,
  2102.                             lambda + minStart, rgba + minStart);
  2103.          break;
  2104.       case GL_NEAREST_MIPMAP_NEAREST:
  2105.          sample_cube_nearest_mipmap_nearest(ctx, tObj, m,
  2106.                                             texcoords + minStart,
  2107.                                            lambda + minStart, rgba + minStart);
  2108.          break;
  2109.       case GL_LINEAR_MIPMAP_NEAREST:
  2110.          sample_cube_linear_mipmap_nearest(ctx, tObj, m,
  2111.                                            texcoords + minStart,
  2112.                                            lambda + minStart, rgba + minStart);
  2113.          break;
  2114.       case GL_NEAREST_MIPMAP_LINEAR:
  2115.          sample_cube_nearest_mipmap_linear(ctx, tObj, m,
  2116.                                            texcoords + minStart,
  2117.                                            lambda + minStart, rgba + minStart);
  2118.          break;
  2119.       case GL_LINEAR_MIPMAP_LINEAR:
  2120.          sample_cube_linear_mipmap_linear(ctx, tObj, m,
  2121.                                           texcoords + minStart,
  2122.                                           lambda + minStart, rgba + minStart);
  2123.          break;
  2124.       default:
  2125.          _mesa_problem(ctx, "Bad min filter in sample_lambda_cube");
  2126.       }
  2127.    }
  2128.  
  2129.    if (magStart < magEnd) {
  2130.       /* do the magnified texels */
  2131.       const GLuint m = magEnd - magStart;
  2132.       switch (tObj->MagFilter) {
  2133.       case GL_NEAREST:
  2134.          sample_nearest_cube(ctx, tObj, m, texcoords + magStart,
  2135.                              lambda + magStart, rgba + magStart);
  2136.          break;
  2137.       case GL_LINEAR:
  2138.          sample_linear_cube(ctx, tObj, m, texcoords + magStart,
  2139.                             lambda + magStart, rgba + magStart);
  2140.          break;
  2141.       default:
  2142.          _mesa_problem(ctx, "Bad mag filter in sample_lambda_cube");
  2143.       }
  2144.    }
  2145. }
  2146.  
  2147.  
  2148. /**********************************************************************/
  2149. /*               Texture Rectangle Sampling Functions                 */
  2150. /**********************************************************************/
  2151.  
  2152.  
  2153. static void
  2154. sample_nearest_rect(struct gl_context *ctx,
  2155.                     const struct gl_texture_object *tObj, GLuint n,
  2156.                     const GLfloat texcoords[][4], const GLfloat lambda[],
  2157.                     GLfloat rgba[][4])
  2158. {
  2159.    const struct gl_texture_image *img = tObj->Image[0][0];
  2160.    const GLint width = img->Width;
  2161.    const GLint height = img->Height;
  2162.    GLuint i;
  2163.  
  2164.    (void) ctx;
  2165.    (void) lambda;
  2166.  
  2167.    ASSERT(tObj->WrapS == GL_CLAMP ||
  2168.           tObj->WrapS == GL_CLAMP_TO_EDGE ||
  2169.           tObj->WrapS == GL_CLAMP_TO_BORDER);
  2170.    ASSERT(tObj->WrapT == GL_CLAMP ||
  2171.           tObj->WrapT == GL_CLAMP_TO_EDGE ||
  2172.           tObj->WrapT == GL_CLAMP_TO_BORDER);
  2173.    ASSERT(img->_BaseFormat != GL_COLOR_INDEX);
  2174.  
  2175.    for (i = 0; i < n; i++) {
  2176.       GLint row, col;
  2177.       col = clamp_rect_coord_nearest(tObj->WrapS, texcoords[i][0], width);
  2178.       row = clamp_rect_coord_nearest(tObj->WrapT, texcoords[i][1], height);
  2179.       if (col < 0 || col >= width || row < 0 || row >= height)
  2180.          get_border_color(tObj, img, rgba[i]);
  2181.       else
  2182.          img->FetchTexelf(img, col, row, 0, rgba[i]);
  2183.    }
  2184. }
  2185.  
  2186.  
  2187. static void
  2188. sample_linear_rect(struct gl_context *ctx,
  2189.                    const struct gl_texture_object *tObj, GLuint n,
  2190.                    const GLfloat texcoords[][4],
  2191.                    const GLfloat lambda[], GLfloat rgba[][4])
  2192. {
  2193.    const struct gl_texture_image *img = tObj->Image[0][0];
  2194.    const GLint width = img->Width;
  2195.    const GLint height = img->Height;
  2196.    GLuint i;
  2197.  
  2198.    (void) ctx;
  2199.    (void) lambda;
  2200.  
  2201.    ASSERT(tObj->WrapS == GL_CLAMP ||
  2202.           tObj->WrapS == GL_CLAMP_TO_EDGE ||
  2203.           tObj->WrapS == GL_CLAMP_TO_BORDER);
  2204.    ASSERT(tObj->WrapT == GL_CLAMP ||
  2205.           tObj->WrapT == GL_CLAMP_TO_EDGE ||
  2206.           tObj->WrapT == GL_CLAMP_TO_BORDER);
  2207.    ASSERT(img->_BaseFormat != GL_COLOR_INDEX);
  2208.  
  2209.    for (i = 0; i < n; i++) {
  2210.       GLint i0, j0, i1, j1;
  2211.       GLfloat t00[4], t01[4], t10[4], t11[4];
  2212.       GLfloat a, b;
  2213.       GLbitfield useBorderColor = 0x0;
  2214.  
  2215.       clamp_rect_coord_linear(tObj->WrapS, texcoords[i][0], width,
  2216.                               &i0, &i1, &a);
  2217.       clamp_rect_coord_linear(tObj->WrapT, texcoords[i][1], height,
  2218.                               &j0, &j1, &b);
  2219.  
  2220.       /* compute integer rows/columns */
  2221.       if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
  2222.       if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
  2223.       if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
  2224.       if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
  2225.  
  2226.       /* get four texel samples */
  2227.       if (useBorderColor & (I0BIT | J0BIT))
  2228.          get_border_color(tObj, img, t00);
  2229.       else
  2230.          img->FetchTexelf(img, i0, j0, 0, t00);
  2231.  
  2232.       if (useBorderColor & (I1BIT | J0BIT))
  2233.          get_border_color(tObj, img, t10);
  2234.       else
  2235.          img->FetchTexelf(img, i1, j0, 0, t10);
  2236.  
  2237.       if (useBorderColor & (I0BIT | J1BIT))
  2238.          get_border_color(tObj, img, t01);
  2239.       else
  2240.          img->FetchTexelf(img, i0, j1, 0, t01);
  2241.  
  2242.       if (useBorderColor & (I1BIT | J1BIT))
  2243.          get_border_color(tObj, img, t11);
  2244.       else
  2245.          img->FetchTexelf(img, i1, j1, 0, t11);
  2246.  
  2247.       lerp_rgba_2d(rgba[i], a, b, t00, t10, t01, t11);
  2248.    }
  2249. }
  2250.  
  2251.  
  2252. /** Sample Rect texture, using lambda to choose between min/magnification */
  2253. static void
  2254. sample_lambda_rect(struct gl_context *ctx,
  2255.                    const struct gl_texture_object *tObj, GLuint n,
  2256.                    const GLfloat texcoords[][4], const GLfloat lambda[],
  2257.                    GLfloat rgba[][4])
  2258. {
  2259.    GLuint minStart, minEnd, magStart, magEnd;
  2260.  
  2261.    /* We only need lambda to decide between minification and magnification.
  2262.     * There is no mipmapping with rectangular textures.
  2263.     */
  2264.    compute_min_mag_ranges(tObj, n, lambda,
  2265.                           &minStart, &minEnd, &magStart, &magEnd);
  2266.  
  2267.    if (minStart < minEnd) {
  2268.       if (tObj->MinFilter == GL_NEAREST) {
  2269.          sample_nearest_rect(ctx, tObj, minEnd - minStart,
  2270.                              texcoords + minStart, NULL, rgba + minStart);
  2271.       }
  2272.       else {
  2273.          sample_linear_rect(ctx, tObj, minEnd - minStart,
  2274.                             texcoords + minStart, NULL, rgba + minStart);
  2275.       }
  2276.    }
  2277.    if (magStart < magEnd) {
  2278.       if (tObj->MagFilter == GL_NEAREST) {
  2279.          sample_nearest_rect(ctx, tObj, magEnd - magStart,
  2280.                              texcoords + magStart, NULL, rgba + magStart);
  2281.       }
  2282.       else {
  2283.          sample_linear_rect(ctx, tObj, magEnd - magStart,
  2284.                             texcoords + magStart, NULL, rgba + magStart);
  2285.       }
  2286.    }
  2287. }
  2288.  
  2289.  
  2290. /**********************************************************************/
  2291. /*                2D Texture Array Sampling Functions                 */
  2292. /**********************************************************************/
  2293.  
  2294. /**
  2295.  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  2296.  */
  2297. static void
  2298. sample_2d_array_nearest(struct gl_context *ctx,
  2299.                         const struct gl_texture_object *tObj,
  2300.                         const struct gl_texture_image *img,
  2301.                         const GLfloat texcoord[4],
  2302.                         GLfloat rgba[4])
  2303. {
  2304.    const GLint width = img->Width2;     /* without border, power of two */
  2305.    const GLint height = img->Height2;   /* without border, power of two */
  2306.    const GLint depth = img->Depth;
  2307.    GLint i, j;
  2308.    GLint array;
  2309.    (void) ctx;
  2310.  
  2311.    i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
  2312.    j = nearest_texel_location(tObj->WrapT, img, height, texcoord[1]);
  2313.    array = tex_array_slice(texcoord[2], depth);
  2314.  
  2315.    if (i < 0 || i >= (GLint) img->Width ||
  2316.        j < 0 || j >= (GLint) img->Height ||
  2317.        array < 0 || array >= (GLint) img->Depth) {
  2318.       /* Need this test for GL_CLAMP_TO_BORDER mode */
  2319.       get_border_color(tObj, img, rgba);
  2320.    }
  2321.    else {
  2322.       img->FetchTexelf(img, i, j, array, rgba);
  2323.    }
  2324. }
  2325.  
  2326.  
  2327. /**
  2328.  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  2329.  */
  2330. static void
  2331. sample_2d_array_linear(struct gl_context *ctx,
  2332.                        const struct gl_texture_object *tObj,
  2333.                        const struct gl_texture_image *img,
  2334.                        const GLfloat texcoord[4],
  2335.                        GLfloat rgba[4])
  2336. {
  2337.    const GLint width = img->Width2;
  2338.    const GLint height = img->Height2;
  2339.    const GLint depth = img->Depth;
  2340.    GLint i0, j0, i1, j1;
  2341.    GLint array;
  2342.    GLbitfield useBorderColor = 0x0;
  2343.    GLfloat a, b;
  2344.    GLfloat t00[4], t01[4], t10[4], t11[4];
  2345.  
  2346.    linear_texel_locations(tObj->WrapS, img, width,  texcoord[0], &i0, &i1, &a);
  2347.    linear_texel_locations(tObj->WrapT, img, height, texcoord[1], &j0, &j1, &b);
  2348.    array = tex_array_slice(texcoord[2], depth);
  2349.  
  2350.    if (array < 0 || array >= depth) {
  2351.       COPY_4V(rgba, tObj->BorderColor.f);
  2352.    }
  2353.    else {
  2354.       if (img->Border) {
  2355.          i0 += img->Border;
  2356.          i1 += img->Border;
  2357.          j0 += img->Border;
  2358.          j1 += img->Border;
  2359.       }
  2360.       else {
  2361.          /* check if sampling texture border color */
  2362.          if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
  2363.          if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
  2364.          if (j0 < 0 || j0 >= height)  useBorderColor |= J0BIT;
  2365.          if (j1 < 0 || j1 >= height)  useBorderColor |= J1BIT;
  2366.       }
  2367.  
  2368.       /* Fetch texels */
  2369.       if (useBorderColor & (I0BIT | J0BIT)) {
  2370.          get_border_color(tObj, img, t00);
  2371.       }
  2372.       else {
  2373.          img->FetchTexelf(img, i0, j0, array, t00);
  2374.       }
  2375.       if (useBorderColor & (I1BIT | J0BIT)) {
  2376.          get_border_color(tObj, img, t10);
  2377.       }
  2378.       else {
  2379.          img->FetchTexelf(img, i1, j0, array, t10);
  2380.       }
  2381.       if (useBorderColor & (I0BIT | J1BIT)) {
  2382.          get_border_color(tObj, img, t01);
  2383.       }
  2384.       else {
  2385.          img->FetchTexelf(img, i0, j1, array, t01);
  2386.       }
  2387.       if (useBorderColor & (I1BIT | J1BIT)) {
  2388.          get_border_color(tObj, img, t11);
  2389.       }
  2390.       else {
  2391.          img->FetchTexelf(img, i1, j1, array, t11);
  2392.       }
  2393.      
  2394.       /* trilinear interpolation of samples */
  2395.       lerp_rgba_2d(rgba, a, b, t00, t10, t01, t11);
  2396.    }
  2397. }
  2398.  
  2399.  
  2400. static void
  2401. sample_2d_array_nearest_mipmap_nearest(struct gl_context *ctx,
  2402.                                        const struct gl_texture_object *tObj,
  2403.                                        GLuint n, const GLfloat texcoord[][4],
  2404.                                        const GLfloat lambda[], GLfloat rgba[][4])
  2405. {
  2406.    GLuint i;
  2407.    for (i = 0; i < n; i++) {
  2408.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  2409.       sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
  2410.                               rgba[i]);
  2411.    }
  2412. }
  2413.  
  2414.  
  2415. static void
  2416. sample_2d_array_linear_mipmap_nearest(struct gl_context *ctx,
  2417.                                       const struct gl_texture_object *tObj,
  2418.                                       GLuint n, const GLfloat texcoord[][4],
  2419.                                       const GLfloat lambda[], GLfloat rgba[][4])
  2420. {
  2421.    GLuint i;
  2422.    ASSERT(lambda != NULL);
  2423.    for (i = 0; i < n; i++) {
  2424.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  2425.       sample_2d_array_linear(ctx, tObj, tObj->Image[0][level],
  2426.                              texcoord[i], rgba[i]);
  2427.    }
  2428. }
  2429.  
  2430.  
  2431. static void
  2432. sample_2d_array_nearest_mipmap_linear(struct gl_context *ctx,
  2433.                                       const struct gl_texture_object *tObj,
  2434.                                       GLuint n, const GLfloat texcoord[][4],
  2435.                                       const GLfloat lambda[], GLfloat rgba[][4])
  2436. {
  2437.    GLuint i;
  2438.    ASSERT(lambda != NULL);
  2439.    for (i = 0; i < n; i++) {
  2440.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  2441.       if (level >= tObj->_MaxLevel) {
  2442.          sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  2443.                                  texcoord[i], rgba[i]);
  2444.       }
  2445.       else {
  2446.          GLfloat t0[4], t1[4];  /* texels */
  2447.          const GLfloat f = FRAC(lambda[i]);
  2448.          sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level  ],
  2449.                                  texcoord[i], t0);
  2450.          sample_2d_array_nearest(ctx, tObj, tObj->Image[0][level+1],
  2451.                                  texcoord[i], t1);
  2452.          lerp_rgba(rgba[i], f, t0, t1);
  2453.       }
  2454.    }
  2455. }
  2456.  
  2457.  
  2458. static void
  2459. sample_2d_array_linear_mipmap_linear(struct gl_context *ctx,
  2460.                                      const struct gl_texture_object *tObj,
  2461.                                      GLuint n, const GLfloat texcoord[][4],
  2462.                                      const GLfloat lambda[], GLfloat rgba[][4])
  2463. {
  2464.    GLuint i;
  2465.    ASSERT(lambda != NULL);
  2466.    for (i = 0; i < n; i++) {
  2467.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  2468.       if (level >= tObj->_MaxLevel) {
  2469.          sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  2470.                           texcoord[i], rgba[i]);
  2471.       }
  2472.       else {
  2473.          GLfloat t0[4], t1[4];  /* texels */
  2474.          const GLfloat f = FRAC(lambda[i]);
  2475.          sample_2d_array_linear(ctx, tObj, tObj->Image[0][level  ],
  2476.                                 texcoord[i], t0);
  2477.          sample_2d_array_linear(ctx, tObj, tObj->Image[0][level+1],
  2478.                                 texcoord[i], t1);
  2479.          lerp_rgba(rgba[i], f, t0, t1);
  2480.       }
  2481.    }
  2482. }
  2483.  
  2484.  
  2485. /** Sample 2D Array texture, nearest filtering for both min/magnification */
  2486. static void
  2487. sample_nearest_2d_array(struct gl_context *ctx,
  2488.                         const struct gl_texture_object *tObj, GLuint n,
  2489.                         const GLfloat texcoords[][4], const GLfloat lambda[],
  2490.                         GLfloat rgba[][4])
  2491. {
  2492.    GLuint i;
  2493.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  2494.    (void) lambda;
  2495.    for (i = 0; i < n; i++) {
  2496.       sample_2d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
  2497.    }
  2498. }
  2499.  
  2500.  
  2501.  
  2502. /** Sample 2D Array texture, linear filtering for both min/magnification */
  2503. static void
  2504. sample_linear_2d_array(struct gl_context *ctx,
  2505.                        const struct gl_texture_object *tObj, GLuint n,
  2506.                        const GLfloat texcoords[][4],
  2507.                        const GLfloat lambda[], GLfloat rgba[][4])
  2508. {
  2509.    GLuint i;
  2510.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  2511.    (void) lambda;
  2512.    for (i = 0; i < n; i++) {
  2513.       sample_2d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
  2514.    }
  2515. }
  2516.  
  2517.  
  2518. /** Sample 2D Array texture, using lambda to choose between min/magnification */
  2519. static void
  2520. sample_lambda_2d_array(struct gl_context *ctx,
  2521.                        const struct gl_texture_object *tObj, GLuint n,
  2522.                        const GLfloat texcoords[][4], const GLfloat lambda[],
  2523.                        GLfloat rgba[][4])
  2524. {
  2525.    GLuint minStart, minEnd;  /* texels with minification */
  2526.    GLuint magStart, magEnd;  /* texels with magnification */
  2527.    GLuint i;
  2528.  
  2529.    ASSERT(lambda != NULL);
  2530.    compute_min_mag_ranges(tObj, n, lambda,
  2531.                           &minStart, &minEnd, &magStart, &magEnd);
  2532.  
  2533.    if (minStart < minEnd) {
  2534.       /* do the minified texels */
  2535.       GLuint m = minEnd - minStart;
  2536.       switch (tObj->MinFilter) {
  2537.       case GL_NEAREST:
  2538.          for (i = minStart; i < minEnd; i++)
  2539.             sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  2540.                                     texcoords[i], rgba[i]);
  2541.          break;
  2542.       case GL_LINEAR:
  2543.          for (i = minStart; i < minEnd; i++)
  2544.             sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  2545.                                    texcoords[i], rgba[i]);
  2546.          break;
  2547.       case GL_NEAREST_MIPMAP_NEAREST:
  2548.          sample_2d_array_nearest_mipmap_nearest(ctx, tObj, m,
  2549.                                                 texcoords + minStart,
  2550.                                                 lambda + minStart,
  2551.                                                 rgba + minStart);
  2552.          break;
  2553.       case GL_LINEAR_MIPMAP_NEAREST:
  2554.          sample_2d_array_linear_mipmap_nearest(ctx, tObj, m,
  2555.                                                texcoords + minStart,
  2556.                                                lambda + minStart,
  2557.                                                rgba + minStart);
  2558.          break;
  2559.       case GL_NEAREST_MIPMAP_LINEAR:
  2560.          sample_2d_array_nearest_mipmap_linear(ctx, tObj, m,
  2561.                                                texcoords + minStart,
  2562.                                                lambda + minStart,
  2563.                                                rgba + minStart);
  2564.          break;
  2565.       case GL_LINEAR_MIPMAP_LINEAR:
  2566.          sample_2d_array_linear_mipmap_linear(ctx, tObj, m,
  2567.                                               texcoords + minStart,
  2568.                                               lambda + minStart,
  2569.                                               rgba + minStart);
  2570.          break;
  2571.       default:
  2572.          _mesa_problem(ctx, "Bad min filter in sample_2d_array_texture");
  2573.          return;
  2574.       }
  2575.    }
  2576.  
  2577.    if (magStart < magEnd) {
  2578.       /* do the magnified texels */
  2579.       switch (tObj->MagFilter) {
  2580.       case GL_NEAREST:
  2581.          for (i = magStart; i < magEnd; i++)
  2582.             sample_2d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  2583.                               texcoords[i], rgba[i]);
  2584.          break;
  2585.       case GL_LINEAR:
  2586.          for (i = magStart; i < magEnd; i++)
  2587.             sample_2d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  2588.                                    texcoords[i], rgba[i]);
  2589.          break;
  2590.       default:
  2591.          _mesa_problem(ctx, "Bad mag filter in sample_2d_array_texture");
  2592.          return;
  2593.       }
  2594.    }
  2595. }
  2596.  
  2597.  
  2598.  
  2599.  
  2600. /**********************************************************************/
  2601. /*                1D Texture Array Sampling Functions                 */
  2602. /**********************************************************************/
  2603.  
  2604. /**
  2605.  * Return the texture sample for coordinate (s,t,r) using GL_NEAREST filter.
  2606.  */
  2607. static void
  2608. sample_1d_array_nearest(struct gl_context *ctx,
  2609.                         const struct gl_texture_object *tObj,
  2610.                         const struct gl_texture_image *img,
  2611.                         const GLfloat texcoord[4],
  2612.                         GLfloat rgba[4])
  2613. {
  2614.    const GLint width = img->Width2;     /* without border, power of two */
  2615.    const GLint height = img->Height;
  2616.    GLint i;
  2617.    GLint array;
  2618.    (void) ctx;
  2619.  
  2620.    i = nearest_texel_location(tObj->WrapS, img, width, texcoord[0]);
  2621.    array = tex_array_slice(texcoord[1], height);
  2622.  
  2623.    if (i < 0 || i >= (GLint) img->Width ||
  2624.        array < 0 || array >= (GLint) img->Height) {
  2625.       /* Need this test for GL_CLAMP_TO_BORDER mode */
  2626.       get_border_color(tObj, img, rgba);
  2627.    }
  2628.    else {
  2629.       img->FetchTexelf(img, i, array, 0, rgba);
  2630.    }
  2631. }
  2632.  
  2633.  
  2634. /**
  2635.  * Return the texture sample for coordinate (s,t,r) using GL_LINEAR filter.
  2636.  */
  2637. static void
  2638. sample_1d_array_linear(struct gl_context *ctx,
  2639.                        const struct gl_texture_object *tObj,
  2640.                        const struct gl_texture_image *img,
  2641.                        const GLfloat texcoord[4],
  2642.                        GLfloat rgba[4])
  2643. {
  2644.    const GLint width = img->Width2;
  2645.    const GLint height = img->Height;
  2646.    GLint i0, i1;
  2647.    GLint array;
  2648.    GLbitfield useBorderColor = 0x0;
  2649.    GLfloat a;
  2650.    GLfloat t0[4], t1[4];
  2651.  
  2652.    linear_texel_locations(tObj->WrapS, img, width, texcoord[0], &i0, &i1, &a);
  2653.    array = tex_array_slice(texcoord[1], height);
  2654.  
  2655.    if (img->Border) {
  2656.       i0 += img->Border;
  2657.       i1 += img->Border;
  2658.    }
  2659.    else {
  2660.       /* check if sampling texture border color */
  2661.       if (i0 < 0 || i0 >= width)   useBorderColor |= I0BIT;
  2662.       if (i1 < 0 || i1 >= width)   useBorderColor |= I1BIT;
  2663.    }
  2664.  
  2665.    if (array < 0 || array >= height)   useBorderColor |= K0BIT;
  2666.  
  2667.    /* Fetch texels */
  2668.    if (useBorderColor & (I0BIT | K0BIT)) {
  2669.       get_border_color(tObj, img, t0);
  2670.    }
  2671.    else {
  2672.       img->FetchTexelf(img, i0, array, 0, t0);
  2673.    }
  2674.    if (useBorderColor & (I1BIT | K0BIT)) {
  2675.       get_border_color(tObj, img, t1);
  2676.    }
  2677.    else {
  2678.       img->FetchTexelf(img, i1, array, 0, t1);
  2679.    }
  2680.  
  2681.    /* bilinear interpolation of samples */
  2682.    lerp_rgba(rgba, a, t0, t1);
  2683. }
  2684.  
  2685.  
  2686. static void
  2687. sample_1d_array_nearest_mipmap_nearest(struct gl_context *ctx,
  2688.                                        const struct gl_texture_object *tObj,
  2689.                                        GLuint n, const GLfloat texcoord[][4],
  2690.                                        const GLfloat lambda[], GLfloat rgba[][4])
  2691. {
  2692.    GLuint i;
  2693.    for (i = 0; i < n; i++) {
  2694.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  2695.       sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level], texcoord[i],
  2696.                               rgba[i]);
  2697.    }
  2698. }
  2699.  
  2700.  
  2701. static void
  2702. sample_1d_array_linear_mipmap_nearest(struct gl_context *ctx,
  2703.                                       const struct gl_texture_object *tObj,
  2704.                                       GLuint n, const GLfloat texcoord[][4],
  2705.                                       const GLfloat lambda[], GLfloat rgba[][4])
  2706. {
  2707.    GLuint i;
  2708.    ASSERT(lambda != NULL);
  2709.    for (i = 0; i < n; i++) {
  2710.       GLint level = nearest_mipmap_level(tObj, lambda[i]);
  2711.       sample_1d_array_linear(ctx, tObj, tObj->Image[0][level],
  2712.                              texcoord[i], rgba[i]);
  2713.    }
  2714. }
  2715.  
  2716.  
  2717. static void
  2718. sample_1d_array_nearest_mipmap_linear(struct gl_context *ctx,
  2719.                                       const struct gl_texture_object *tObj,
  2720.                                       GLuint n, const GLfloat texcoord[][4],
  2721.                                       const GLfloat lambda[], GLfloat rgba[][4])
  2722. {
  2723.    GLuint i;
  2724.    ASSERT(lambda != NULL);
  2725.    for (i = 0; i < n; i++) {
  2726.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  2727.       if (level >= tObj->_MaxLevel) {
  2728.          sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  2729.                                  texcoord[i], rgba[i]);
  2730.       }
  2731.       else {
  2732.          GLfloat t0[4], t1[4];  /* texels */
  2733.          const GLfloat f = FRAC(lambda[i]);
  2734.          sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
  2735.          sample_1d_array_nearest(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
  2736.          lerp_rgba(rgba[i], f, t0, t1);
  2737.       }
  2738.    }
  2739. }
  2740.  
  2741.  
  2742. static void
  2743. sample_1d_array_linear_mipmap_linear(struct gl_context *ctx,
  2744.                                      const struct gl_texture_object *tObj,
  2745.                                      GLuint n, const GLfloat texcoord[][4],
  2746.                                      const GLfloat lambda[], GLfloat rgba[][4])
  2747. {
  2748.    GLuint i;
  2749.    ASSERT(lambda != NULL);
  2750.    for (i = 0; i < n; i++) {
  2751.       GLint level = linear_mipmap_level(tObj, lambda[i]);
  2752.       if (level >= tObj->_MaxLevel) {
  2753.          sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->_MaxLevel],
  2754.                           texcoord[i], rgba[i]);
  2755.       }
  2756.       else {
  2757.          GLfloat t0[4], t1[4];  /* texels */
  2758.          const GLfloat f = FRAC(lambda[i]);
  2759.          sample_1d_array_linear(ctx, tObj, tObj->Image[0][level  ], texcoord[i], t0);
  2760.          sample_1d_array_linear(ctx, tObj, tObj->Image[0][level+1], texcoord[i], t1);
  2761.          lerp_rgba(rgba[i], f, t0, t1);
  2762.       }
  2763.    }
  2764. }
  2765.  
  2766.  
  2767. /** Sample 1D Array texture, nearest filtering for both min/magnification */
  2768. static void
  2769. sample_nearest_1d_array(struct gl_context *ctx,
  2770.                         const struct gl_texture_object *tObj, GLuint n,
  2771.                         const GLfloat texcoords[][4], const GLfloat lambda[],
  2772.                         GLfloat rgba[][4])
  2773. {
  2774.    GLuint i;
  2775.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  2776.    (void) lambda;
  2777.    for (i = 0; i < n; i++) {
  2778.       sample_1d_array_nearest(ctx, tObj, image, texcoords[i], rgba[i]);
  2779.    }
  2780. }
  2781.  
  2782.  
  2783. /** Sample 1D Array texture, linear filtering for both min/magnification */
  2784. static void
  2785. sample_linear_1d_array(struct gl_context *ctx,
  2786.                        const struct gl_texture_object *tObj, GLuint n,
  2787.                        const GLfloat texcoords[][4],
  2788.                        const GLfloat lambda[], GLfloat rgba[][4])
  2789. {
  2790.    GLuint i;
  2791.    struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
  2792.    (void) lambda;
  2793.    for (i = 0; i < n; i++) {
  2794.       sample_1d_array_linear(ctx, tObj, image, texcoords[i], rgba[i]);
  2795.    }
  2796. }
  2797.  
  2798.  
  2799. /** Sample 1D Array texture, using lambda to choose between min/magnification */
  2800. static void
  2801. sample_lambda_1d_array(struct gl_context *ctx,
  2802.                        const struct gl_texture_object *tObj, GLuint n,
  2803.                        const GLfloat texcoords[][4], const GLfloat lambda[],
  2804.                        GLfloat rgba[][4])
  2805. {
  2806.    GLuint minStart, minEnd;  /* texels with minification */
  2807.    GLuint magStart, magEnd;  /* texels with magnification */
  2808.    GLuint i;
  2809.  
  2810.    ASSERT(lambda != NULL);
  2811.    compute_min_mag_ranges(tObj, n, lambda,
  2812.                           &minStart, &minEnd, &magStart, &magEnd);
  2813.  
  2814.    if (minStart < minEnd) {
  2815.       /* do the minified texels */
  2816.       GLuint m = minEnd - minStart;
  2817.       switch (tObj->MinFilter) {
  2818.       case GL_NEAREST:
  2819.          for (i = minStart; i < minEnd; i++)
  2820.             sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  2821.                                     texcoords[i], rgba[i]);
  2822.          break;
  2823.       case GL_LINEAR:
  2824.          for (i = minStart; i < minEnd; i++)
  2825.             sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  2826.                                    texcoords[i], rgba[i]);
  2827.          break;
  2828.       case GL_NEAREST_MIPMAP_NEAREST:
  2829.          sample_1d_array_nearest_mipmap_nearest(ctx, tObj, m, texcoords + minStart,
  2830.                                                 lambda + minStart, rgba + minStart);
  2831.          break;
  2832.       case GL_LINEAR_MIPMAP_NEAREST:
  2833.          sample_1d_array_linear_mipmap_nearest(ctx, tObj, m,
  2834.                                                texcoords + minStart,
  2835.                                                lambda + minStart,
  2836.                                                rgba + minStart);
  2837.          break;
  2838.       case GL_NEAREST_MIPMAP_LINEAR:
  2839.          sample_1d_array_nearest_mipmap_linear(ctx, tObj, m, texcoords + minStart,
  2840.                                                lambda + minStart, rgba + minStart);
  2841.          break;
  2842.       case GL_LINEAR_MIPMAP_LINEAR:
  2843.          sample_1d_array_linear_mipmap_linear(ctx, tObj, m,
  2844.                                               texcoords + minStart,
  2845.                                               lambda + minStart,
  2846.                                               rgba + minStart);
  2847.          break;
  2848.       default:
  2849.          _mesa_problem(ctx, "Bad min filter in sample_1d_array_texture");
  2850.          return;
  2851.       }
  2852.    }
  2853.  
  2854.    if (magStart < magEnd) {
  2855.       /* do the magnified texels */
  2856.       switch (tObj->MagFilter) {
  2857.       case GL_NEAREST:
  2858.          for (i = magStart; i < magEnd; i++)
  2859.             sample_1d_array_nearest(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  2860.                               texcoords[i], rgba[i]);
  2861.          break;
  2862.       case GL_LINEAR:
  2863.          for (i = magStart; i < magEnd; i++)
  2864.             sample_1d_array_linear(ctx, tObj, tObj->Image[0][tObj->BaseLevel],
  2865.                                    texcoords[i], rgba[i]);
  2866.          break;
  2867.       default:
  2868.          _mesa_problem(ctx, "Bad mag filter in sample_1d_array_texture");
  2869.          return;
  2870.       }
  2871.    }
  2872. }
  2873.  
  2874.  
  2875. /**
  2876.  * Compare texcoord against depth sample.  Return 1.0 or the ambient value.
  2877.  */
  2878. static INLINE GLfloat
  2879. shadow_compare(GLenum function, GLfloat coord, GLfloat depthSample,
  2880.                GLfloat ambient)
  2881. {
  2882.    switch (function) {
  2883.    case GL_LEQUAL:
  2884.       return (coord <= depthSample) ? 1.0F : ambient;
  2885.    case GL_GEQUAL:
  2886.       return (coord >= depthSample) ? 1.0F : ambient;
  2887.    case GL_LESS:
  2888.       return (coord < depthSample) ? 1.0F : ambient;
  2889.    case GL_GREATER:
  2890.       return (coord > depthSample) ? 1.0F : ambient;
  2891.    case GL_EQUAL:
  2892.       return (coord == depthSample) ? 1.0F : ambient;
  2893.    case GL_NOTEQUAL:
  2894.       return (coord != depthSample) ? 1.0F : ambient;
  2895.    case GL_ALWAYS:
  2896.       return 1.0F;
  2897.    case GL_NEVER:
  2898.       return ambient;
  2899.    case GL_NONE:
  2900.       return depthSample;
  2901.    default:
  2902.       _mesa_problem(NULL, "Bad compare func in shadow_compare");
  2903.       return ambient;
  2904.    }
  2905. }
  2906.  
  2907.  
  2908. /**
  2909.  * Compare texcoord against four depth samples.
  2910.  */
  2911. static INLINE GLfloat
  2912. shadow_compare4(GLenum function, GLfloat coord,
  2913.                 GLfloat depth00, GLfloat depth01,
  2914.                 GLfloat depth10, GLfloat depth11,
  2915.                 GLfloat ambient, GLfloat wi, GLfloat wj)
  2916. {
  2917.    const GLfloat d = (1.0F - (GLfloat) ambient) * 0.25F;
  2918.    GLfloat luminance = 1.0F;
  2919.  
  2920.    switch (function) {
  2921.    case GL_LEQUAL:
  2922.       if (depth00 <= coord)  luminance -= d;
  2923.       if (depth01 <= coord)  luminance -= d;
  2924.       if (depth10 <= coord)  luminance -= d;
  2925.       if (depth11 <= coord)  luminance -= d;
  2926.       return luminance;
  2927.    case GL_GEQUAL:
  2928.       if (depth00 >= coord)  luminance -= d;
  2929.       if (depth01 >= coord)  luminance -= d;
  2930.       if (depth10 >= coord)  luminance -= d;
  2931.       if (depth11 >= coord)  luminance -= d;
  2932.       return luminance;
  2933.    case GL_LESS:
  2934.       if (depth00 < coord)  luminance -= d;
  2935.       if (depth01 < coord)  luminance -= d;
  2936.       if (depth10 < coord)  luminance -= d;
  2937.       if (depth11 < coord)  luminance -= d;
  2938.       return luminance;
  2939.    case GL_GREATER:
  2940.       if (depth00 > coord)  luminance -= d;
  2941.       if (depth01 > coord)  luminance -= d;
  2942.       if (depth10 > coord)  luminance -= d;
  2943.       if (depth11 > coord)  luminance -= d;
  2944.       return luminance;
  2945.    case GL_EQUAL:
  2946.       if (depth00 == coord)  luminance -= d;
  2947.       if (depth01 == coord)  luminance -= d;
  2948.       if (depth10 == coord)  luminance -= d;
  2949.       if (depth11 == coord)  luminance -= d;
  2950.       return luminance;
  2951.    case GL_NOTEQUAL:
  2952.       if (depth00 != coord)  luminance -= d;
  2953.       if (depth01 != coord)  luminance -= d;
  2954.       if (depth10 != coord)  luminance -= d;
  2955.       if (depth11 != coord)  luminance -= d;
  2956.       return luminance;
  2957.    case GL_ALWAYS:
  2958.       return 0.0;
  2959.    case GL_NEVER:
  2960.       return ambient;
  2961.    case GL_NONE:
  2962.       /* ordinary bilinear filtering */
  2963.       return lerp_2d(wi, wj, depth00, depth10, depth01, depth11);
  2964.    default:
  2965.       _mesa_problem(NULL, "Bad compare func in sample_depth_texture");
  2966.       return 0.0F;
  2967.    }
  2968. }
  2969.  
  2970.  
  2971. /**
  2972.  * Choose the mipmap level to use when sampling from a depth texture.
  2973.  */
  2974. static int
  2975. choose_depth_texture_level(const struct gl_texture_object *tObj, GLfloat lambda)
  2976. {
  2977.    GLint level;
  2978.  
  2979.    if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
  2980.       /* no mipmapping - use base level */
  2981.       level = tObj->BaseLevel;
  2982.    }
  2983.    else {
  2984.       /* choose mipmap level */
  2985.       lambda = CLAMP(lambda, tObj->MinLod, tObj->MaxLod);
  2986.       level = (GLint) lambda;
  2987.       level = CLAMP(level, tObj->BaseLevel, tObj->_MaxLevel);
  2988.    }
  2989.  
  2990.    return level;
  2991. }
  2992.  
  2993.  
  2994. /**
  2995.  * Sample a shadow/depth texture.  This function is incomplete.  It doesn't
  2996.  * check for minification vs. magnification, etc.
  2997.  */
  2998. static void
  2999. sample_depth_texture( struct gl_context *ctx,
  3000.                       const struct gl_texture_object *tObj, GLuint n,
  3001.                       const GLfloat texcoords[][4], const GLfloat lambda[],
  3002.                       GLfloat texel[][4] )
  3003. {
  3004.    const GLint level = choose_depth_texture_level(tObj, lambda[0]);
  3005.    const struct gl_texture_image *img = tObj->Image[0][level];
  3006.    const GLint width = img->Width;
  3007.    const GLint height = img->Height;
  3008.    const GLint depth = img->Depth;
  3009.    const GLuint compare_coord = (tObj->Target == GL_TEXTURE_2D_ARRAY_EXT)
  3010.        ? 3 : 2;
  3011.    GLfloat ambient;
  3012.    GLenum function;
  3013.    GLfloat result;
  3014.  
  3015.    ASSERT(img->_BaseFormat == GL_DEPTH_COMPONENT ||
  3016.           img->_BaseFormat == GL_DEPTH_STENCIL_EXT);
  3017.  
  3018.    ASSERT(tObj->Target == GL_TEXTURE_1D ||
  3019.           tObj->Target == GL_TEXTURE_2D ||
  3020.           tObj->Target == GL_TEXTURE_RECTANGLE_NV ||
  3021.           tObj->Target == GL_TEXTURE_1D_ARRAY_EXT ||
  3022.           tObj->Target == GL_TEXTURE_2D_ARRAY_EXT);
  3023.  
  3024.    ambient = tObj->CompareFailValue;
  3025.  
  3026.    /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */
  3027.  
  3028.    function = (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) ?
  3029.       tObj->CompareFunc : GL_NONE;
  3030.  
  3031.    if (tObj->MagFilter == GL_NEAREST) {
  3032.       GLuint i;
  3033.       for (i = 0; i < n; i++) {
  3034.          GLfloat depthSample;
  3035.          GLint col, row, slice;
  3036.  
  3037.          nearest_texcoord(tObj, level, texcoords[i], &col, &row, &slice);
  3038.  
  3039.          if (col >= 0 && row >= 0 && col < width && row < height &&
  3040.              slice >= 0 && slice < depth) {
  3041.             img->FetchTexelf(img, col, row, slice, &depthSample);
  3042.          }
  3043.          else {
  3044.             depthSample = tObj->BorderColor.f[0];
  3045.          }
  3046.  
  3047.          result = shadow_compare(function, texcoords[i][compare_coord],
  3048.                                  depthSample, ambient);
  3049.  
  3050.          switch (tObj->DepthMode) {
  3051.          case GL_LUMINANCE:
  3052.             ASSIGN_4V(texel[i], result, result, result, 1.0F);
  3053.             break;
  3054.          case GL_INTENSITY:
  3055.             ASSIGN_4V(texel[i], result, result, result, result);
  3056.             break;
  3057.          case GL_ALPHA:
  3058.             ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
  3059.             break;
  3060.          case GL_RED:
  3061.             ASSIGN_4V(texel[i], result, 0.0F, 0.0F, 1.0F);
  3062.             break;
  3063.          default:
  3064.             _mesa_problem(ctx, "Bad depth texture mode");
  3065.          }
  3066.       }
  3067.    }
  3068.    else {
  3069.       GLuint i;
  3070.       ASSERT(tObj->MagFilter == GL_LINEAR);
  3071.       for (i = 0; i < n; i++) {
  3072.          GLfloat depth00, depth01, depth10, depth11;
  3073.          GLint i0, i1, j0, j1;
  3074.          GLint slice;
  3075.          GLfloat wi, wj;
  3076.          GLuint useBorderTexel;
  3077.  
  3078.          linear_texcoord(tObj, level, texcoords[i], &i0, &i1, &j0, &j1, &slice,
  3079.                          &wi, &wj);
  3080.  
  3081.          useBorderTexel = 0;
  3082.          if (img->Border) {
  3083.             i0 += img->Border;
  3084.             i1 += img->Border;
  3085.             if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) {
  3086.                j0 += img->Border;
  3087.                j1 += img->Border;
  3088.             }
  3089.          }
  3090.          else {
  3091.             if (i0 < 0 || i0 >= (GLint) width)   useBorderTexel |= I0BIT;
  3092.             if (i1 < 0 || i1 >= (GLint) width)   useBorderTexel |= I1BIT;
  3093.             if (j0 < 0 || j0 >= (GLint) height)  useBorderTexel |= J0BIT;
  3094.             if (j1 < 0 || j1 >= (GLint) height)  useBorderTexel |= J1BIT;
  3095.          }
  3096.  
  3097.          if (slice < 0 || slice >= (GLint) depth) {
  3098.             depth00 = tObj->BorderColor.f[0];
  3099.             depth01 = tObj->BorderColor.f[0];
  3100.             depth10 = tObj->BorderColor.f[0];
  3101.             depth11 = tObj->BorderColor.f[0];
  3102.          }
  3103.          else {
  3104.             /* get four depth samples from the texture */
  3105.             if (useBorderTexel & (I0BIT | J0BIT)) {
  3106.                depth00 = tObj->BorderColor.f[0];
  3107.             }
  3108.             else {
  3109.                img->FetchTexelf(img, i0, j0, slice, &depth00);
  3110.             }
  3111.             if (useBorderTexel & (I1BIT | J0BIT)) {
  3112.                depth10 = tObj->BorderColor.f[0];
  3113.             }
  3114.             else {
  3115.                img->FetchTexelf(img, i1, j0, slice, &depth10);
  3116.             }
  3117.  
  3118.             if (tObj->Target != GL_TEXTURE_1D_ARRAY_EXT) {
  3119.                if (useBorderTexel & (I0BIT | J1BIT)) {
  3120.                   depth01 = tObj->BorderColor.f[0];
  3121.                }
  3122.                else {
  3123.                   img->FetchTexelf(img, i0, j1, slice, &depth01);
  3124.                }
  3125.                if (useBorderTexel & (I1BIT | J1BIT)) {
  3126.                   depth11 = tObj->BorderColor.f[0];
  3127.                }
  3128.                else {
  3129.                   img->FetchTexelf(img, i1, j1, slice, &depth11);
  3130.                }
  3131.             }
  3132.             else {
  3133.                depth01 = depth00;
  3134.                depth11 = depth10;
  3135.             }
  3136.          }
  3137.  
  3138.          result = shadow_compare4(function, texcoords[i][compare_coord],
  3139.                                   depth00, depth01, depth10, depth11,
  3140.                                   ambient, wi, wj);
  3141.  
  3142.          switch (tObj->DepthMode) {
  3143.          case GL_LUMINANCE:
  3144.             ASSIGN_4V(texel[i], result, result, result, 1.0F);
  3145.             break;
  3146.          case GL_INTENSITY:
  3147.             ASSIGN_4V(texel[i], result, result, result, result);
  3148.             break;
  3149.          case GL_ALPHA:
  3150.             ASSIGN_4V(texel[i], 0.0F, 0.0F, 0.0F, result);
  3151.             break;
  3152.          default:
  3153.             _mesa_problem(ctx, "Bad depth texture mode");
  3154.          }
  3155.  
  3156.       }  /* for */
  3157.    }  /* if filter */
  3158. }
  3159.  
  3160.  
  3161. /**
  3162.  * We use this function when a texture object is in an "incomplete" state.
  3163.  * When a fragment program attempts to sample an incomplete texture we
  3164.  * return black (see issue 23 in GL_ARB_fragment_program spec).
  3165.  * Note: fragment programs don't observe the texture enable/disable flags.
  3166.  */
  3167. static void
  3168. null_sample_func( struct gl_context *ctx,
  3169.                   const struct gl_texture_object *tObj, GLuint n,
  3170.                   const GLfloat texcoords[][4], const GLfloat lambda[],
  3171.                   GLfloat rgba[][4])
  3172. {
  3173.    GLuint i;
  3174.    (void) ctx;
  3175.    (void) tObj;
  3176.    (void) texcoords;
  3177.    (void) lambda;
  3178.    for (i = 0; i < n; i++) {
  3179.       rgba[i][RCOMP] = 0;
  3180.       rgba[i][GCOMP] = 0;
  3181.       rgba[i][BCOMP] = 0;
  3182.       rgba[i][ACOMP] = 1.0;
  3183.    }
  3184. }
  3185.  
  3186.  
  3187. /**
  3188.  * Choose the texture sampling function for the given texture object.
  3189.  */
  3190. texture_sample_func
  3191. _swrast_choose_texture_sample_func( struct gl_context *ctx,
  3192.                                     const struct gl_texture_object *t )
  3193. {
  3194.    if (!t || !t->_Complete) {
  3195.       return &null_sample_func;
  3196.    }
  3197.    else {
  3198.       const GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter);
  3199.       const GLenum format = t->Image[0][t->BaseLevel]->_BaseFormat;
  3200.  
  3201.       switch (t->Target) {
  3202.       case GL_TEXTURE_1D:
  3203.          if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
  3204.             return &sample_depth_texture;
  3205.          }
  3206.          else if (needLambda) {
  3207.             return &sample_lambda_1d;
  3208.          }
  3209.          else if (t->MinFilter == GL_LINEAR) {
  3210.             return &sample_linear_1d;
  3211.          }
  3212.          else {
  3213.             ASSERT(t->MinFilter == GL_NEAREST);
  3214.             return &sample_nearest_1d;
  3215.          }
  3216.       case GL_TEXTURE_2D:
  3217.          if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
  3218.             return &sample_depth_texture;
  3219.          }
  3220.          else if (needLambda) {
  3221.             return &sample_lambda_2d;
  3222.          }
  3223.          else if (t->MinFilter == GL_LINEAR) {
  3224.             return &sample_linear_2d;
  3225.          }
  3226.          else {
  3227.             /* check for a few optimized cases */
  3228.             const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
  3229.             ASSERT(t->MinFilter == GL_NEAREST);
  3230.             if (t->WrapS == GL_REPEAT &&
  3231.                 t->WrapT == GL_REPEAT &&
  3232.                 img->_IsPowerOfTwo &&
  3233.                 img->Border == 0 &&
  3234.                 img->TexFormat == MESA_FORMAT_RGB888) {
  3235.                return &opt_sample_rgb_2d;
  3236.             }
  3237.             else if (t->WrapS == GL_REPEAT &&
  3238.                      t->WrapT == GL_REPEAT &&
  3239.                      img->_IsPowerOfTwo &&
  3240.                      img->Border == 0 &&
  3241.                      img->TexFormat == MESA_FORMAT_RGBA8888) {
  3242.                return &opt_sample_rgba_2d;
  3243.             }
  3244.             else {
  3245.                return &sample_nearest_2d;
  3246.             }
  3247.          }
  3248.       case GL_TEXTURE_3D:
  3249.          if (needLambda) {
  3250.             return &sample_lambda_3d;
  3251.          }
  3252.          else if (t->MinFilter == GL_LINEAR) {
  3253.             return &sample_linear_3d;
  3254.          }
  3255.          else {
  3256.             ASSERT(t->MinFilter == GL_NEAREST);
  3257.             return &sample_nearest_3d;
  3258.          }
  3259.       case GL_TEXTURE_CUBE_MAP:
  3260.          if (needLambda) {
  3261.             return &sample_lambda_cube;
  3262.          }
  3263.          else if (t->MinFilter == GL_LINEAR) {
  3264.             return &sample_linear_cube;
  3265.          }
  3266.          else {
  3267.             ASSERT(t->MinFilter == GL_NEAREST);
  3268.             return &sample_nearest_cube;
  3269.          }
  3270.       case GL_TEXTURE_RECTANGLE_NV:
  3271.          if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL_EXT) {
  3272.             return &sample_depth_texture;
  3273.          }
  3274.          else if (needLambda) {
  3275.             return &sample_lambda_rect;
  3276.          }
  3277.          else if (t->MinFilter == GL_LINEAR) {
  3278.             return &sample_linear_rect;
  3279.          }
  3280.          else {
  3281.             ASSERT(t->MinFilter == GL_NEAREST);
  3282.             return &sample_nearest_rect;
  3283.          }
  3284.       case GL_TEXTURE_1D_ARRAY_EXT:
  3285.          if (needLambda) {
  3286.             return &sample_lambda_1d_array;
  3287.          }
  3288.          else if (t->MinFilter == GL_LINEAR) {
  3289.             return &sample_linear_1d_array;
  3290.          }
  3291.          else {
  3292.             ASSERT(t->MinFilter == GL_NEAREST);
  3293.             return &sample_nearest_1d_array;
  3294.          }
  3295.       case GL_TEXTURE_2D_ARRAY_EXT:
  3296.          if (needLambda) {
  3297.             return &sample_lambda_2d_array;
  3298.          }
  3299.          else if (t->MinFilter == GL_LINEAR) {
  3300.             return &sample_linear_2d_array;
  3301.          }
  3302.          else {
  3303.             ASSERT(t->MinFilter == GL_NEAREST);
  3304.             return &sample_nearest_2d_array;
  3305.          }
  3306.       default:
  3307.          _mesa_problem(ctx,
  3308.                        "invalid target in _swrast_choose_texture_sample_func");
  3309.          return &null_sample_func;
  3310.       }
  3311.    }
  3312. }
  3313.