Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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