Subversion Repositories Kolibri OS

Rev

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

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