Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  * Copyright 2008-2010 VMware, Inc.  All rights reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the
  9.  * "Software"), to deal in the Software without restriction, including
  10.  * without limitation the rights to use, copy, modify, merge, publish,
  11.  * distribute, sub license, and/or sell copies of the Software, and to
  12.  * permit persons to whom the Software is furnished to do so, subject to
  13.  * the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice (including the
  16.  * next paragraph) shall be included in all copies or substantial portions
  17.  * of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  22.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  23.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  24.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  25.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  *
  27.  **************************************************************************/
  28.  
  29. /**
  30.  * Texture sampling
  31.  *
  32.  * Authors:
  33.  *   Brian Paul
  34.  *   Keith Whitwell
  35.  */
  36.  
  37. #include "pipe/p_context.h"
  38. #include "pipe/p_defines.h"
  39. #include "pipe/p_shader_tokens.h"
  40. #include "util/u_math.h"
  41. #include "util/u_format.h"
  42. #include "util/u_memory.h"
  43. #include "util/u_inlines.h"
  44. #include "sp_quad.h"   /* only for #define QUAD_* tokens */
  45. #include "sp_tex_sample.h"
  46. #include "sp_texture.h"
  47. #include "sp_tex_tile_cache.h"
  48.  
  49.  
  50. /** Set to one to help debug texture sampling */
  51. #define DEBUG_TEX 0
  52.  
  53.  
  54. /*
  55.  * Return fractional part of 'f'.  Used for computing interpolation weights.
  56.  * Need to be careful with negative values.
  57.  * Note, if this function isn't perfect you'll sometimes see 1-pixel bands
  58.  * of improperly weighted linear-filtered textures.
  59.  * The tests/texwrap.c demo is a good test.
  60.  */
  61. static INLINE float
  62. frac(float f)
  63. {
  64.    return f - floorf(f);
  65. }
  66.  
  67.  
  68.  
  69. /**
  70.  * Linear interpolation macro
  71.  */
  72. static INLINE float
  73. lerp(float a, float v0, float v1)
  74. {
  75.    return v0 + a * (v1 - v0);
  76. }
  77.  
  78.  
  79. /**
  80.  * Do 2D/bilinear interpolation of float values.
  81.  * v00, v10, v01 and v11 are typically four texture samples in a square/box.
  82.  * a and b are the horizontal and vertical interpolants.
  83.  * It's important that this function is inlined when compiled with
  84.  * optimization!  If we find that's not true on some systems, convert
  85.  * to a macro.
  86.  */
  87. static INLINE float
  88. lerp_2d(float a, float b,
  89.         float v00, float v10, float v01, float v11)
  90. {
  91.    const float temp0 = lerp(a, v00, v10);
  92.    const float temp1 = lerp(a, v01, v11);
  93.    return lerp(b, temp0, temp1);
  94. }
  95.  
  96.  
  97. /**
  98.  * As above, but 3D interpolation of 8 values.
  99.  */
  100. static INLINE float
  101. lerp_3d(float a, float b, float c,
  102.         float v000, float v100, float v010, float v110,
  103.         float v001, float v101, float v011, float v111)
  104. {
  105.    const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
  106.    const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
  107.    return lerp(c, temp0, temp1);
  108. }
  109.  
  110.  
  111.  
  112. /**
  113.  * Compute coord % size for repeat wrap modes.
  114.  * Note that if coord is negative, coord % size doesn't give the right
  115.  * value.  To avoid that problem we add a large multiple of the size
  116.  * (rather than using a conditional).
  117.  */
  118. static INLINE int
  119. repeat(int coord, unsigned size)
  120. {
  121.    return (coord + size * 1024) % size;
  122. }
  123.  
  124.  
  125. /**
  126.  * Apply texture coord wrapping mode and return integer texture indexes
  127.  * for a vector of four texcoords (S or T or P).
  128.  * \param wrapMode  PIPE_TEX_WRAP_x
  129.  * \param s  the incoming texcoords
  130.  * \param size  the texture image size
  131.  * \param icoord  returns the integer texcoords
  132.  */
  133. static void
  134. wrap_nearest_repeat(float s, unsigned size, int *icoord)
  135. {
  136.    /* s limited to [0,1) */
  137.    /* i limited to [0,size-1] */
  138.    int i = util_ifloor(s * size);
  139.    *icoord = repeat(i, size);
  140. }
  141.  
  142.  
  143. static void
  144. wrap_nearest_clamp(float s, unsigned size, int *icoord)
  145. {
  146.    /* s limited to [0,1] */
  147.    /* i limited to [0,size-1] */
  148.    if (s <= 0.0F)
  149.       *icoord = 0;
  150.    else if (s >= 1.0F)
  151.       *icoord = size - 1;
  152.    else
  153.       *icoord = util_ifloor(s * size);
  154. }
  155.  
  156.  
  157. static void
  158. wrap_nearest_clamp_to_edge(float s, unsigned size, int *icoord)
  159. {
  160.    /* s limited to [min,max] */
  161.    /* i limited to [0, size-1] */
  162.    const float min = 1.0F / (2.0F * size);
  163.    const float max = 1.0F - min;
  164.    if (s < min)
  165.       *icoord = 0;
  166.    else if (s > max)
  167.       *icoord = size - 1;
  168.    else
  169.       *icoord = util_ifloor(s * size);
  170. }
  171.  
  172.  
  173. static void
  174. wrap_nearest_clamp_to_border(float s, unsigned size, int *icoord)
  175. {
  176.    /* s limited to [min,max] */
  177.    /* i limited to [-1, size] */
  178.    const float min = -1.0F / (2.0F * size);
  179.    const float max = 1.0F - min;
  180.    if (s <= min)
  181.       *icoord = -1;
  182.    else if (s >= max)
  183.       *icoord = size;
  184.    else
  185.       *icoord = util_ifloor(s * size);
  186. }
  187.  
  188.  
  189. static void
  190. wrap_nearest_mirror_repeat(float s, unsigned size, int *icoord)
  191. {
  192.    const float min = 1.0F / (2.0F * size);
  193.    const float max = 1.0F - min;
  194.    const int flr = util_ifloor(s);
  195.    float u = frac(s);
  196.    if (flr & 1)
  197.       u = 1.0F - u;
  198.    if (u < min)
  199.       *icoord = 0;
  200.    else if (u > max)
  201.       *icoord = size - 1;
  202.    else
  203.       *icoord = util_ifloor(u * size);
  204. }
  205.  
  206.  
  207. static void
  208. wrap_nearest_mirror_clamp(float s, unsigned size, int *icoord)
  209. {
  210.    /* s limited to [0,1] */
  211.    /* i limited to [0,size-1] */
  212.    const float u = fabsf(s);
  213.    if (u <= 0.0F)
  214.       *icoord = 0;
  215.    else if (u >= 1.0F)
  216.       *icoord = size - 1;
  217.    else
  218.       *icoord = util_ifloor(u * size);
  219. }
  220.  
  221.  
  222. static void
  223. wrap_nearest_mirror_clamp_to_edge(float s, unsigned size, int *icoord)
  224. {
  225.    /* s limited to [min,max] */
  226.    /* i limited to [0, size-1] */
  227.    const float min = 1.0F / (2.0F * size);
  228.    const float max = 1.0F - min;
  229.    const float u = fabsf(s);
  230.    if (u < min)
  231.       *icoord = 0;
  232.    else if (u > max)
  233.       *icoord = size - 1;
  234.    else
  235.       *icoord = util_ifloor(u * size);
  236. }
  237.  
  238.  
  239. static void
  240. wrap_nearest_mirror_clamp_to_border(float s, unsigned size, int *icoord)
  241. {
  242.    /* s limited to [min,max] */
  243.    /* i limited to [0, size-1] */
  244.    const float min = -1.0F / (2.0F * size);
  245.    const float max = 1.0F - min;
  246.    const float u = fabsf(s);
  247.    if (u < min)
  248.       *icoord = -1;
  249.    else if (u > max)
  250.       *icoord = size;
  251.    else
  252.       *icoord = util_ifloor(u * size);
  253. }
  254.  
  255.  
  256. /**
  257.  * Used to compute texel locations for linear sampling
  258.  * \param wrapMode  PIPE_TEX_WRAP_x
  259.  * \param s  the texcoord
  260.  * \param size  the texture image size
  261.  * \param icoord0  returns first texture index
  262.  * \param icoord1  returns second texture index (usually icoord0 + 1)
  263.  * \param w  returns blend factor/weight between texture indices
  264.  * \param icoord  returns the computed integer texture coord
  265.  */
  266. static void
  267. wrap_linear_repeat(float s, unsigned size,
  268.                    int *icoord0, int *icoord1, float *w)
  269. {
  270.    float u = s * size - 0.5F;
  271.    *icoord0 = repeat(util_ifloor(u), size);
  272.    *icoord1 = repeat(*icoord0 + 1, size);
  273.    *w = frac(u);
  274. }
  275.  
  276.  
  277. static void
  278. wrap_linear_clamp(float s, unsigned size,
  279.                   int *icoord0, int *icoord1, float *w)
  280. {
  281.    float u = CLAMP(s, 0.0F, 1.0F);
  282.    u = u * size - 0.5f;
  283.    *icoord0 = util_ifloor(u);
  284.    *icoord1 = *icoord0 + 1;
  285.    *w = frac(u);
  286. }
  287.  
  288.  
  289. static void
  290. wrap_linear_clamp_to_edge(float s, unsigned size,
  291.                           int *icoord0, int *icoord1, float *w)
  292. {
  293.    float u = CLAMP(s, 0.0F, 1.0F);
  294.    u = u * size - 0.5f;
  295.    *icoord0 = util_ifloor(u);
  296.    *icoord1 = *icoord0 + 1;
  297.    if (*icoord0 < 0)
  298.       *icoord0 = 0;
  299.    if (*icoord1 >= (int) size)
  300.       *icoord1 = size - 1;
  301.    *w = frac(u);
  302. }
  303.  
  304.  
  305. static void
  306. wrap_linear_clamp_to_border(float s, unsigned size,
  307.                             int *icoord0, int *icoord1, float *w)
  308. {
  309.    const float min = -1.0F / (2.0F * size);
  310.    const float max = 1.0F - min;
  311.    float u = CLAMP(s, min, max);
  312.    u = u * size - 0.5f;
  313.    *icoord0 = util_ifloor(u);
  314.    *icoord1 = *icoord0 + 1;
  315.    *w = frac(u);
  316. }
  317.  
  318.  
  319. static void
  320. wrap_linear_mirror_repeat(float s, unsigned size,
  321.                           int *icoord0, int *icoord1, float *w)
  322. {
  323.    const int flr = util_ifloor(s);
  324.    float u = frac(s);
  325.    if (flr & 1)
  326.       u = 1.0F - u;
  327.    u = u * size - 0.5F;
  328.    *icoord0 = util_ifloor(u);
  329.    *icoord1 = *icoord0 + 1;
  330.    if (*icoord0 < 0)
  331.       *icoord0 = 0;
  332.    if (*icoord1 >= (int) size)
  333.       *icoord1 = size - 1;
  334.    *w = frac(u);
  335. }
  336.  
  337.  
  338. static void
  339. wrap_linear_mirror_clamp(float s, unsigned size,
  340.                          int *icoord0, int *icoord1, float *w)
  341. {
  342.    float u = fabsf(s);
  343.    if (u >= 1.0F)
  344.       u = (float) size;
  345.    else
  346.       u *= size;
  347.    u -= 0.5F;
  348.    *icoord0 = util_ifloor(u);
  349.    *icoord1 = *icoord0 + 1;
  350.    *w = frac(u);
  351. }
  352.  
  353.  
  354. static void
  355. wrap_linear_mirror_clamp_to_edge(float s, unsigned size,
  356.                                  int *icoord0, int *icoord1, float *w)
  357. {
  358.    float u = fabsf(s);
  359.    if (u >= 1.0F)
  360.       u = (float) size;
  361.    else
  362.       u *= size;
  363.    u -= 0.5F;
  364.    *icoord0 = util_ifloor(u);
  365.    *icoord1 = *icoord0 + 1;
  366.    if (*icoord0 < 0)
  367.       *icoord0 = 0;
  368.    if (*icoord1 >= (int) size)
  369.       *icoord1 = size - 1;
  370.    *w = frac(u);
  371. }
  372.  
  373.  
  374. static void
  375. wrap_linear_mirror_clamp_to_border(float s, unsigned size,
  376.                                    int *icoord0, int *icoord1, float *w)
  377. {
  378.    const float min = -1.0F / (2.0F * size);
  379.    const float max = 1.0F - min;
  380.    float u = fabsf(s);
  381.    if (u <= min)
  382.       u = min * size;
  383.    else if (u >= max)
  384.       u = max * size;
  385.    else
  386.       u *= size;
  387.    u -= 0.5F;
  388.    *icoord0 = util_ifloor(u);
  389.    *icoord1 = *icoord0 + 1;
  390.    *w = frac(u);
  391. }
  392.  
  393.  
  394. /**
  395.  * PIPE_TEX_WRAP_CLAMP for nearest sampling, unnormalized coords.
  396.  */
  397. static void
  398. wrap_nearest_unorm_clamp(float s, unsigned size, int *icoord)
  399. {
  400.    int i = util_ifloor(s);
  401.    *icoord = CLAMP(i, 0, (int) size-1);
  402. }
  403.  
  404.  
  405. /**
  406.  * PIPE_TEX_WRAP_CLAMP_TO_BORDER for nearest sampling, unnormalized coords.
  407.  */
  408. static void
  409. wrap_nearest_unorm_clamp_to_border(float s, unsigned size, int *icoord)
  410. {
  411.    *icoord = util_ifloor( CLAMP(s, -0.5F, (float) size + 0.5F) );
  412. }
  413.  
  414.  
  415. /**
  416.  * PIPE_TEX_WRAP_CLAMP_TO_EDGE for nearest sampling, unnormalized coords.
  417.  */
  418. static void
  419. wrap_nearest_unorm_clamp_to_edge(float s, unsigned size, int *icoord)
  420. {
  421.    *icoord = util_ifloor( CLAMP(s, 0.5F, (float) size - 0.5F) );
  422. }
  423.  
  424.  
  425. /**
  426.  * PIPE_TEX_WRAP_CLAMP for linear sampling, unnormalized coords.
  427.  */
  428. static void
  429. wrap_linear_unorm_clamp(float s, unsigned size,
  430.                         int *icoord0, int *icoord1, float *w)
  431. {
  432.    /* Not exactly what the spec says, but it matches NVIDIA output */
  433.    float u = CLAMP(s - 0.5F, 0.0f, (float) size - 1.0f);
  434.    *icoord0 = util_ifloor(u);
  435.    *icoord1 = *icoord0 + 1;
  436.    *w = frac(u);
  437. }
  438.  
  439.  
  440. /**
  441.  * PIPE_TEX_WRAP_CLAMP_TO_BORDER for linear sampling, unnormalized coords.
  442.  */
  443. static void
  444. wrap_linear_unorm_clamp_to_border(float s, unsigned size,
  445.                                   int *icoord0, int *icoord1, float *w)
  446. {
  447.    float u = CLAMP(s, -0.5F, (float) size + 0.5F);
  448.    u -= 0.5F;
  449.    *icoord0 = util_ifloor(u);
  450.    *icoord1 = *icoord0 + 1;
  451.    if (*icoord1 > (int) size - 1)
  452.       *icoord1 = size - 1;
  453.    *w = frac(u);
  454. }
  455.  
  456.  
  457. /**
  458.  * PIPE_TEX_WRAP_CLAMP_TO_EDGE for linear sampling, unnormalized coords.
  459.  */
  460. static void
  461. wrap_linear_unorm_clamp_to_edge(float s, unsigned size,
  462.                                 int *icoord0, int *icoord1, float *w)
  463. {
  464.    float u = CLAMP(s, +0.5F, (float) size - 0.5F);
  465.    u -= 0.5F;
  466.    *icoord0 = util_ifloor(u);
  467.    *icoord1 = *icoord0 + 1;
  468.    if (*icoord1 > (int) size - 1)
  469.       *icoord1 = size - 1;
  470.    *w = frac(u);
  471. }
  472.  
  473.  
  474. /**
  475.  * Do coordinate to array index conversion.  For array textures.
  476.  */
  477. static INLINE void
  478. wrap_array_layer(float coord, unsigned size, int *layer)
  479. {
  480.    int c = util_ifloor(coord + 0.5F);
  481.    *layer = CLAMP(c, 0, (int) size - 1);
  482. }
  483.  
  484.  
  485. /**
  486.  * Examine the quad's texture coordinates to compute the partial
  487.  * derivatives w.r.t X and Y, then compute lambda (level of detail).
  488.  */
  489. static float
  490. compute_lambda_1d(const struct sp_sampler_view *sview,
  491.                   const float s[TGSI_QUAD_SIZE],
  492.                   const float t[TGSI_QUAD_SIZE],
  493.                   const float p[TGSI_QUAD_SIZE])
  494. {
  495.    const struct pipe_resource *texture = sview->base.texture;
  496.    float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
  497.    float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
  498.    float rho = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
  499.  
  500.    return util_fast_log2(rho);
  501. }
  502.  
  503.  
  504. static float
  505. compute_lambda_2d(const struct sp_sampler_view *sview,
  506.                   const float s[TGSI_QUAD_SIZE],
  507.                   const float t[TGSI_QUAD_SIZE],
  508.                   const float p[TGSI_QUAD_SIZE])
  509. {
  510.    const struct pipe_resource *texture = sview->base.texture;
  511.    float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
  512.    float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
  513.    float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
  514.    float dtdy = fabsf(t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]);
  515.    float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
  516.    float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
  517.    float rho  = MAX2(maxx, maxy);
  518.  
  519.    return util_fast_log2(rho);
  520. }
  521.  
  522.  
  523. static float
  524. compute_lambda_3d(const struct sp_sampler_view *sview,
  525.                   const float s[TGSI_QUAD_SIZE],
  526.                   const float t[TGSI_QUAD_SIZE],
  527.                   const float p[TGSI_QUAD_SIZE])
  528. {
  529.    const struct pipe_resource *texture = sview->base.texture;
  530.    float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
  531.    float dsdy = fabsf(s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]);
  532.    float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
  533.    float dtdy = fabsf(t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]);
  534.    float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]);
  535.    float dpdy = fabsf(p[QUAD_TOP_LEFT]     - p[QUAD_BOTTOM_LEFT]);
  536.    float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
  537.    float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
  538.    float maxz = MAX2(dpdx, dpdy) * u_minify(texture->depth0, sview->base.u.tex.first_level);
  539.    float rho;
  540.  
  541.    rho = MAX2(maxx, maxy);
  542.    rho = MAX2(rho, maxz);
  543.  
  544.    return util_fast_log2(rho);
  545. }
  546.  
  547.  
  548. /**
  549.  * Compute lambda for a vertex texture sampler.
  550.  * Since there aren't derivatives to use, just return 0.
  551.  */
  552. static float
  553. compute_lambda_vert(const struct sp_sampler_view *sview,
  554.                     const float s[TGSI_QUAD_SIZE],
  555.                     const float t[TGSI_QUAD_SIZE],
  556.                     const float p[TGSI_QUAD_SIZE])
  557. {
  558.    return 0.0f;
  559. }
  560.  
  561.  
  562.  
  563. /**
  564.  * Get a texel from a texture, using the texture tile cache.
  565.  *
  566.  * \param addr  the template tex address containing cube, z, face info.
  567.  * \param x  the x coord of texel within 2D image
  568.  * \param y  the y coord of texel within 2D image
  569.  * \param rgba  the quad to put the texel/color into
  570.  *
  571.  * XXX maybe move this into sp_tex_tile_cache.c and merge with the
  572.  * sp_get_cached_tile_tex() function.
  573.  */
  574.  
  575.  
  576.  
  577.  
  578. static INLINE const float *
  579. get_texel_2d_no_border(const struct sp_sampler_view *sp_sview,
  580.                        union tex_tile_address addr, int x, int y)
  581. {
  582.    const struct softpipe_tex_cached_tile *tile;
  583.    addr.bits.x = x / TEX_TILE_SIZE;
  584.    addr.bits.y = y / TEX_TILE_SIZE;
  585.    y %= TEX_TILE_SIZE;
  586.    x %= TEX_TILE_SIZE;
  587.  
  588.    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
  589.  
  590.    return &tile->data.color[y][x][0];
  591. }
  592.  
  593.  
  594. static INLINE const float *
  595. get_texel_2d(const struct sp_sampler_view *sp_sview,
  596.              const struct sp_sampler *sp_samp,
  597.              union tex_tile_address addr, int x, int y)
  598. {
  599.    const struct pipe_resource *texture = sp_sview->base.texture;
  600.    unsigned level = addr.bits.level;
  601.  
  602.    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
  603.        y < 0 || y >= (int) u_minify(texture->height0, level)) {
  604.       return sp_samp->base.border_color.f;
  605.    }
  606.    else {
  607.       return get_texel_2d_no_border( sp_sview, addr, x, y );
  608.    }
  609. }
  610.  
  611. /*
  612.  * seamless cubemap neighbour array.
  613.  * this array is used to find the adjacent face in each of 4 directions,
  614.  * left, right, up, down. (or -x, +x, -y, +y).
  615.  */
  616. static const unsigned face_array[PIPE_TEX_FACE_MAX][4] = {
  617.    /* pos X first then neg X is Z different, Y the same */
  618.    /* PIPE_TEX_FACE_POS_X,*/
  619.    { PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z,
  620.      PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
  621.    /* PIPE_TEX_FACE_NEG_X */
  622.    { PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z,
  623.      PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
  624.  
  625.    /* pos Y first then neg Y is X different, X the same */
  626.    /* PIPE_TEX_FACE_POS_Y */
  627.    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
  628.      PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z },
  629.  
  630.    /* PIPE_TEX_FACE_NEG_Y */
  631.    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
  632.      PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z },
  633.  
  634.    /* pos Z first then neg Y is X different, X the same */
  635.    /* PIPE_TEX_FACE_POS_Z */
  636.    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
  637.      PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
  638.  
  639.    /* PIPE_TEX_FACE_NEG_Z */
  640.    { PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_NEG_X,
  641.      PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y }
  642. };
  643.  
  644. static INLINE unsigned
  645. get_next_face(unsigned face, int x, int y)
  646. {
  647.    int idx = 0;
  648.  
  649.    if (x == 0 && y == 0)
  650.       return face;
  651.    if (x == -1)
  652.       idx = 0;
  653.    else if (x == 1)
  654.       idx = 1;
  655.    else if (y == -1)
  656.       idx = 2;
  657.    else if (y == 1)
  658.       idx = 3;
  659.  
  660.    return face_array[face][idx];
  661. }
  662.  
  663. static INLINE const float *
  664. get_texel_cube_seamless(const struct sp_sampler_view *sp_sview,
  665.                         union tex_tile_address addr, int x, int y,
  666.                         float *corner)
  667. {
  668.    const struct pipe_resource *texture = sp_sview->base.texture;
  669.    unsigned level = addr.bits.level;
  670.    unsigned face = addr.bits.face;
  671.    int new_x, new_y;
  672.    int max_x, max_y;
  673.    int c;
  674.  
  675.    max_x = (int) u_minify(texture->width0, level);
  676.    max_y = (int) u_minify(texture->height0, level);
  677.    new_x = x;
  678.    new_y = y;
  679.  
  680.    /* the corner case */
  681.    if ((x < 0 || x >= max_x) &&
  682.        (y < 0 || y >= max_y)) {
  683.       const float *c1, *c2, *c3;
  684.       int fx = x < 0 ? 0 : max_x - 1;
  685.       int fy = y < 0 ? 0 : max_y - 1;
  686.       c1 = get_texel_2d_no_border( sp_sview, addr, fx, fy);
  687.       addr.bits.face = get_next_face(face, (x < 0) ? -1 : 1, 0);
  688.       c2 = get_texel_2d_no_border( sp_sview, addr, (x < 0) ? max_x - 1 : 0, fy);
  689.       addr.bits.face = get_next_face(face, 0, (y < 0) ? -1 : 1);
  690.       c3 = get_texel_2d_no_border( sp_sview, addr, fx, (y < 0) ?  max_y - 1 : 0);
  691.       for (c = 0; c < TGSI_QUAD_SIZE; c++)
  692.          corner[c] = CLAMP((c1[c] + c2[c] + c3[c]), 0.0F, 1.0F) / 3;
  693.  
  694.       return corner;
  695.    }
  696.    /* change the face */
  697.    if (x < 0) {
  698.       new_x = max_x - 1;
  699.       face = get_next_face(face, -1, 0);
  700.    } else if (x >= max_x) {
  701.       new_x = 0;
  702.       face = get_next_face(face, 1, 0);
  703.    } else if (y < 0) {
  704.       new_y = max_y - 1;
  705.       face = get_next_face(face, 0, -1);
  706.    } else if (y >= max_y) {
  707.       new_y = 0;
  708.       face = get_next_face(face, 0, 1);
  709.    }
  710.  
  711.    addr.bits.face = face;
  712.    return get_texel_2d_no_border( sp_sview, addr, new_x, new_y );
  713. }
  714.  
  715. /* Gather a quad of adjacent texels within a tile:
  716.  */
  717. static INLINE void
  718. get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_view *sp_sview,
  719.                                         union tex_tile_address addr,
  720.                                         unsigned x, unsigned y,
  721.                                         const float *out[4])
  722. {
  723.     const struct softpipe_tex_cached_tile *tile;
  724.  
  725.    addr.bits.x = x / TEX_TILE_SIZE;
  726.    addr.bits.y = y / TEX_TILE_SIZE;
  727.    y %= TEX_TILE_SIZE;
  728.    x %= TEX_TILE_SIZE;
  729.  
  730.    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
  731.      
  732.    out[0] = &tile->data.color[y  ][x  ][0];
  733.    out[1] = &tile->data.color[y  ][x+1][0];
  734.    out[2] = &tile->data.color[y+1][x  ][0];
  735.    out[3] = &tile->data.color[y+1][x+1][0];
  736. }
  737.  
  738.  
  739. /* Gather a quad of potentially non-adjacent texels:
  740.  */
  741. static INLINE void
  742. get_texel_quad_2d_no_border(const struct sp_sampler_view *sp_sview,
  743.                             union tex_tile_address addr,
  744.                             int x0, int y0,
  745.                             int x1, int y1,
  746.                             const float *out[4])
  747. {
  748.    out[0] = get_texel_2d_no_border( sp_sview, addr, x0, y0 );
  749.    out[1] = get_texel_2d_no_border( sp_sview, addr, x1, y0 );
  750.    out[2] = get_texel_2d_no_border( sp_sview, addr, x0, y1 );
  751.    out[3] = get_texel_2d_no_border( sp_sview, addr, x1, y1 );
  752. }
  753.  
  754. /* Can involve a lot of unnecessary checks for border color:
  755.  */
  756. static INLINE void
  757. get_texel_quad_2d(const struct sp_sampler_view *sp_sview,
  758.                   const struct sp_sampler *sp_samp,
  759.                   union tex_tile_address addr,
  760.                   int x0, int y0,
  761.                   int x1, int y1,
  762.                   const float *out[4])
  763. {
  764.    out[0] = get_texel_2d( sp_sview, sp_samp, addr, x0, y0 );
  765.    out[1] = get_texel_2d( sp_sview, sp_samp, addr, x1, y0 );
  766.    out[3] = get_texel_2d( sp_sview, sp_samp, addr, x1, y1 );
  767.    out[2] = get_texel_2d( sp_sview, sp_samp, addr, x0, y1 );
  768. }
  769.  
  770.  
  771.  
  772. /* 3d variants:
  773.  */
  774. static INLINE const float *
  775. get_texel_3d_no_border(const struct sp_sampler_view *sp_sview,
  776.                        union tex_tile_address addr, int x, int y, int z)
  777. {
  778.    const struct softpipe_tex_cached_tile *tile;
  779.  
  780.    addr.bits.x = x / TEX_TILE_SIZE;
  781.    addr.bits.y = y / TEX_TILE_SIZE;
  782.    addr.bits.z = z;
  783.    y %= TEX_TILE_SIZE;
  784.    x %= TEX_TILE_SIZE;
  785.  
  786.    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
  787.  
  788.    return &tile->data.color[y][x][0];
  789. }
  790.  
  791.  
  792. static INLINE const float *
  793. get_texel_3d(const struct sp_sampler_view *sp_sview,
  794.              const struct sp_sampler *sp_samp,
  795.              union tex_tile_address addr, int x, int y, int z)
  796. {
  797.    const struct pipe_resource *texture = sp_sview->base.texture;
  798.    unsigned level = addr.bits.level;
  799.  
  800.    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
  801.        y < 0 || y >= (int) u_minify(texture->height0, level) ||
  802.        z < 0 || z >= (int) u_minify(texture->depth0, level)) {
  803.       return sp_samp->base.border_color.f;
  804.    }
  805.    else {
  806.       return get_texel_3d_no_border( sp_sview, addr, x, y, z );
  807.    }
  808. }
  809.  
  810.  
  811. /* Get texel pointer for 1D array texture */
  812. static INLINE const float *
  813. get_texel_1d_array(const struct sp_sampler_view *sp_sview,
  814.                    const struct sp_sampler *sp_samp,
  815.                    union tex_tile_address addr, int x, int y)
  816. {
  817.    const struct pipe_resource *texture = sp_sview->base.texture;
  818.    unsigned level = addr.bits.level;
  819.  
  820.    if (x < 0 || x >= (int) u_minify(texture->width0, level)) {
  821.       return sp_samp->base.border_color.f;
  822.    }
  823.    else {
  824.       return get_texel_2d_no_border(sp_sview, addr, x, y);
  825.    }
  826. }
  827.  
  828.  
  829. /* Get texel pointer for 2D array texture */
  830. static INLINE const float *
  831. get_texel_2d_array(const struct sp_sampler_view *sp_sview,
  832.                    const struct sp_sampler *sp_samp,
  833.                    union tex_tile_address addr, int x, int y, int layer)
  834. {
  835.    const struct pipe_resource *texture = sp_sview->base.texture;
  836.    unsigned level = addr.bits.level;
  837.  
  838.    assert(layer < (int) texture->array_size);
  839.    assert(layer >= 0);
  840.  
  841.    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
  842.        y < 0 || y >= (int) u_minify(texture->height0, level)) {
  843.       return sp_samp->base.border_color.f;
  844.    }
  845.    else {
  846.       return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
  847.    }
  848. }
  849.  
  850.  
  851. /* Get texel pointer for cube array texture */
  852. static INLINE const float *
  853. get_texel_cube_array(const struct sp_sampler_view *sp_sview,
  854.                      const struct sp_sampler *sp_samp,
  855.                      union tex_tile_address addr, int x, int y, int layer)
  856. {
  857.    const struct pipe_resource *texture = sp_sview->base.texture;
  858.    unsigned level = addr.bits.level;
  859.  
  860.    assert(layer < (int) texture->array_size);
  861.    assert(layer >= 0);
  862.  
  863.    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
  864.        y < 0 || y >= (int) u_minify(texture->height0, level)) {
  865.       return sp_samp->base.border_color.f;
  866.    }
  867.    else {
  868.       return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
  869.    }
  870. }
  871. /**
  872.  * Given the logbase2 of a mipmap's base level size and a mipmap level,
  873.  * return the size (in texels) of that mipmap level.
  874.  * For example, if level[0].width = 256 then base_pot will be 8.
  875.  * If level = 2, then we'll return 64 (the width at level=2).
  876.  * Return 1 if level > base_pot.
  877.  */
  878. static INLINE unsigned
  879. pot_level_size(unsigned base_pot, unsigned level)
  880. {
  881.    return (base_pot >= level) ? (1 << (base_pot - level)) : 1;
  882. }
  883.  
  884.  
  885. static void
  886. print_sample(const char *function, const float *rgba)
  887. {
  888.    debug_printf("%s %g %g %g %g\n",
  889.                 function,
  890.                 rgba[0], rgba[TGSI_NUM_CHANNELS], rgba[2*TGSI_NUM_CHANNELS], rgba[3*TGSI_NUM_CHANNELS]);
  891. }
  892.  
  893.  
  894. static void
  895. print_sample_4(const char *function, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  896. {
  897.    debug_printf("%s %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n",
  898.                 function,
  899.                 rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0],
  900.                 rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1],
  901.                 rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2],
  902.                 rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]);
  903. }
  904.  
  905.  
  906. /* Some image-filter fastpaths:
  907.  */
  908. static INLINE void
  909. img_filter_2d_linear_repeat_POT(struct sp_sampler_view *sp_sview,
  910.                                 struct sp_sampler *sp_samp,
  911.                                 float s,
  912.                                 float t,
  913.                                 float p,
  914.                                 unsigned level,
  915.                                 unsigned face_id,
  916.                                 float *rgba)
  917. {
  918.    unsigned xpot = pot_level_size(sp_sview->xpot, level);
  919.    unsigned ypot = pot_level_size(sp_sview->ypot, level);
  920.    int xmax = (xpot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, xpot) - 1; */
  921.    int ymax = (ypot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, ypot) - 1; */
  922.    union tex_tile_address addr;
  923.    int c;
  924.  
  925.    float u = s * xpot - 0.5F;
  926.    float v = t * ypot - 0.5F;
  927.  
  928.    int uflr = util_ifloor(u);
  929.    int vflr = util_ifloor(v);
  930.  
  931.    float xw = u - (float)uflr;
  932.    float yw = v - (float)vflr;
  933.  
  934.    int x0 = uflr & (xpot - 1);
  935.    int y0 = vflr & (ypot - 1);
  936.  
  937.    const float *tx[4];
  938.      
  939.    addr.value = 0;
  940.    addr.bits.level = level;
  941.  
  942.    /* Can we fetch all four at once:
  943.     */
  944.    if (x0 < xmax && y0 < ymax) {
  945.       get_texel_quad_2d_no_border_single_tile(sp_sview, addr, x0, y0, tx);
  946.    }
  947.    else {
  948.       unsigned x1 = (x0 + 1) & (xpot - 1);
  949.       unsigned y1 = (y0 + 1) & (ypot - 1);
  950.       get_texel_quad_2d_no_border(sp_sview, addr, x0, y0, x1, y1, tx);
  951.    }
  952.  
  953.    /* interpolate R, G, B, A */
  954.    for (c = 0; c < TGSI_QUAD_SIZE; c++) {
  955.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  956.                                        tx[0][c], tx[1][c],
  957.                                        tx[2][c], tx[3][c]);
  958.    }
  959.  
  960.    if (DEBUG_TEX) {
  961.       print_sample(__FUNCTION__, rgba);
  962.    }
  963. }
  964.  
  965.  
  966. static INLINE void
  967. img_filter_2d_nearest_repeat_POT(struct sp_sampler_view *sp_sview,
  968.                                  struct sp_sampler *sp_samp,
  969.                                  float s,
  970.                                  float t,
  971.                                  float p,
  972.                                  unsigned level,
  973.                                  unsigned face_id,
  974.                                  float rgba[TGSI_QUAD_SIZE])
  975. {
  976.    unsigned xpot = pot_level_size(sp_sview->xpot, level);
  977.    unsigned ypot = pot_level_size(sp_sview->ypot, level);
  978.    const float *out;
  979.    union tex_tile_address addr;
  980.    int c;
  981.  
  982.    float u = s * xpot;
  983.    float v = t * ypot;
  984.  
  985.    int uflr = util_ifloor(u);
  986.    int vflr = util_ifloor(v);
  987.  
  988.    int x0 = uflr & (xpot - 1);
  989.    int y0 = vflr & (ypot - 1);
  990.  
  991.    addr.value = 0;
  992.    addr.bits.level = level;
  993.  
  994.    out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
  995.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  996.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  997.  
  998.    if (DEBUG_TEX) {
  999.       print_sample(__FUNCTION__, rgba);
  1000.    }
  1001. }
  1002.  
  1003.  
  1004. static INLINE void
  1005. img_filter_2d_nearest_clamp_POT(struct sp_sampler_view *sp_sview,
  1006.                                 struct sp_sampler *sp_samp,
  1007.                                 float s,
  1008.                                 float t,
  1009.                                 float p,
  1010.                                 unsigned level,
  1011.                                 unsigned face_id,
  1012.                                 float rgba[TGSI_QUAD_SIZE])
  1013. {
  1014.    unsigned xpot = pot_level_size(sp_sview->xpot, level);
  1015.    unsigned ypot = pot_level_size(sp_sview->ypot, level);
  1016.    union tex_tile_address addr;
  1017.    int c;
  1018.  
  1019.    float u = s * xpot;
  1020.    float v = t * ypot;
  1021.  
  1022.    int x0, y0;
  1023.    const float *out;
  1024.  
  1025.    addr.value = 0;
  1026.    addr.bits.level = level;
  1027.  
  1028.    x0 = util_ifloor(u);
  1029.    if (x0 < 0)
  1030.       x0 = 0;
  1031.    else if (x0 > (int) xpot - 1)
  1032.       x0 = xpot - 1;
  1033.  
  1034.    y0 = util_ifloor(v);
  1035.    if (y0 < 0)
  1036.       y0 = 0;
  1037.    else if (y0 > (int) ypot - 1)
  1038.       y0 = ypot - 1;
  1039.    
  1040.    out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
  1041.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1042.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1043.  
  1044.    if (DEBUG_TEX) {
  1045.       print_sample(__FUNCTION__, rgba);
  1046.    }
  1047. }
  1048.  
  1049.  
  1050. static void
  1051. img_filter_1d_nearest(struct sp_sampler_view *sp_sview,
  1052.                       struct sp_sampler *sp_samp,
  1053.                       float s,
  1054.                       float t,
  1055.                       float p,
  1056.                       unsigned level,
  1057.                       unsigned face_id,
  1058.                       float rgba[TGSI_QUAD_SIZE])
  1059. {
  1060.    const struct pipe_resource *texture = sp_sview->base.texture;
  1061.    int width;
  1062.    int x;
  1063.    union tex_tile_address addr;
  1064.    const float *out;
  1065.    int c;
  1066.  
  1067.    width = u_minify(texture->width0, level);
  1068.  
  1069.    assert(width > 0);
  1070.  
  1071.    addr.value = 0;
  1072.    addr.bits.level = level;
  1073.  
  1074.    sp_samp->nearest_texcoord_s(s, width, &x);
  1075.  
  1076.    out = get_texel_2d(sp_sview, sp_samp, addr, x, 0);
  1077.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1078.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1079.  
  1080.    if (DEBUG_TEX) {
  1081.       print_sample(__FUNCTION__, rgba);
  1082.    }
  1083. }
  1084.  
  1085.  
  1086. static void
  1087. img_filter_1d_array_nearest(struct sp_sampler_view *sp_sview,
  1088.                             struct sp_sampler *sp_samp,
  1089.                             float s,
  1090.                             float t,
  1091.                             float p,
  1092.                             unsigned level,
  1093.                             unsigned face_id,
  1094.                             float *rgba)
  1095. {
  1096.    const struct pipe_resource *texture = sp_sview->base.texture;
  1097.    int width;
  1098.    int x, layer;
  1099.    union tex_tile_address addr;
  1100.    const float *out;
  1101.    int c;
  1102.  
  1103.    width = u_minify(texture->width0, level);
  1104.  
  1105.    assert(width > 0);
  1106.  
  1107.    addr.value = 0;
  1108.    addr.bits.level = level;
  1109.  
  1110.    sp_samp->nearest_texcoord_s(s, width, &x);
  1111.    wrap_array_layer(t, texture->array_size, &layer);
  1112.  
  1113.    out = get_texel_1d_array(sp_sview, sp_samp, addr, x, layer);
  1114.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1115.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1116.  
  1117.    if (DEBUG_TEX) {
  1118.       print_sample(__FUNCTION__, rgba);
  1119.    }
  1120. }
  1121.  
  1122.  
  1123. static void
  1124. img_filter_2d_nearest(struct sp_sampler_view *sp_sview,
  1125.                       struct sp_sampler *sp_samp,
  1126.                       float s,
  1127.                       float t,
  1128.                       float p,
  1129.                       unsigned level,
  1130.                       unsigned face_id,
  1131.                       float *rgba)
  1132. {
  1133.    const struct pipe_resource *texture = sp_sview->base.texture;
  1134.    int width, height;
  1135.    int x, y;
  1136.    union tex_tile_address addr;
  1137.    const float *out;
  1138.    int c;
  1139.  
  1140.    width = u_minify(texture->width0, level);
  1141.    height = u_minify(texture->height0, level);
  1142.  
  1143.    assert(width > 0);
  1144.    assert(height > 0);
  1145.  
  1146.    addr.value = 0;
  1147.    addr.bits.level = level;
  1148.  
  1149.    sp_samp->nearest_texcoord_s(s, width, &x);
  1150.    sp_samp->nearest_texcoord_t(t, height, &y);
  1151.  
  1152.    out = get_texel_2d(sp_sview, sp_samp, addr, x, y);
  1153.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1154.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1155.  
  1156.    if (DEBUG_TEX) {
  1157.       print_sample(__FUNCTION__, rgba);
  1158.    }
  1159. }
  1160.  
  1161.  
  1162. static void
  1163. img_filter_2d_array_nearest(struct sp_sampler_view *sp_sview,
  1164.                             struct sp_sampler *sp_samp,
  1165.                             float s,
  1166.                             float t,
  1167.                             float p,
  1168.                             unsigned level,
  1169.                             unsigned face_id,
  1170.                             float *rgba)
  1171. {
  1172.    const struct pipe_resource *texture = sp_sview->base.texture;
  1173.    int width, height;
  1174.    int x, y, layer;
  1175.    union tex_tile_address addr;
  1176.    const float *out;
  1177.    int c;
  1178.  
  1179.    width = u_minify(texture->width0, level);
  1180.    height = u_minify(texture->height0, level);
  1181.  
  1182.    assert(width > 0);
  1183.    assert(height > 0);
  1184.  
  1185.    addr.value = 0;
  1186.    addr.bits.level = level;
  1187.  
  1188.    sp_samp->nearest_texcoord_s(s, width, &x);
  1189.    sp_samp->nearest_texcoord_t(t, height, &y);
  1190.    wrap_array_layer(p, texture->array_size, &layer);
  1191.  
  1192.    out = get_texel_2d_array(sp_sview, sp_samp, addr, x, y, layer);
  1193.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1194.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1195.  
  1196.    if (DEBUG_TEX) {
  1197.       print_sample(__FUNCTION__, rgba);
  1198.    }
  1199. }
  1200.  
  1201.  
  1202. static INLINE union tex_tile_address
  1203. face(union tex_tile_address addr, unsigned face )
  1204. {
  1205.    addr.bits.face = face;
  1206.    return addr;
  1207. }
  1208.  
  1209.  
  1210. static void
  1211. img_filter_cube_nearest(struct sp_sampler_view *sp_sview,
  1212.                         struct sp_sampler *sp_samp,
  1213.                         float s,
  1214.                         float t,
  1215.                         float p,
  1216.                         unsigned level,
  1217.                         unsigned face_id,
  1218.                         float *rgba)
  1219. {
  1220.    const struct pipe_resource *texture = sp_sview->base.texture;
  1221.    int width, height;
  1222.    int x, y;
  1223.    union tex_tile_address addr;
  1224.    const float *out;
  1225.    int c;
  1226.  
  1227.    width = u_minify(texture->width0, level);
  1228.    height = u_minify(texture->height0, level);
  1229.  
  1230.    assert(width > 0);
  1231.    assert(height > 0);
  1232.  
  1233.    addr.value = 0;
  1234.    addr.bits.level = level;
  1235.  
  1236.    /*
  1237.     * If NEAREST filtering is done within a miplevel, always apply wrap
  1238.     * mode CLAMP_TO_EDGE.
  1239.     */
  1240.    if (sp_samp->base.seamless_cube_map) {
  1241.       wrap_nearest_clamp_to_edge(s, width, &x);
  1242.       wrap_nearest_clamp_to_edge(t, height, &y);
  1243.    } else {
  1244.       sp_samp->nearest_texcoord_s(s, width, &x);
  1245.       sp_samp->nearest_texcoord_t(t, height, &y);
  1246.    }
  1247.  
  1248.    out = get_texel_2d(sp_sview, sp_samp, face(addr, face_id), x, y);
  1249.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1250.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1251.  
  1252.    if (DEBUG_TEX) {
  1253.       print_sample(__FUNCTION__, rgba);
  1254.    }
  1255. }
  1256.  
  1257. static void
  1258. img_filter_cube_array_nearest(struct sp_sampler_view *sp_sview,
  1259.                               struct sp_sampler *sp_samp,
  1260.                               float s,
  1261.                               float t,
  1262.                               float p,
  1263.                               unsigned level,
  1264.                               unsigned face_id,
  1265.                               float *rgba)
  1266. {
  1267.    const struct pipe_resource *texture = sp_sview->base.texture;
  1268.    int width, height;
  1269.    int x, y, layer;
  1270.    union tex_tile_address addr;
  1271.    const float *out;
  1272.    int c;
  1273.  
  1274.    width = u_minify(texture->width0, level);
  1275.    height = u_minify(texture->height0, level);
  1276.  
  1277.    assert(width > 0);
  1278.    assert(height > 0);
  1279.  
  1280.    addr.value = 0;
  1281.    addr.bits.level = level;
  1282.  
  1283.    sp_samp->nearest_texcoord_s(s, width, &x);
  1284.    sp_samp->nearest_texcoord_t(t, height, &y);
  1285.    wrap_array_layer(p, texture->array_size, &layer);
  1286.  
  1287.    out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layer * 6 + face_id);
  1288.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1289.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1290.  
  1291.    if (DEBUG_TEX) {
  1292.       print_sample(__FUNCTION__, rgba);
  1293.    }
  1294. }
  1295.  
  1296. static void
  1297. img_filter_3d_nearest(struct sp_sampler_view *sp_sview,
  1298.                       struct sp_sampler *sp_samp,
  1299.                       float s,
  1300.                       float t,
  1301.                       float p,
  1302.                       unsigned level,
  1303.                       unsigned face_id,
  1304.                       float *rgba)
  1305. {
  1306.    const struct pipe_resource *texture = sp_sview->base.texture;
  1307.    int width, height, depth;
  1308.    int x, y, z;
  1309.    union tex_tile_address addr;
  1310.    const float *out;
  1311.    int c;
  1312.  
  1313.    width = u_minify(texture->width0, level);
  1314.    height = u_minify(texture->height0, level);
  1315.    depth = u_minify(texture->depth0, level);
  1316.  
  1317.    assert(width > 0);
  1318.    assert(height > 0);
  1319.    assert(depth > 0);
  1320.  
  1321.    sp_samp->nearest_texcoord_s(s, width,  &x);
  1322.    sp_samp->nearest_texcoord_t(t, height, &y);
  1323.    sp_samp->nearest_texcoord_p(p, depth,  &z);
  1324.  
  1325.    addr.value = 0;
  1326.    addr.bits.level = level;
  1327.  
  1328.    out = get_texel_3d(sp_sview, sp_samp, addr, x, y, z);
  1329.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1330.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1331. }
  1332.  
  1333.  
  1334. static void
  1335. img_filter_1d_linear(struct sp_sampler_view *sp_sview,
  1336.                      struct sp_sampler *sp_samp,
  1337.                      float s,
  1338.                      float t,
  1339.                      float p,
  1340.                      unsigned level,
  1341.                      unsigned face_id,
  1342.                      float *rgba)
  1343. {
  1344.    const struct pipe_resource *texture = sp_sview->base.texture;
  1345.    int width;
  1346.    int x0, x1;
  1347.    float xw; /* weights */
  1348.    union tex_tile_address addr;
  1349.    const float *tx0, *tx1;
  1350.    int c;
  1351.  
  1352.    width = u_minify(texture->width0, level);
  1353.  
  1354.    assert(width > 0);
  1355.  
  1356.    addr.value = 0;
  1357.    addr.bits.level = level;
  1358.  
  1359.    sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
  1360.  
  1361.    tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, 0);
  1362.    tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, 0);
  1363.  
  1364.    /* interpolate R, G, B, A */
  1365.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1366.       rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
  1367. }
  1368.  
  1369.  
  1370. static void
  1371. img_filter_1d_array_linear(struct sp_sampler_view *sp_sview,
  1372.                            struct sp_sampler *sp_samp,
  1373.                            float s,
  1374.                            float t,
  1375.                            float p,
  1376.                            unsigned level,
  1377.                            unsigned face_id,
  1378.                            float *rgba)
  1379. {
  1380.    const struct pipe_resource *texture = sp_sview->base.texture;
  1381.    int width;
  1382.    int x0, x1, layer;
  1383.    float xw; /* weights */
  1384.    union tex_tile_address addr;
  1385.    const float *tx0, *tx1;
  1386.    int c;
  1387.  
  1388.    width = u_minify(texture->width0, level);
  1389.  
  1390.    assert(width > 0);
  1391.  
  1392.    addr.value = 0;
  1393.    addr.bits.level = level;
  1394.  
  1395.    sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
  1396.    wrap_array_layer(t, texture->array_size, &layer);
  1397.  
  1398.    tx0 = get_texel_1d_array(sp_sview, sp_samp, addr, x0, layer);
  1399.    tx1 = get_texel_1d_array(sp_sview, sp_samp, addr, x1, layer);
  1400.  
  1401.    /* interpolate R, G, B, A */
  1402.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1403.       rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
  1404. }
  1405.  
  1406.  
  1407. static void
  1408. img_filter_2d_linear(struct sp_sampler_view *sp_sview,
  1409.                      struct sp_sampler *sp_samp,
  1410.                      float s,
  1411.                      float t,
  1412.                      float p,
  1413.                      unsigned level,
  1414.                      unsigned face_id,
  1415.                      float *rgba)
  1416. {
  1417.    const struct pipe_resource *texture = sp_sview->base.texture;
  1418.    int width, height;
  1419.    int x0, y0, x1, y1;
  1420.    float xw, yw; /* weights */
  1421.    union tex_tile_address addr;
  1422.    const float *tx0, *tx1, *tx2, *tx3;
  1423.    int c;
  1424.  
  1425.    width = u_minify(texture->width0, level);
  1426.    height = u_minify(texture->height0, level);
  1427.  
  1428.    assert(width > 0);
  1429.    assert(height > 0);
  1430.  
  1431.    addr.value = 0;
  1432.    addr.bits.level = level;
  1433.  
  1434.    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1435.    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1436.  
  1437.    tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, y0);
  1438.    tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, y0);
  1439.    tx2 = get_texel_2d(sp_sview, sp_samp, addr, x0, y1);
  1440.    tx3 = get_texel_2d(sp_sview, sp_samp, addr, x1, y1);
  1441.  
  1442.    /* interpolate R, G, B, A */
  1443.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1444.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  1445.                                           tx0[c], tx1[c],
  1446.                                           tx2[c], tx3[c]);
  1447. }
  1448.  
  1449.  
  1450. static void
  1451. img_filter_2d_array_linear(struct sp_sampler_view *sp_sview,
  1452.                            struct sp_sampler *sp_samp,
  1453.                            float s,
  1454.                            float t,
  1455.                            float p,
  1456.                            unsigned level,
  1457.                            unsigned face_id,
  1458.                            float *rgba)
  1459. {
  1460.    const struct pipe_resource *texture = sp_sview->base.texture;
  1461.    int width, height;
  1462.    int x0, y0, x1, y1, layer;
  1463.    float xw, yw; /* weights */
  1464.    union tex_tile_address addr;
  1465.    const float *tx0, *tx1, *tx2, *tx3;
  1466.    int c;
  1467.  
  1468.    width = u_minify(texture->width0, level);
  1469.    height = u_minify(texture->height0, level);
  1470.  
  1471.    assert(width > 0);
  1472.    assert(height > 0);
  1473.  
  1474.    addr.value = 0;
  1475.    addr.bits.level = level;
  1476.  
  1477.    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1478.    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1479.    wrap_array_layer(p, texture->array_size, &layer);
  1480.  
  1481.    tx0 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y0, layer);
  1482.    tx1 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y0, layer);
  1483.    tx2 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y1, layer);
  1484.    tx3 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y1, layer);
  1485.  
  1486.    /* interpolate R, G, B, A */
  1487.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1488.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  1489.                                           tx0[c], tx1[c],
  1490.                                           tx2[c], tx3[c]);
  1491. }
  1492.  
  1493.  
  1494. static void
  1495. img_filter_cube_linear(struct sp_sampler_view *sp_sview,
  1496.                        struct sp_sampler *sp_samp,
  1497.                        float s,
  1498.                        float t,
  1499.                        float p,
  1500.                        unsigned level,
  1501.                        unsigned face_id,
  1502.                        float *rgba)
  1503. {
  1504.    const struct pipe_resource *texture = sp_sview->base.texture;
  1505.    int width, height;
  1506.    int x0, y0, x1, y1;
  1507.    float xw, yw; /* weights */
  1508.    union tex_tile_address addr, addrj;
  1509.    const float *tx0, *tx1, *tx2, *tx3;
  1510.    float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE],
  1511.          corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
  1512.    int c;
  1513.  
  1514.    width = u_minify(texture->width0, level);
  1515.    height = u_minify(texture->height0, level);
  1516.  
  1517.    assert(width > 0);
  1518.    assert(height > 0);
  1519.  
  1520.    addr.value = 0;
  1521.    addr.bits.level = level;
  1522.  
  1523.    /*
  1524.     * For seamless if LINEAR filtering is done within a miplevel,
  1525.     * always apply wrap mode CLAMP_TO_BORDER.
  1526.     */
  1527.    if (sp_samp->base.seamless_cube_map) {
  1528.       wrap_linear_clamp_to_border(s, width, &x0, &x1, &xw);
  1529.       wrap_linear_clamp_to_border(t, height, &y0, &y1, &yw);
  1530.    } else {
  1531.       sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1532.       sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1533.    }
  1534.  
  1535.    addrj = face(addr, face_id);
  1536.  
  1537.    if (sp_samp->base.seamless_cube_map) {
  1538.       tx0 = get_texel_cube_seamless(sp_sview, addrj, x0, y0, corner0);
  1539.       tx1 = get_texel_cube_seamless(sp_sview, addrj, x1, y0, corner1);
  1540.       tx2 = get_texel_cube_seamless(sp_sview, addrj, x0, y1, corner2);
  1541.       tx3 = get_texel_cube_seamless(sp_sview, addrj, x1, y1, corner3);
  1542.    } else {
  1543.       tx0 = get_texel_2d(sp_sview, sp_samp, addrj, x0, y0);
  1544.       tx1 = get_texel_2d(sp_sview, sp_samp, addrj, x1, y0);
  1545.       tx2 = get_texel_2d(sp_sview, sp_samp, addrj, x0, y1);
  1546.       tx3 = get_texel_2d(sp_sview, sp_samp, addrj, x1, y1);
  1547.    }
  1548.    /* interpolate R, G, B, A */
  1549.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1550.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  1551.                                           tx0[c], tx1[c],
  1552.                                           tx2[c], tx3[c]);
  1553. }
  1554.  
  1555.  
  1556. static void
  1557. img_filter_cube_array_linear(struct sp_sampler_view *sp_sview,
  1558.                              struct sp_sampler *sp_samp,
  1559.                              float s,
  1560.                              float t,
  1561.                              float p,
  1562.                              unsigned level,
  1563.                              unsigned face_id,
  1564.                              float *rgba)
  1565. {
  1566.    const struct pipe_resource *texture = sp_sview->base.texture;
  1567.    int width, height;
  1568.    int x0, y0, x1, y1, layer;
  1569.    float xw, yw; /* weights */
  1570.    union tex_tile_address addr;
  1571.    const float *tx0, *tx1, *tx2, *tx3;
  1572.    int c;
  1573.  
  1574.    width = u_minify(texture->width0, level);
  1575.    height = u_minify(texture->height0, level);
  1576.  
  1577.    assert(width > 0);
  1578.    assert(height > 0);
  1579.  
  1580.    addr.value = 0;
  1581.    addr.bits.level = level;
  1582.  
  1583.    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1584.    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1585.    wrap_array_layer(p, texture->array_size, &layer);
  1586.  
  1587.    tx0 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer * 6 + face_id);
  1588.    tx1 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer * 6 + face_id);
  1589.    tx2 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer * 6 + face_id);
  1590.    tx3 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer * 6 + face_id);
  1591.  
  1592.    /* interpolate R, G, B, A */
  1593.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1594.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  1595.                                           tx0[c], tx1[c],
  1596.                                           tx2[c], tx3[c]);
  1597. }
  1598.  
  1599. static void
  1600. img_filter_3d_linear(struct sp_sampler_view *sp_sview,
  1601.                      struct sp_sampler *sp_samp,
  1602.                      float s,
  1603.                      float t,
  1604.                      float p,
  1605.                      unsigned level,
  1606.                      unsigned face_id,
  1607.                      float *rgba)
  1608. {
  1609.    const struct pipe_resource *texture = sp_sview->base.texture;
  1610.    int width, height, depth;
  1611.    int x0, x1, y0, y1, z0, z1;
  1612.    float xw, yw, zw; /* interpolation weights */
  1613.    union tex_tile_address addr;
  1614.    const float *tx00, *tx01, *tx02, *tx03, *tx10, *tx11, *tx12, *tx13;
  1615.    int c;
  1616.  
  1617.    width = u_minify(texture->width0, level);
  1618.    height = u_minify(texture->height0, level);
  1619.    depth = u_minify(texture->depth0, level);
  1620.  
  1621.    addr.value = 0;
  1622.    addr.bits.level = level;
  1623.  
  1624.    assert(width > 0);
  1625.    assert(height > 0);
  1626.    assert(depth > 0);
  1627.  
  1628.    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1629.    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1630.    sp_samp->linear_texcoord_p(p, depth,  &z0, &z1, &zw);
  1631.  
  1632.  
  1633.    tx00 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z0);
  1634.    tx01 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z0);
  1635.    tx02 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z0);
  1636.    tx03 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z0);
  1637.      
  1638.    tx10 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z1);
  1639.    tx11 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z1);
  1640.    tx12 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z1);
  1641.    tx13 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z1);
  1642.      
  1643.       /* interpolate R, G, B, A */
  1644.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1645.       rgba[TGSI_NUM_CHANNELS*c] =  lerp_3d(xw, yw, zw,
  1646.                                            tx00[c], tx01[c],
  1647.                                            tx02[c], tx03[c],
  1648.                                            tx10[c], tx11[c],
  1649.                                            tx12[c], tx13[c]);
  1650. }
  1651.  
  1652.  
  1653. /* Calculate level of detail for every fragment,
  1654.  * with lambda already computed.
  1655.  * Note that lambda has already been biased by global LOD bias.
  1656.  * \param biased_lambda per-quad lambda.
  1657.  * \param lod_in per-fragment lod_bias or explicit_lod.
  1658.  * \param lod returns the per-fragment lod.
  1659.  */
  1660. static INLINE void
  1661. compute_lod(const struct pipe_sampler_state *sampler,
  1662.             enum tgsi_sampler_control control,
  1663.             const float biased_lambda,
  1664.             const float lod_in[TGSI_QUAD_SIZE],
  1665.             float lod[TGSI_QUAD_SIZE])
  1666. {
  1667.    float min_lod = sampler->min_lod;
  1668.    float max_lod = sampler->max_lod;
  1669.    uint i;
  1670.  
  1671.    switch (control) {
  1672.    case tgsi_sampler_lod_none:
  1673.    case tgsi_sampler_lod_zero:
  1674.    /* XXX FIXME */
  1675.    case tgsi_sampler_derivs_explicit:
  1676.       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(biased_lambda, min_lod, max_lod);
  1677.       break;
  1678.    case tgsi_sampler_lod_bias:
  1679.       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  1680.          lod[i] = biased_lambda + lod_in[i];
  1681.          lod[i] = CLAMP(lod[i], min_lod, max_lod);
  1682.       }
  1683.       break;
  1684.    case tgsi_sampler_lod_explicit:
  1685.       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  1686.          lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
  1687.       }
  1688.       break;
  1689.    default:
  1690.       assert(0);
  1691.       lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
  1692.    }
  1693. }
  1694.  
  1695.  
  1696. /* Calculate level of detail for every fragment.
  1697.  * \param lod_in per-fragment lod_bias or explicit_lod.
  1698.  * \param lod results per-fragment lod.
  1699.  */
  1700. static INLINE void
  1701. compute_lambda_lod(struct sp_sampler_view *sp_sview,
  1702.                    struct sp_sampler *sp_samp,
  1703.                    const float s[TGSI_QUAD_SIZE],
  1704.                    const float t[TGSI_QUAD_SIZE],
  1705.                    const float p[TGSI_QUAD_SIZE],
  1706.                    const float lod_in[TGSI_QUAD_SIZE],
  1707.                    enum tgsi_sampler_control control,
  1708.                    float lod[TGSI_QUAD_SIZE])
  1709. {
  1710.    const struct pipe_sampler_state *sampler = &sp_samp->base;
  1711.    float lod_bias = sampler->lod_bias;
  1712.    float min_lod = sampler->min_lod;
  1713.    float max_lod = sampler->max_lod;
  1714.    float lambda;
  1715.    uint i;
  1716.  
  1717.    switch (control) {
  1718.    case tgsi_sampler_lod_none:
  1719.       /* XXX FIXME */
  1720.    case tgsi_sampler_derivs_explicit:
  1721.       lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
  1722.       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lambda, min_lod, max_lod);
  1723.       break;
  1724.    case tgsi_sampler_lod_bias:
  1725.       lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
  1726.       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  1727.          lod[i] = lambda + lod_in[i];
  1728.          lod[i] = CLAMP(lod[i], min_lod, max_lod);
  1729.       }
  1730.       break;
  1731.    case tgsi_sampler_lod_explicit:
  1732.       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  1733.          lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
  1734.       }
  1735.       break;
  1736.    case tgsi_sampler_lod_zero:
  1737.       /* this is all static state in the sampler really need clamp here? */
  1738.       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lod_bias, min_lod, max_lod);
  1739.       break;
  1740.    default:
  1741.       assert(0);
  1742.       lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
  1743.    }
  1744. }
  1745.  
  1746.  
  1747. static void
  1748. mip_filter_linear(struct sp_sampler_view *sp_sview,
  1749.                   struct sp_sampler *sp_samp,
  1750.                   img_filter_func min_filter,
  1751.                   img_filter_func mag_filter,
  1752.                   const float s[TGSI_QUAD_SIZE],
  1753.                   const float t[TGSI_QUAD_SIZE],
  1754.                   const float p[TGSI_QUAD_SIZE],
  1755.                   const float c0[TGSI_QUAD_SIZE],
  1756.                   const float lod_in[TGSI_QUAD_SIZE],
  1757.                   enum tgsi_sampler_control control,
  1758.                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  1759. {
  1760.    const struct pipe_resource *texture = sp_sview->base.texture;
  1761.    int j;
  1762.    float lod[TGSI_QUAD_SIZE];
  1763.  
  1764.    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
  1765.  
  1766.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  1767.       int level0 = sp_sview->base.u.tex.first_level + (int)lod[j];
  1768.  
  1769.       if (lod[j] < 0.0)
  1770.          mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1771.                     sp_sview->base.u.tex.first_level,
  1772.                     sp_sview->faces[j], &rgba[0][j]);
  1773.  
  1774.       else if (level0 >= (int) texture->last_level)
  1775.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], texture->last_level,
  1776.                     sp_sview->faces[j], &rgba[0][j]);
  1777.  
  1778.       else {
  1779.          float levelBlend = frac(lod[j]);
  1780.          float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  1781.          int c;
  1782.  
  1783.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0,
  1784.                     sp_sview->faces[j], &rgbax[0][0]);
  1785.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
  1786.                     sp_sview->faces[j], &rgbax[0][1]);
  1787.  
  1788.          for (c = 0; c < 4; c++) {
  1789.             rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
  1790.          }
  1791.       }
  1792.    }
  1793.  
  1794.    if (DEBUG_TEX) {
  1795.       print_sample_4(__FUNCTION__, rgba);
  1796.    }
  1797. }
  1798.  
  1799.  
  1800. /**
  1801.  * Compute nearest mipmap level from texcoords.
  1802.  * Then sample the texture level for four elements of a quad.
  1803.  * \param c0  the LOD bias factors, or absolute LODs (depending on control)
  1804.  */
  1805. static void
  1806. mip_filter_nearest(struct sp_sampler_view *sp_sview,
  1807.                    struct sp_sampler *sp_samp,
  1808.                    img_filter_func min_filter,
  1809.                    img_filter_func mag_filter,
  1810.                    const float s[TGSI_QUAD_SIZE],
  1811.                    const float t[TGSI_QUAD_SIZE],
  1812.                    const float p[TGSI_QUAD_SIZE],
  1813.                    const float c0[TGSI_QUAD_SIZE],
  1814.                    const float lod_in[TGSI_QUAD_SIZE],
  1815.                    enum tgsi_sampler_control control,
  1816.                    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  1817. {
  1818.    const struct pipe_resource *texture = sp_sview->base.texture;
  1819.    float lod[TGSI_QUAD_SIZE];
  1820.    int j;
  1821.  
  1822.    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
  1823.  
  1824.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  1825.       if (lod[j] < 0.0)
  1826.          mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1827.                     sp_sview->base.u.tex.first_level,
  1828.                     sp_sview->faces[j], &rgba[0][j]);
  1829.       else {
  1830.          int level = sp_sview->base.u.tex.first_level + (int)(lod[j] + 0.5F);
  1831.          level = MIN2(level, (int)texture->last_level);
  1832.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1833.                     level, sp_sview->faces[j], &rgba[0][j]);
  1834.       }
  1835.    }
  1836.  
  1837.    if (DEBUG_TEX) {
  1838.       print_sample_4(__FUNCTION__, rgba);
  1839.    }
  1840. }
  1841.  
  1842.  
  1843. static void
  1844. mip_filter_none(struct sp_sampler_view *sp_sview,
  1845.                 struct sp_sampler *sp_samp,
  1846.                 img_filter_func min_filter,
  1847.                 img_filter_func mag_filter,
  1848.                 const float s[TGSI_QUAD_SIZE],
  1849.                 const float t[TGSI_QUAD_SIZE],
  1850.                 const float p[TGSI_QUAD_SIZE],
  1851.                 const float c0[TGSI_QUAD_SIZE],
  1852.                 const float lod_in[TGSI_QUAD_SIZE],
  1853.                 enum tgsi_sampler_control control,
  1854.                 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  1855. {
  1856.    float lod[TGSI_QUAD_SIZE];
  1857.    int j;
  1858.  
  1859.    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
  1860.  
  1861.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  1862.       if (lod[j] < 0.0) {
  1863.          mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1864.                     sp_sview->base.u.tex.first_level,
  1865.                     sp_sview->faces[j], &rgba[0][j]);
  1866.       }
  1867.       else {
  1868.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1869.                     sp_sview->base.u.tex.first_level,
  1870.                     sp_sview->faces[j], &rgba[0][j]);
  1871.       }
  1872.    }
  1873. }
  1874.  
  1875.  
  1876. static void
  1877. mip_filter_none_no_filter_select(struct sp_sampler_view *sp_sview,
  1878.                                  struct sp_sampler *sp_samp,
  1879.                                  img_filter_func min_filter,
  1880.                                  img_filter_func mag_filter,
  1881.                                  const float s[TGSI_QUAD_SIZE],
  1882.                                  const float t[TGSI_QUAD_SIZE],
  1883.                                  const float p[TGSI_QUAD_SIZE],
  1884.                                  const float c0[TGSI_QUAD_SIZE],
  1885.                                  const float lod_in[TGSI_QUAD_SIZE],
  1886.                                  enum tgsi_sampler_control control,
  1887.                                  float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  1888. {
  1889.    int j;
  1890.  
  1891.    for (j = 0; j < TGSI_QUAD_SIZE; j++)
  1892.       mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1893.                  sp_sview->base.u.tex.first_level,
  1894.                  sp_sview->faces[j], &rgba[0][j]);
  1895. }
  1896.  
  1897.  
  1898. /* For anisotropic filtering */
  1899. #define WEIGHT_LUT_SIZE 1024
  1900.  
  1901. static float *weightLut = NULL;
  1902.  
  1903. /**
  1904.  * Creates the look-up table used to speed-up EWA sampling
  1905.  */
  1906. static void
  1907. create_filter_table(void)
  1908. {
  1909.    unsigned i;
  1910.    if (!weightLut) {
  1911.       weightLut = (float *) MALLOC(WEIGHT_LUT_SIZE * sizeof(float));
  1912.  
  1913.       for (i = 0; i < WEIGHT_LUT_SIZE; ++i) {
  1914.          float alpha = 2;
  1915.          float r2 = (float) i / (float) (WEIGHT_LUT_SIZE - 1);
  1916.          float weight = (float) exp(-alpha * r2);
  1917.          weightLut[i] = weight;
  1918.       }
  1919.    }
  1920. }
  1921.  
  1922.  
  1923. /**
  1924.  * Elliptical weighted average (EWA) filter for producing high quality
  1925.  * anisotropic filtered results.
  1926.  * Based on the Higher Quality Elliptical Weighted Average Filter
  1927.  * published by Paul S. Heckbert in his Master's Thesis
  1928.  * "Fundamentals of Texture Mapping and Image Warping" (1989)
  1929.  */
  1930. static void
  1931. img_filter_2d_ewa(struct sp_sampler_view *sp_sview,
  1932.                   struct sp_sampler *sp_samp,
  1933.                   img_filter_func min_filter,
  1934.                   img_filter_func mag_filter,
  1935.                   const float s[TGSI_QUAD_SIZE],
  1936.                   const float t[TGSI_QUAD_SIZE],
  1937.                   const float p[TGSI_QUAD_SIZE],
  1938.                   unsigned level,
  1939.                   const float dudx, const float dvdx,
  1940.                   const float dudy, const float dvdy,
  1941.                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  1942. {
  1943.    const struct pipe_resource *texture = sp_sview->base.texture;
  1944.  
  1945.    // ??? Won't the image filters blow up if level is negative?
  1946.    unsigned level0 = level > 0 ? level : 0;
  1947.    float scaling = 1.0f / (1 << level0);
  1948.    int width = u_minify(texture->width0, level0);
  1949.    int height = u_minify(texture->height0, level0);
  1950.  
  1951.    float ux = dudx * scaling;
  1952.    float vx = dvdx * scaling;
  1953.    float uy = dudy * scaling;
  1954.    float vy = dvdy * scaling;
  1955.  
  1956.    /* compute ellipse coefficients to bound the region:
  1957.     * A*x*x + B*x*y + C*y*y = F.
  1958.     */
  1959.    float A = vx*vx+vy*vy+1;
  1960.    float B = -2*(ux*vx+uy*vy);
  1961.    float C = ux*ux+uy*uy+1;
  1962.    float F = A*C-B*B/4.0f;
  1963.  
  1964.    /* check if it is an ellipse */
  1965.    /* ASSERT(F > 0.0); */
  1966.  
  1967.    /* Compute the ellipse's (u,v) bounding box in texture space */
  1968.    float d = -B*B+4.0f*C*A;
  1969.    float box_u = 2.0f / d * sqrtf(d*C*F); /* box_u -> half of bbox with   */
  1970.    float box_v = 2.0f / d * sqrtf(A*d*F); /* box_v -> half of bbox height */
  1971.  
  1972.    float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  1973.    float s_buffer[TGSI_QUAD_SIZE];
  1974.    float t_buffer[TGSI_QUAD_SIZE];
  1975.    float weight_buffer[TGSI_QUAD_SIZE];
  1976.    unsigned buffer_next;
  1977.    int j;
  1978.    float den; /* = 0.0F; */
  1979.    float ddq;
  1980.    float U; /* = u0 - tex_u; */
  1981.    int v;
  1982.  
  1983.    /* Scale ellipse formula to directly index the Filter Lookup Table.
  1984.     * i.e. scale so that F = WEIGHT_LUT_SIZE-1
  1985.     */
  1986.    double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F;
  1987.    A *= formScale;
  1988.    B *= formScale;
  1989.    C *= formScale;
  1990.    /* F *= formScale; */ /* no need to scale F as we don't use it below here */
  1991.  
  1992.    /* For each quad, the du and dx values are the same and so the ellipse is
  1993.     * also the same. Note that texel/image access can only be performed using
  1994.     * a quad, i.e. it is not possible to get the pixel value for a single
  1995.     * tex coord. In order to have a better performance, the access is buffered
  1996.     * using the s_buffer/t_buffer and weight_buffer. Only when the buffer is
  1997.     * full, then the pixel values are read from the image.
  1998.     */
  1999.    ddq = 2 * A;
  2000.    
  2001.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2002.       /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
  2003.        * and incrementally update the value of Ax^2+Bxy*Cy^2; when this
  2004.        * value, q, is less than F, we're inside the ellipse
  2005.        */
  2006.       float tex_u = -0.5F + s[j] * texture->width0 * scaling;
  2007.       float tex_v = -0.5F + t[j] * texture->height0 * scaling;
  2008.  
  2009.       int u0 = (int) floorf(tex_u - box_u);
  2010.       int u1 = (int) ceilf(tex_u + box_u);
  2011.       int v0 = (int) floorf(tex_v - box_v);
  2012.       int v1 = (int) ceilf(tex_v + box_v);
  2013.  
  2014.       float num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
  2015.       buffer_next = 0;
  2016.       den = 0;
  2017.       U = u0 - tex_u;
  2018.       for (v = v0; v <= v1; ++v) {
  2019.          float V = v - tex_v;
  2020.          float dq = A * (2 * U + 1) + B * V;
  2021.          float q = (C * V + B * U) * V + A * U * U;
  2022.  
  2023.          int u;
  2024.          for (u = u0; u <= u1; ++u) {
  2025.             /* Note that the ellipse has been pre-scaled so F =
  2026.              * WEIGHT_LUT_SIZE - 1
  2027.              */
  2028.             if (q < WEIGHT_LUT_SIZE) {
  2029.                /* as a LUT is used, q must never be negative;
  2030.                 * should not happen, though
  2031.                 */
  2032.                const int qClamped = q >= 0.0F ? q : 0;
  2033.                float weight = weightLut[qClamped];
  2034.  
  2035.                weight_buffer[buffer_next] = weight;
  2036.                s_buffer[buffer_next] = u / ((float) width);
  2037.                t_buffer[buffer_next] = v / ((float) height);
  2038.            
  2039.                buffer_next++;
  2040.                if (buffer_next == TGSI_QUAD_SIZE) {
  2041.                   /* 4 texel coords are in the buffer -> read it now */
  2042.                   unsigned jj;
  2043.                   /* it is assumed that samp->min_img_filter is set to
  2044.                    * img_filter_2d_nearest or one of the
  2045.                    * accelerated img_filter_2d_nearest_XXX functions.
  2046.                    */
  2047.                   for (jj = 0; jj < buffer_next; jj++) {
  2048.                      min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
  2049.                                 level, sp_sview->faces[j], &rgba_temp[0][jj]);
  2050.                      num[0] += weight_buffer[jj] * rgba_temp[0][jj];
  2051.                      num[1] += weight_buffer[jj] * rgba_temp[1][jj];
  2052.                      num[2] += weight_buffer[jj] * rgba_temp[2][jj];
  2053.                      num[3] += weight_buffer[jj] * rgba_temp[3][jj];
  2054.                   }
  2055.  
  2056.                   buffer_next = 0;
  2057.                }
  2058.  
  2059.                den += weight;
  2060.             }
  2061.             q += dq;
  2062.             dq += ddq;
  2063.          }
  2064.       }
  2065.  
  2066.       /* if the tex coord buffer contains unread values, we will read
  2067.        * them now.
  2068.        */
  2069.       if (buffer_next > 0) {
  2070.          unsigned jj;
  2071.          /* it is assumed that samp->min_img_filter is set to
  2072.           * img_filter_2d_nearest or one of the
  2073.           * accelerated img_filter_2d_nearest_XXX functions.
  2074.           */
  2075.          for (jj = 0; jj < buffer_next; jj++) {
  2076.             min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
  2077.                        level, sp_sview->faces[j], &rgba_temp[0][jj]);
  2078.             num[0] += weight_buffer[jj] * rgba_temp[0][jj];
  2079.             num[1] += weight_buffer[jj] * rgba_temp[1][jj];
  2080.             num[2] += weight_buffer[jj] * rgba_temp[2][jj];
  2081.             num[3] += weight_buffer[jj] * rgba_temp[3][jj];
  2082.          }
  2083.       }
  2084.  
  2085.       if (den <= 0.0F) {
  2086.          /* Reaching this place would mean that no pixels intersected
  2087.           * the ellipse.  This should never happen because the filter
  2088.           * we use always intersects at least one pixel.
  2089.           */
  2090.  
  2091.          /*rgba[0]=0;
  2092.          rgba[1]=0;
  2093.          rgba[2]=0;
  2094.          rgba[3]=0;*/
  2095.          /* not enough pixels in resampling, resort to direct interpolation */
  2096.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level,
  2097.                     sp_sview->faces[j], &rgba_temp[0][j]);
  2098.          den = 1;
  2099.          num[0] = rgba_temp[0][j];
  2100.          num[1] = rgba_temp[1][j];
  2101.          num[2] = rgba_temp[2][j];
  2102.          num[3] = rgba_temp[3][j];
  2103.       }
  2104.  
  2105.       rgba[0][j] = num[0] / den;
  2106.       rgba[1][j] = num[1] / den;
  2107.       rgba[2][j] = num[2] / den;
  2108.       rgba[3][j] = num[3] / den;
  2109.    }
  2110. }
  2111.  
  2112.  
  2113. /**
  2114.  * Sample 2D texture using an anisotropic filter.
  2115.  */
  2116. static void
  2117. mip_filter_linear_aniso(struct sp_sampler_view *sp_sview,
  2118.                         struct sp_sampler *sp_samp,
  2119.                         img_filter_func min_filter,
  2120.                         img_filter_func mag_filter,
  2121.                         const float s[TGSI_QUAD_SIZE],
  2122.                         const float t[TGSI_QUAD_SIZE],
  2123.                         const float p[TGSI_QUAD_SIZE],
  2124.                         const float c0[TGSI_QUAD_SIZE],
  2125.                         const float lod_in[TGSI_QUAD_SIZE],
  2126.                         enum tgsi_sampler_control control,
  2127.                         float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2128. {
  2129.    const struct pipe_resource *texture = sp_sview->base.texture;
  2130.    int level0;
  2131.    float lambda;
  2132.    float lod[TGSI_QUAD_SIZE];
  2133.  
  2134.    float s_to_u = u_minify(texture->width0, sp_sview->base.u.tex.first_level);
  2135.    float t_to_v = u_minify(texture->height0, sp_sview->base.u.tex.first_level);
  2136.    float dudx = (s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
  2137.    float dudy = (s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]) * s_to_u;
  2138.    float dvdx = (t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
  2139.    float dvdy = (t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]) * t_to_v;
  2140.    
  2141.    if (control == tgsi_sampler_lod_bias ||
  2142.        control == tgsi_sampler_lod_none ||
  2143.        /* XXX FIXME */
  2144.        control == tgsi_sampler_derivs_explicit) {
  2145.       /* note: instead of working with Px and Py, we will use the
  2146.        * squared length instead, to avoid sqrt.
  2147.        */
  2148.       float Px2 = dudx * dudx + dvdx * dvdx;
  2149.       float Py2 = dudy * dudy + dvdy * dvdy;
  2150.  
  2151.       float Pmax2;
  2152.       float Pmin2;
  2153.       float e;
  2154.       const float maxEccentricity = sp_samp->base.max_anisotropy * sp_samp->base.max_anisotropy;
  2155.      
  2156.       if (Px2 < Py2) {
  2157.          Pmax2 = Py2;
  2158.          Pmin2 = Px2;
  2159.       }
  2160.       else {
  2161.          Pmax2 = Px2;
  2162.          Pmin2 = Py2;
  2163.       }
  2164.      
  2165.       /* if the eccentricity of the ellipse is too big, scale up the shorter
  2166.        * of the two vectors to limit the maximum amount of work per pixel
  2167.        */
  2168.       e = Pmax2 / Pmin2;
  2169.       if (e > maxEccentricity) {
  2170.          /* float s=e / maxEccentricity;
  2171.             minor[0] *= s;
  2172.             minor[1] *= s;
  2173.             Pmin2 *= s; */
  2174.          Pmin2 = Pmax2 / maxEccentricity;
  2175.       }
  2176.      
  2177.       /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
  2178.        * this since 0.5*log(x) = log(sqrt(x))
  2179.        */
  2180.       lambda = 0.5F * util_fast_log2(Pmin2) + sp_samp->base.lod_bias;
  2181.       compute_lod(&sp_samp->base, control, lambda, lod_in, lod);
  2182.    }
  2183.    else {
  2184.       assert(control == tgsi_sampler_lod_explicit ||
  2185.              control == tgsi_sampler_lod_zero);
  2186.       compute_lod(&sp_samp->base, control, sp_samp->base.lod_bias, lod_in, lod);
  2187.    }
  2188.    
  2189.    /* XXX: Take into account all lod values.
  2190.     */
  2191.    lambda = lod[0];
  2192.    level0 = sp_sview->base.u.tex.first_level + (int)lambda;
  2193.  
  2194.    /* If the ellipse covers the whole image, we can
  2195.     * simply return the average of the whole image.
  2196.     */
  2197.    if (level0 >= (int) texture->last_level) {
  2198.       int j;
  2199.       for (j = 0; j < TGSI_QUAD_SIZE; j++)
  2200.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], texture->last_level,
  2201.                     sp_sview->faces[j], &rgba[0][j]);
  2202.    }
  2203.    else {
  2204.       /* don't bother interpolating between multiple LODs; it doesn't
  2205.        * seem to be worth the extra running time.
  2206.        */
  2207.       img_filter_2d_ewa(sp_sview, sp_samp, min_filter, mag_filter,
  2208.                         s, t, p, level0,
  2209.                         dudx, dvdx, dudy, dvdy, rgba);
  2210.    }
  2211.  
  2212.    if (DEBUG_TEX) {
  2213.       print_sample_4(__FUNCTION__, rgba);
  2214.    }
  2215. }
  2216.  
  2217.  
  2218. /**
  2219.  * Specialized version of mip_filter_linear with hard-wired calls to
  2220.  * 2d lambda calculation and 2d_linear_repeat_POT img filters.
  2221.  */
  2222. static void
  2223. mip_filter_linear_2d_linear_repeat_POT(
  2224.    struct sp_sampler_view *sp_sview,
  2225.    struct sp_sampler *sp_samp,
  2226.    img_filter_func min_filter,
  2227.    img_filter_func mag_filter,
  2228.    const float s[TGSI_QUAD_SIZE],
  2229.    const float t[TGSI_QUAD_SIZE],
  2230.    const float p[TGSI_QUAD_SIZE],
  2231.    const float c0[TGSI_QUAD_SIZE],
  2232.    const float lod_in[TGSI_QUAD_SIZE],
  2233.    enum tgsi_sampler_control control,
  2234.    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2235. {
  2236.    const struct pipe_resource *texture = sp_sview->base.texture;
  2237.    int j;
  2238.    float lod[TGSI_QUAD_SIZE];
  2239.  
  2240.    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
  2241.  
  2242.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2243.       int level0 = sp_sview->base.u.tex.first_level + (int)lod[j];
  2244.  
  2245.       /* Catches both negative and large values of level0:
  2246.        */
  2247.       if ((unsigned)level0 >= texture->last_level) {
  2248.          if (level0 < 0)
  2249.             img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
  2250.                                             sp_sview->base.u.tex.first_level,
  2251.                                             sp_sview->faces[j], &rgba[0][j]);
  2252.          else
  2253.             img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
  2254.                                             sp_sview->base.texture->last_level,
  2255.                                             sp_sview->faces[j], &rgba[0][j]);
  2256.  
  2257.       }
  2258.       else {
  2259.          float levelBlend = frac(lod[j]);
  2260.          float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  2261.          int c;
  2262.  
  2263.          img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0,
  2264.                                          sp_sview->faces[j], &rgbax[0][0]);
  2265.          img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
  2266.                                          sp_sview->faces[j], &rgbax[0][1]);
  2267.  
  2268.          for (c = 0; c < TGSI_NUM_CHANNELS; c++)
  2269.             rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
  2270.       }
  2271.    }
  2272.  
  2273.    if (DEBUG_TEX) {
  2274.       print_sample_4(__FUNCTION__, rgba);
  2275.    }
  2276. }
  2277.  
  2278.  
  2279. /**
  2280.  * Do shadow/depth comparisons.
  2281.  */
  2282. static void
  2283. sample_compare(struct sp_sampler_view *sp_sview,
  2284.                struct sp_sampler *sp_samp,
  2285.                const float s[TGSI_QUAD_SIZE],
  2286.                const float t[TGSI_QUAD_SIZE],
  2287.                const float p[TGSI_QUAD_SIZE],
  2288.                const float c0[TGSI_QUAD_SIZE],
  2289.                const float c1[TGSI_QUAD_SIZE],
  2290.                enum tgsi_sampler_control control,
  2291.                float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2292. {
  2293.    const struct pipe_sampler_state *sampler = &sp_samp->base;
  2294.    int j, k0, k1, k2, k3;
  2295.    float val;
  2296.    float pc0, pc1, pc2, pc3;
  2297.  
  2298.    /**
  2299.     * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
  2300.     * for 2D Array texture we need to use the 'c0' (aka Q).
  2301.     * When we sampled the depth texture, the depth value was put into all
  2302.     * RGBA channels.  We look at the red channel here.
  2303.     */
  2304.  
  2305.    if (sp_sview->base.texture->target == PIPE_TEXTURE_2D_ARRAY ||
  2306.        sp_sview->base.texture->target == PIPE_TEXTURE_CUBE) {
  2307.       pc0 = CLAMP(c0[0], 0.0F, 1.0F);
  2308.       pc1 = CLAMP(c0[1], 0.0F, 1.0F);
  2309.       pc2 = CLAMP(c0[2], 0.0F, 1.0F);
  2310.       pc3 = CLAMP(c0[3], 0.0F, 1.0F);
  2311.    } else if (sp_sview->base.texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
  2312.       pc0 = CLAMP(c1[0], 0.0F, 1.0F);
  2313.       pc1 = CLAMP(c1[1], 0.0F, 1.0F);
  2314.       pc2 = CLAMP(c1[2], 0.0F, 1.0F);
  2315.       pc3 = CLAMP(c1[3], 0.0F, 1.0F);
  2316.    } else {
  2317.       pc0 = CLAMP(p[0], 0.0F, 1.0F);
  2318.       pc1 = CLAMP(p[1], 0.0F, 1.0F);
  2319.       pc2 = CLAMP(p[2], 0.0F, 1.0F);
  2320.       pc3 = CLAMP(p[3], 0.0F, 1.0F);
  2321.    }
  2322.    /* compare four texcoords vs. four texture samples */
  2323.    switch (sampler->compare_func) {
  2324.    case PIPE_FUNC_LESS:
  2325.       k0 = pc0 < rgba[0][0];
  2326.       k1 = pc1 < rgba[0][1];
  2327.       k2 = pc2 < rgba[0][2];
  2328.       k3 = pc3 < rgba[0][3];
  2329.       break;
  2330.    case PIPE_FUNC_LEQUAL:
  2331.       k0 = pc0 <= rgba[0][0];
  2332.       k1 = pc1 <= rgba[0][1];
  2333.       k2 = pc2 <= rgba[0][2];
  2334.       k3 = pc3 <= rgba[0][3];
  2335.       break;
  2336.    case PIPE_FUNC_GREATER:
  2337.       k0 = pc0 > rgba[0][0];
  2338.       k1 = pc1 > rgba[0][1];
  2339.       k2 = pc2 > rgba[0][2];
  2340.       k3 = pc3 > rgba[0][3];
  2341.       break;
  2342.    case PIPE_FUNC_GEQUAL:
  2343.       k0 = pc0 >= rgba[0][0];
  2344.       k1 = pc1 >= rgba[0][1];
  2345.       k2 = pc2 >= rgba[0][2];
  2346.       k3 = pc3 >= rgba[0][3];
  2347.       break;
  2348.    case PIPE_FUNC_EQUAL:
  2349.       k0 = pc0 == rgba[0][0];
  2350.       k1 = pc1 == rgba[0][1];
  2351.       k2 = pc2 == rgba[0][2];
  2352.       k3 = pc3 == rgba[0][3];
  2353.       break;
  2354.    case PIPE_FUNC_NOTEQUAL:
  2355.       k0 = pc0 != rgba[0][0];
  2356.       k1 = pc1 != rgba[0][1];
  2357.       k2 = pc2 != rgba[0][2];
  2358.       k3 = pc3 != rgba[0][3];
  2359.       break;
  2360.    case PIPE_FUNC_ALWAYS:
  2361.       k0 = k1 = k2 = k3 = 1;
  2362.       break;
  2363.    case PIPE_FUNC_NEVER:
  2364.       k0 = k1 = k2 = k3 = 0;
  2365.       break;
  2366.    default:
  2367.       k0 = k1 = k2 = k3 = 0;
  2368.       assert(0);
  2369.       break;
  2370.    }
  2371.  
  2372.    if (sampler->mag_img_filter == PIPE_TEX_FILTER_LINEAR) {
  2373.       /* convert four pass/fail values to an intensity in [0,1] */
  2374.       /*
  2375.        * XXX this doesn't actually make much sense.
  2376.        * We just average the result of four _pixels_ and output the same
  2377.        * value for all of the four pixels of the quad.
  2378.        * This really needs to work on the _samples_ i.e. inside the img filter.
  2379.        */
  2380.       val = 0.25F * (k0 + k1 + k2 + k3);
  2381.  
  2382.       /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
  2383.       for (j = 0; j < 4; j++) {
  2384.          rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
  2385.          rgba[3][j] = 1.0F;
  2386.       }
  2387.    } else {
  2388.       for (j = 0; j < 4; j++) {
  2389.          rgba[0][j] = k0;
  2390.          rgba[1][j] = k1;
  2391.          rgba[2][j] = k2;
  2392.          rgba[3][j] = 1.0F;
  2393.       }
  2394.    }
  2395. }
  2396.  
  2397.  
  2398. static void
  2399. do_swizzling(const struct pipe_sampler_view *sview,
  2400.              float in[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
  2401.              float out[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2402. {
  2403.    int j;
  2404.    const unsigned swizzle_r = sview->swizzle_r;
  2405.    const unsigned swizzle_g = sview->swizzle_g;
  2406.    const unsigned swizzle_b = sview->swizzle_b;
  2407.    const unsigned swizzle_a = sview->swizzle_a;
  2408.  
  2409.    switch (swizzle_r) {
  2410.    case PIPE_SWIZZLE_ZERO:
  2411.       for (j = 0; j < 4; j++)
  2412.          out[0][j] = 0.0f;
  2413.       break;
  2414.    case PIPE_SWIZZLE_ONE:
  2415.       for (j = 0; j < 4; j++)
  2416.          out[0][j] = 1.0f;
  2417.       break;
  2418.    default:
  2419.       assert(swizzle_r < 4);
  2420.       for (j = 0; j < 4; j++)
  2421.          out[0][j] = in[swizzle_r][j];
  2422.    }
  2423.  
  2424.    switch (swizzle_g) {
  2425.    case PIPE_SWIZZLE_ZERO:
  2426.       for (j = 0; j < 4; j++)
  2427.          out[1][j] = 0.0f;
  2428.       break;
  2429.    case PIPE_SWIZZLE_ONE:
  2430.       for (j = 0; j < 4; j++)
  2431.          out[1][j] = 1.0f;
  2432.       break;
  2433.    default:
  2434.       assert(swizzle_g < 4);
  2435.       for (j = 0; j < 4; j++)
  2436.          out[1][j] = in[swizzle_g][j];
  2437.    }
  2438.  
  2439.    switch (swizzle_b) {
  2440.    case PIPE_SWIZZLE_ZERO:
  2441.       for (j = 0; j < 4; j++)
  2442.          out[2][j] = 0.0f;
  2443.       break;
  2444.    case PIPE_SWIZZLE_ONE:
  2445.       for (j = 0; j < 4; j++)
  2446.          out[2][j] = 1.0f;
  2447.       break;
  2448.    default:
  2449.       assert(swizzle_b < 4);
  2450.       for (j = 0; j < 4; j++)
  2451.          out[2][j] = in[swizzle_b][j];
  2452.    }
  2453.  
  2454.    switch (swizzle_a) {
  2455.    case PIPE_SWIZZLE_ZERO:
  2456.       for (j = 0; j < 4; j++)
  2457.          out[3][j] = 0.0f;
  2458.       break;
  2459.    case PIPE_SWIZZLE_ONE:
  2460.       for (j = 0; j < 4; j++)
  2461.          out[3][j] = 1.0f;
  2462.       break;
  2463.    default:
  2464.       assert(swizzle_a < 4);
  2465.       for (j = 0; j < 4; j++)
  2466.          out[3][j] = in[swizzle_a][j];
  2467.    }
  2468. }
  2469.  
  2470.  
  2471. static wrap_nearest_func
  2472. get_nearest_unorm_wrap(unsigned mode)
  2473. {
  2474.    switch (mode) {
  2475.    case PIPE_TEX_WRAP_CLAMP:
  2476.       return wrap_nearest_unorm_clamp;
  2477.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  2478.       return wrap_nearest_unorm_clamp_to_edge;
  2479.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  2480.       return wrap_nearest_unorm_clamp_to_border;
  2481.    default:
  2482.       assert(0);
  2483.       return wrap_nearest_unorm_clamp;
  2484.    }
  2485. }
  2486.  
  2487.  
  2488. static wrap_nearest_func
  2489. get_nearest_wrap(unsigned mode)
  2490. {
  2491.    switch (mode) {
  2492.    case PIPE_TEX_WRAP_REPEAT:
  2493.       return wrap_nearest_repeat;
  2494.    case PIPE_TEX_WRAP_CLAMP:
  2495.       return wrap_nearest_clamp;
  2496.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  2497.       return wrap_nearest_clamp_to_edge;
  2498.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  2499.       return wrap_nearest_clamp_to_border;
  2500.    case PIPE_TEX_WRAP_MIRROR_REPEAT:
  2501.       return wrap_nearest_mirror_repeat;
  2502.    case PIPE_TEX_WRAP_MIRROR_CLAMP:
  2503.       return wrap_nearest_mirror_clamp;
  2504.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
  2505.       return wrap_nearest_mirror_clamp_to_edge;
  2506.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
  2507.       return wrap_nearest_mirror_clamp_to_border;
  2508.    default:
  2509.       assert(0);
  2510.       return wrap_nearest_repeat;
  2511.    }
  2512. }
  2513.  
  2514.  
  2515. static wrap_linear_func
  2516. get_linear_unorm_wrap(unsigned mode)
  2517. {
  2518.    switch (mode) {
  2519.    case PIPE_TEX_WRAP_CLAMP:
  2520.       return wrap_linear_unorm_clamp;
  2521.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  2522.       return wrap_linear_unorm_clamp_to_edge;
  2523.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  2524.       return wrap_linear_unorm_clamp_to_border;
  2525.    default:
  2526.       assert(0);
  2527.       return wrap_linear_unorm_clamp;
  2528.    }
  2529. }
  2530.  
  2531.  
  2532. static wrap_linear_func
  2533. get_linear_wrap(unsigned mode)
  2534. {
  2535.    switch (mode) {
  2536.    case PIPE_TEX_WRAP_REPEAT:
  2537.       return wrap_linear_repeat;
  2538.    case PIPE_TEX_WRAP_CLAMP:
  2539.       return wrap_linear_clamp;
  2540.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  2541.       return wrap_linear_clamp_to_edge;
  2542.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  2543.       return wrap_linear_clamp_to_border;
  2544.    case PIPE_TEX_WRAP_MIRROR_REPEAT:
  2545.       return wrap_linear_mirror_repeat;
  2546.    case PIPE_TEX_WRAP_MIRROR_CLAMP:
  2547.       return wrap_linear_mirror_clamp;
  2548.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
  2549.       return wrap_linear_mirror_clamp_to_edge;
  2550.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
  2551.       return wrap_linear_mirror_clamp_to_border;
  2552.    default:
  2553.       assert(0);
  2554.       return wrap_linear_repeat;
  2555.    }
  2556. }
  2557.  
  2558.  
  2559. /**
  2560.  * Is swizzling needed for the given state key?
  2561.  */
  2562. static INLINE bool
  2563. any_swizzle(const struct pipe_sampler_view *view)
  2564. {
  2565.    return (view->swizzle_r != PIPE_SWIZZLE_RED ||
  2566.            view->swizzle_g != PIPE_SWIZZLE_GREEN ||
  2567.            view->swizzle_b != PIPE_SWIZZLE_BLUE ||
  2568.            view->swizzle_a != PIPE_SWIZZLE_ALPHA);
  2569. }
  2570.  
  2571.  
  2572. static img_filter_func
  2573. get_img_filter(const struct sp_sampler_view *sp_sview,
  2574.                const struct pipe_sampler_state *sampler,
  2575.                unsigned filter)
  2576. {
  2577.    switch (sp_sview->base.texture->target) {
  2578.    case PIPE_BUFFER:
  2579.    case PIPE_TEXTURE_1D:
  2580.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2581.          return img_filter_1d_nearest;
  2582.       else
  2583.          return img_filter_1d_linear;
  2584.       break;
  2585.    case PIPE_TEXTURE_1D_ARRAY:
  2586.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2587.          return img_filter_1d_array_nearest;
  2588.       else
  2589.          return img_filter_1d_array_linear;
  2590.       break;
  2591.    case PIPE_TEXTURE_2D:
  2592.    case PIPE_TEXTURE_RECT:
  2593.       /* Try for fast path:
  2594.        */
  2595.       if (sp_sview->pot2d &&
  2596.           sampler->wrap_s == sampler->wrap_t &&
  2597.           sampler->normalized_coords)
  2598.       {
  2599.          switch (sampler->wrap_s) {
  2600.          case PIPE_TEX_WRAP_REPEAT:
  2601.             switch (filter) {
  2602.             case PIPE_TEX_FILTER_NEAREST:
  2603.                return img_filter_2d_nearest_repeat_POT;
  2604.             case PIPE_TEX_FILTER_LINEAR:
  2605.                return img_filter_2d_linear_repeat_POT;
  2606.             default:
  2607.                break;
  2608.             }
  2609.             break;
  2610.          case PIPE_TEX_WRAP_CLAMP:
  2611.             switch (filter) {
  2612.             case PIPE_TEX_FILTER_NEAREST:
  2613.                return img_filter_2d_nearest_clamp_POT;
  2614.             default:
  2615.                break;
  2616.             }
  2617.          }
  2618.       }
  2619.       /* Otherwise use default versions:
  2620.        */
  2621.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2622.          return img_filter_2d_nearest;
  2623.       else
  2624.          return img_filter_2d_linear;
  2625.       break;
  2626.    case PIPE_TEXTURE_2D_ARRAY:
  2627.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2628.          return img_filter_2d_array_nearest;
  2629.       else
  2630.          return img_filter_2d_array_linear;
  2631.       break;
  2632.    case PIPE_TEXTURE_CUBE:
  2633.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2634.          return img_filter_cube_nearest;
  2635.       else
  2636.          return img_filter_cube_linear;
  2637.       break;
  2638.    case PIPE_TEXTURE_CUBE_ARRAY:
  2639.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2640.          return img_filter_cube_array_nearest;
  2641.       else
  2642.          return img_filter_cube_array_linear;
  2643.       break;
  2644.    case PIPE_TEXTURE_3D:
  2645.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2646.          return img_filter_3d_nearest;
  2647.       else
  2648.          return img_filter_3d_linear;
  2649.       break;
  2650.    default:
  2651.       assert(0);
  2652.       return img_filter_1d_nearest;
  2653.    }
  2654. }
  2655.  
  2656.  
  2657. static void
  2658. sample_mip(struct sp_sampler_view *sp_sview,
  2659.            struct sp_sampler *sp_samp,
  2660.            const float s[TGSI_QUAD_SIZE],
  2661.            const float t[TGSI_QUAD_SIZE],
  2662.            const float p[TGSI_QUAD_SIZE],
  2663.            const float c0[TGSI_QUAD_SIZE],
  2664.            const float lod[TGSI_QUAD_SIZE],
  2665.            enum tgsi_sampler_control control,
  2666.            float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2667. {
  2668.    mip_filter_func mip_filter;
  2669.    img_filter_func min_img_filter = NULL;
  2670.    img_filter_func mag_img_filter = NULL;
  2671.  
  2672.    if (sp_sview->pot2d & sp_samp->min_mag_equal_repeat_linear) {
  2673.       mip_filter = mip_filter_linear_2d_linear_repeat_POT;
  2674.    }
  2675.    else {
  2676.       mip_filter = sp_samp->mip_filter;
  2677.       min_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->min_img_filter);
  2678.       if (sp_samp->min_mag_equal) {
  2679.          mag_img_filter = min_img_filter;
  2680.       }
  2681.       else {
  2682.          mag_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->base.mag_img_filter);
  2683.       }
  2684.    }
  2685.  
  2686.    mip_filter(sp_sview, sp_samp, min_img_filter, mag_img_filter,
  2687.               s, t, p, c0, lod, control, rgba);
  2688.  
  2689.    if (sp_samp->base.compare_mode != PIPE_TEX_COMPARE_NONE) {
  2690.       sample_compare(sp_sview, sp_samp, s, t, p, c0, lod, control, rgba);
  2691.    }
  2692.  
  2693.    if (sp_sview->need_swizzle) {
  2694.       float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  2695.       memcpy(rgba_temp, rgba, sizeof(rgba_temp));
  2696.       do_swizzling(&sp_sview->base, rgba_temp, rgba);
  2697.    }
  2698.  
  2699. }
  2700.  
  2701.  
  2702. /**
  2703.  * Use 3D texcoords to choose a cube face, then sample the 2D cube faces.
  2704.  * Put face info into the sampler faces[] array.
  2705.  */
  2706. static void
  2707. sample_cube(struct sp_sampler_view *sp_sview,
  2708.             struct sp_sampler *sp_samp,
  2709.             const float s[TGSI_QUAD_SIZE],
  2710.             const float t[TGSI_QUAD_SIZE],
  2711.             const float p[TGSI_QUAD_SIZE],
  2712.             const float c0[TGSI_QUAD_SIZE],
  2713.             const float c1[TGSI_QUAD_SIZE],
  2714.             enum tgsi_sampler_control control,
  2715.             float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2716. {
  2717.    unsigned j;
  2718.    float ssss[4], tttt[4];
  2719.  
  2720.    /* Not actually used, but the intermediate steps that do the
  2721.     * dereferencing don't know it.
  2722.     */
  2723.    static float pppp[4] = { 0, 0, 0, 0 };
  2724.  
  2725.    pppp[0] = c0[0];
  2726.    pppp[1] = c0[1];
  2727.    pppp[2] = c0[2];
  2728.    pppp[3] = c0[3];
  2729.    /*
  2730.      major axis
  2731.      direction    target                             sc     tc    ma
  2732.      ----------   -------------------------------    ---    ---   ---
  2733.      +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
  2734.      -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
  2735.      +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
  2736.      -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
  2737.      +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
  2738.      -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
  2739.    */
  2740.  
  2741.    /* Choose the cube face and compute new s/t coords for the 2D face.
  2742.     *
  2743.     * Use the same cube face for all four pixels in the quad.
  2744.     *
  2745.     * This isn't ideal, but if we want to use a different cube face
  2746.     * per pixel in the quad, we'd have to also compute the per-face
  2747.     * LOD here too.  That's because the four post-face-selection
  2748.     * texcoords are no longer related to each other (they're
  2749.     * per-face!)  so we can't use subtraction to compute the partial
  2750.     * deriviates to compute the LOD.  Doing so (near cube edges
  2751.     * anyway) gives us pretty much random values.
  2752.     */
  2753.    {
  2754.       /* use the average of the four pixel's texcoords to choose the face */
  2755.       const float rx = 0.25F * (s[0] + s[1] + s[2] + s[3]);
  2756.       const float ry = 0.25F * (t[0] + t[1] + t[2] + t[3]);
  2757.       const float rz = 0.25F * (p[0] + p[1] + p[2] + p[3]);
  2758.       const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
  2759.  
  2760.       if (arx >= ary && arx >= arz) {
  2761.          float sign = (rx >= 0.0F) ? 1.0F : -1.0F;
  2762.          uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X;
  2763.          for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2764.             const float ima = -0.5F / fabsf(s[j]);
  2765.             ssss[j] = sign *  p[j] * ima + 0.5F;
  2766.             tttt[j] =         t[j] * ima + 0.5F;
  2767.             sp_sview->faces[j] = face;
  2768.          }
  2769.       }
  2770.       else if (ary >= arx && ary >= arz) {
  2771.          float sign = (ry >= 0.0F) ? 1.0F : -1.0F;
  2772.          uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y;
  2773.          for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2774.             const float ima = -0.5F / fabsf(t[j]);
  2775.             ssss[j] =        -s[j] * ima + 0.5F;
  2776.             tttt[j] = sign * -p[j] * ima + 0.5F;
  2777.             sp_sview->faces[j] = face;
  2778.          }
  2779.       }
  2780.       else {
  2781.          float sign = (rz >= 0.0F) ? 1.0F : -1.0F;
  2782.          uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z;
  2783.          for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2784.             const float ima = -0.5F / fabsf(p[j]);
  2785.             ssss[j] = sign * -s[j] * ima + 0.5F;
  2786.             tttt[j] =         t[j] * ima + 0.5F;
  2787.             sp_sview->faces[j] = face;
  2788.          }
  2789.       }
  2790.    }
  2791.  
  2792.    sample_mip(sp_sview, sp_samp, ssss, tttt, pppp, c0, c1, control, rgba);
  2793. }
  2794.  
  2795.  
  2796. static void
  2797. sp_get_dims(struct sp_sampler_view *sp_sview, int level,
  2798.             int dims[4])
  2799. {
  2800.    const struct pipe_sampler_view *view = &sp_sview->base;
  2801.    const struct pipe_resource *texture = view->texture;
  2802.  
  2803.    /* undefined according to EXT_gpu_program */
  2804.    level += view->u.tex.first_level;
  2805.    if (level > view->u.tex.last_level)
  2806.       return;
  2807.  
  2808.    dims[0] = u_minify(texture->width0, level);
  2809.  
  2810.    switch(texture->target) {
  2811.    case PIPE_TEXTURE_1D_ARRAY:
  2812.       dims[1] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
  2813.       /* fallthrough */
  2814.    case PIPE_TEXTURE_1D:
  2815.       return;
  2816.    case PIPE_TEXTURE_2D_ARRAY:
  2817.       dims[2] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
  2818.       /* fallthrough */
  2819.    case PIPE_TEXTURE_2D:
  2820.    case PIPE_TEXTURE_CUBE:
  2821.    case PIPE_TEXTURE_RECT:
  2822.       dims[1] = u_minify(texture->height0, level);
  2823.       return;
  2824.    case PIPE_TEXTURE_3D:
  2825.       dims[1] = u_minify(texture->height0, level);
  2826.       dims[2] = u_minify(texture->depth0, level);
  2827.       return;
  2828.    case PIPE_TEXTURE_CUBE_ARRAY:
  2829.       dims[1] = u_minify(texture->height0, level);
  2830.       dims[2] = (view->u.tex.last_layer - view->u.tex.first_layer + 1) / 6;
  2831.       break;
  2832.    case PIPE_BUFFER:
  2833.       dims[0] /= util_format_get_blocksize(view->format);
  2834.       return;
  2835.    default:
  2836.       assert(!"unexpected texture target in sp_get_dims()");
  2837.       return;
  2838.    }
  2839. }
  2840.  
  2841. /**
  2842.  * This function is only used for getting unfiltered texels via the
  2843.  * TXF opcode.  The GL spec says that out-of-bounds texel fetches
  2844.  * produce undefined results.  Instead of crashing, lets just clamp
  2845.  * coords to the texture image size.
  2846.  */
  2847. static void
  2848. sp_get_texels(struct sp_sampler_view *sp_sview,
  2849.               const int v_i[TGSI_QUAD_SIZE],
  2850.               const int v_j[TGSI_QUAD_SIZE],
  2851.               const int v_k[TGSI_QUAD_SIZE],
  2852.               const int lod[TGSI_QUAD_SIZE],
  2853.               const int8_t offset[3],
  2854.               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2855. {
  2856.    union tex_tile_address addr;
  2857.    const struct pipe_resource *texture = sp_sview->base.texture;
  2858.    int j, c;
  2859.    const float *tx;
  2860.    int width, height, depth;
  2861.  
  2862.    addr.value = 0;
  2863.    /* TODO write a better test for LOD */
  2864.    addr.bits.level = lod[0];
  2865.  
  2866.    width = u_minify(texture->width0, addr.bits.level);
  2867.    height = u_minify(texture->height0, addr.bits.level);
  2868.    depth = u_minify(texture->depth0, addr.bits.level);
  2869.  
  2870.    switch(texture->target) {
  2871.    case PIPE_BUFFER:
  2872.    case PIPE_TEXTURE_1D:
  2873.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2874.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  2875.          tx = get_texel_2d_no_border(sp_sview, addr, x, 0);
  2876.          for (c = 0; c < 4; c++) {
  2877.             rgba[c][j] = tx[c];
  2878.          }
  2879.       }
  2880.       break;
  2881.    case PIPE_TEXTURE_1D_ARRAY:
  2882.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2883.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  2884.          int y = CLAMP(v_j[j], sp_sview->base.u.tex.first_layer, sp_sview->base.u.tex.last_layer);
  2885.          tx = get_texel_2d_no_border(sp_sview, addr, x, y);
  2886.          for (c = 0; c < 4; c++) {
  2887.             rgba[c][j] = tx[c];
  2888.          }
  2889.       }
  2890.       break;
  2891.    case PIPE_TEXTURE_2D:
  2892.    case PIPE_TEXTURE_RECT:
  2893.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2894.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  2895.          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
  2896.          tx = get_texel_2d_no_border(sp_sview, addr, x, y);
  2897.          for (c = 0; c < 4; c++) {
  2898.             rgba[c][j] = tx[c];
  2899.          }
  2900.       }
  2901.       break;
  2902.    case PIPE_TEXTURE_2D_ARRAY:
  2903.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2904.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  2905.          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
  2906.          int layer = CLAMP(v_k[j], sp_sview->base.u.tex.first_layer, sp_sview->base.u.tex.last_layer);
  2907.          tx = get_texel_3d_no_border(sp_sview, addr, x, y, layer);
  2908.          for (c = 0; c < 4; c++) {
  2909.             rgba[c][j] = tx[c];
  2910.          }
  2911.       }
  2912.       break;
  2913.    case PIPE_TEXTURE_3D:
  2914.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2915.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  2916.          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
  2917.          int z = CLAMP(v_k[j] + offset[2], 0, depth - 1);
  2918.          tx = get_texel_3d_no_border(sp_sview, addr, x, y, z);
  2919.          for (c = 0; c < 4; c++) {
  2920.             rgba[c][j] = tx[c];
  2921.          }
  2922.       }
  2923.       break;
  2924.    case PIPE_TEXTURE_CUBE: /* TXF can't work on CUBE according to spec */
  2925.    default:
  2926.       assert(!"Unknown or CUBE texture type in TXF processing\n");
  2927.       break;
  2928.    }
  2929.  
  2930.    if (sp_sview->need_swizzle) {
  2931.       float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  2932.       memcpy(rgba_temp, rgba, sizeof(rgba_temp));
  2933.       do_swizzling(&sp_sview->base, rgba_temp, rgba);
  2934.    }
  2935. }
  2936.  
  2937.  
  2938. void *
  2939. softpipe_create_sampler_state(struct pipe_context *pipe,
  2940.                               const struct pipe_sampler_state *sampler)
  2941. {
  2942.    struct sp_sampler *samp = CALLOC_STRUCT(sp_sampler);
  2943.  
  2944.    samp->base = *sampler;
  2945.  
  2946.    /* Note that (for instance) linear_texcoord_s and
  2947.     * nearest_texcoord_s may be active at the same time, if the
  2948.     * sampler min_img_filter differs from its mag_img_filter.
  2949.     */
  2950.    if (sampler->normalized_coords) {
  2951.       samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
  2952.       samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
  2953.       samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
  2954.  
  2955.       samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
  2956.       samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
  2957.       samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
  2958.    }
  2959.    else {
  2960.       samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
  2961.       samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
  2962.       samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
  2963.  
  2964.       samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
  2965.       samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
  2966.       samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
  2967.    }
  2968.  
  2969.    samp->min_img_filter = sampler->min_img_filter;
  2970.  
  2971.    switch (sampler->min_mip_filter) {
  2972.    case PIPE_TEX_MIPFILTER_NONE:
  2973.       if (sampler->min_img_filter == sampler->mag_img_filter)
  2974.          samp->mip_filter = mip_filter_none_no_filter_select;
  2975.       else
  2976.          samp->mip_filter = mip_filter_none;
  2977.       break;
  2978.  
  2979.    case PIPE_TEX_MIPFILTER_NEAREST:
  2980.       samp->mip_filter = mip_filter_nearest;
  2981.       break;
  2982.  
  2983.    case PIPE_TEX_MIPFILTER_LINEAR:
  2984.       if (sampler->min_img_filter == sampler->mag_img_filter &&
  2985.           sampler->normalized_coords &&
  2986.           sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
  2987.           sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
  2988.           sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
  2989.           sampler->max_anisotropy <= 1) {
  2990.          samp->min_mag_equal_repeat_linear = TRUE;
  2991.       }
  2992.       samp->mip_filter = mip_filter_linear;
  2993.  
  2994.       /* Anisotropic filtering extension. */
  2995.       if (sampler->max_anisotropy > 1) {
  2996.          samp->mip_filter = mip_filter_linear_aniso;
  2997.  
  2998.          /* Override min_img_filter:
  2999.           * min_img_filter needs to be set to NEAREST since we need to access
  3000.           * each texture pixel as it is and weight it later; using linear
  3001.           * filters will have incorrect results.
  3002.           * By setting the filter to NEAREST here, we can avoid calling the
  3003.           * generic img_filter_2d_nearest in the anisotropic filter function,
  3004.           * making it possible to use one of the accelerated implementations
  3005.           */
  3006.          samp->min_img_filter = PIPE_TEX_FILTER_NEAREST;
  3007.  
  3008.          /* on first access create the lookup table containing the filter weights. */
  3009.         if (!weightLut) {
  3010.            create_filter_table();
  3011.         }
  3012.       }
  3013.       break;
  3014.    }
  3015.    if (samp->min_img_filter == sampler->mag_img_filter) {
  3016.       samp->min_mag_equal = TRUE;
  3017.    }
  3018.  
  3019.    return (void *)samp;
  3020. }
  3021.  
  3022.  
  3023. compute_lambda_func
  3024. softpipe_get_lambda_func(const struct pipe_sampler_view *view, unsigned shader)
  3025. {
  3026.    if (shader != PIPE_SHADER_FRAGMENT)
  3027.       return compute_lambda_vert;
  3028.  
  3029.    switch (view->texture->target) {
  3030.    case PIPE_BUFFER:
  3031.    case PIPE_TEXTURE_1D:
  3032.    case PIPE_TEXTURE_1D_ARRAY:
  3033.       return compute_lambda_1d;
  3034.    case PIPE_TEXTURE_2D:
  3035.    case PIPE_TEXTURE_2D_ARRAY:
  3036.    case PIPE_TEXTURE_RECT:
  3037.    case PIPE_TEXTURE_CUBE:
  3038.    case PIPE_TEXTURE_CUBE_ARRAY:
  3039.       return compute_lambda_2d;
  3040.    case PIPE_TEXTURE_3D:
  3041.       return compute_lambda_3d;
  3042.    default:
  3043.       assert(0);
  3044.       return compute_lambda_1d;
  3045.    }
  3046. }
  3047.  
  3048.  
  3049. struct pipe_sampler_view *
  3050. softpipe_create_sampler_view(struct pipe_context *pipe,
  3051.                              struct pipe_resource *resource,
  3052.                              const struct pipe_sampler_view *templ)
  3053. {
  3054.    struct sp_sampler_view *sview = CALLOC_STRUCT(sp_sampler_view);
  3055.    struct softpipe_resource *spr = (struct softpipe_resource *)resource;
  3056.  
  3057.    if (sview) {
  3058.       struct pipe_sampler_view *view = &sview->base;
  3059.       *view = *templ;
  3060.       view->reference.count = 1;
  3061.       view->texture = NULL;
  3062.       pipe_resource_reference(&view->texture, resource);
  3063.       view->context = pipe;
  3064.  
  3065.       if (any_swizzle(view)) {
  3066.          sview->need_swizzle = TRUE;
  3067.       }
  3068.  
  3069.       if (resource->target == PIPE_TEXTURE_CUBE ||
  3070.           resource->target == PIPE_TEXTURE_CUBE_ARRAY)
  3071.          sview->get_samples = sample_cube;
  3072.       else {
  3073.          sview->get_samples = sample_mip;
  3074.       }
  3075.       sview->pot2d = spr->pot &&
  3076.                      (resource->target == PIPE_TEXTURE_2D ||
  3077.                       resource->target == PIPE_TEXTURE_RECT);
  3078.  
  3079.       sview->xpot = util_logbase2( resource->width0 );
  3080.       sview->ypot = util_logbase2( resource->height0 );
  3081.    }
  3082.  
  3083.    return (struct pipe_sampler_view *) sview;
  3084. }
  3085.  
  3086.  
  3087. static void
  3088. sp_tgsi_get_dims(struct tgsi_sampler *tgsi_sampler,
  3089.                  const unsigned sview_index,
  3090.                  int level, int dims[4])
  3091. {
  3092.    struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
  3093.  
  3094.    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
  3095.    /* TODO should have defined behavior if no texture is bound. */
  3096.    sp_get_dims(&sp_samp->sp_sview[sview_index], level, dims);
  3097. }
  3098.  
  3099.  
  3100. static void
  3101. sp_tgsi_get_samples(struct tgsi_sampler *tgsi_sampler,
  3102.                     const unsigned sview_index,
  3103.                     const unsigned sampler_index,
  3104.                     const float s[TGSI_QUAD_SIZE],
  3105.                     const float t[TGSI_QUAD_SIZE],
  3106.                     const float p[TGSI_QUAD_SIZE],
  3107.                     const float c0[TGSI_QUAD_SIZE],
  3108.                     const float lod[TGSI_QUAD_SIZE],
  3109.                     float derivs[3][2][TGSI_QUAD_SIZE],
  3110.                     const int8_t offset[3],
  3111.                     enum tgsi_sampler_control control,
  3112.                     float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  3113. {
  3114.    struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
  3115.  
  3116.    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
  3117.    assert(sampler_index < PIPE_MAX_SAMPLERS);
  3118.    assert(sp_samp->sp_sampler[sampler_index]);
  3119.    /* FIXME should have defined behavior if no texture is bound. */
  3120.    assert(sp_samp->sp_sview[sview_index].get_samples);
  3121.    sp_samp->sp_sview[sview_index].get_samples(&sp_samp->sp_sview[sview_index],
  3122.                                               sp_samp->sp_sampler[sampler_index],
  3123.                                               s, t, p, c0, lod, control, rgba);
  3124. }
  3125.  
  3126.  
  3127. static void
  3128. sp_tgsi_get_texel(struct tgsi_sampler *tgsi_sampler,
  3129.                   const unsigned sview_index,
  3130.                   const int i[TGSI_QUAD_SIZE],
  3131.                   const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
  3132.                   const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
  3133.                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  3134. {
  3135.    struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
  3136.  
  3137.    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
  3138.    /* FIXME should have defined behavior if no texture is bound. */
  3139.    assert(sp_samp->sp_sview[sview_index].base.texture);
  3140.    sp_get_texels(&sp_samp->sp_sview[sview_index], i, j, k, lod, offset, rgba);
  3141. }
  3142.  
  3143.  
  3144. struct sp_tgsi_sampler *
  3145. sp_create_tgsi_sampler(void)
  3146. {
  3147.    struct sp_tgsi_sampler *samp = CALLOC_STRUCT(sp_tgsi_sampler);
  3148.    if (!samp)
  3149.       return NULL;
  3150.  
  3151.    samp->base.get_dims = sp_tgsi_get_dims;
  3152.    samp->base.get_samples = sp_tgsi_get_samples;
  3153.    samp->base.get_texel = sp_tgsi_get_texel;
  3154.  
  3155.    return samp;
  3156. }
  3157.  
  3158.