Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 VMware, Inc.
  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 VMWARE 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 int
  478. coord_to_layer(float coord, unsigned first_layer, unsigned last_layer)
  479. {
  480.    int c = util_ifloor(coord + 0.5F);
  481.    return CLAMP(c, (int)first_layer, (int)last_layer);
  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. /*
  613.  * Here's the complete logic (HOLY CRAP) for finding next face and doing the
  614.  * corresponding coord wrapping, implemented by get_next_face,
  615.  * get_next_xcoord, get_next_ycoord.
  616.  * Read like that (first line):
  617.  * If face is +x and s coord is below zero, then
  618.  * new face is +z, new s is max , new t is old t
  619.  * (max is always cube size - 1).
  620.  *
  621.  * +x s- -> +z: s = max,   t = t
  622.  * +x s+ -> -z: s = 0,     t = t
  623.  * +x t- -> +y: s = max,   t = max-s
  624.  * +x t+ -> -y: s = max,   t = s
  625.  *
  626.  * -x s- -> -z: s = max,   t = t
  627.  * -x s+ -> +z: s = 0,     t = t
  628.  * -x t- -> +y: s = 0,     t = s
  629.  * -x t+ -> -y: s = 0,     t = max-s
  630.  *
  631.  * +y s- -> -x: s = t,     t = 0
  632.  * +y s+ -> +x: s = max-t, t = 0
  633.  * +y t- -> -z: s = max-s, t = 0
  634.  * +y t+ -> +z: s = s,     t = 0
  635.  *
  636.  * -y s- -> -x: s = max-t, t = max
  637.  * -y s+ -> +x: s = t,     t = max
  638.  * -y t- -> +z: s = s,     t = max
  639.  * -y t+ -> -z: s = max-s, t = max
  640.  
  641.  * +z s- -> -x: s = max,   t = t
  642.  * +z s+ -> +x: s = 0,     t = t
  643.  * +z t- -> +y: s = s,     t = max
  644.  * +z t+ -> -y: s = s,     t = 0
  645.  
  646.  * -z s- -> +x: s = max,   t = t
  647.  * -z s+ -> -x: s = 0,     t = t
  648.  * -z t- -> +y: s = max-s, t = 0
  649.  * -z t+ -> -y: s = max-s, t = max
  650.  */
  651.  
  652.  
  653. /*
  654.  * seamless cubemap neighbour array.
  655.  * this array is used to find the adjacent face in each of 4 directions,
  656.  * left, right, up, down. (or -x, +x, -y, +y).
  657.  */
  658. static const unsigned face_array[PIPE_TEX_FACE_MAX][4] = {
  659.    /* pos X first then neg X is Z different, Y the same */
  660.    /* PIPE_TEX_FACE_POS_X,*/
  661.    { PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z,
  662.      PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y },
  663.    /* PIPE_TEX_FACE_NEG_X */
  664.    { PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z,
  665.      PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y },
  666.  
  667.    /* pos Y first then neg Y is X different, X the same */
  668.    /* PIPE_TEX_FACE_POS_Y */
  669.    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
  670.      PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z },
  671.  
  672.    /* PIPE_TEX_FACE_NEG_Y */
  673.    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
  674.      PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z },
  675.  
  676.    /* pos Z first then neg Y is X different, X the same */
  677.    /* PIPE_TEX_FACE_POS_Z */
  678.    { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
  679.      PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y },
  680.  
  681.    /* PIPE_TEX_FACE_NEG_Z */
  682.    { PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_NEG_X,
  683.      PIPE_TEX_FACE_POS_Y, PIPE_TEX_FACE_NEG_Y }
  684. };
  685.  
  686. static INLINE unsigned
  687. get_next_face(unsigned face, int idx)
  688. {
  689.    return face_array[face][idx];
  690. }
  691.  
  692. /*
  693.  * return a new xcoord based on old face, old coords, cube size
  694.  * and fall_off_index (0 for x-, 1 for x+, 2 for y-, 3 for y+)
  695.  */
  696. static INLINE int
  697. get_next_xcoord(unsigned face, unsigned fall_off_index, int max, int xc, int yc)
  698. {
  699.    if ((face == 0 && fall_off_index != 1) ||
  700.        (face == 1 && fall_off_index == 0) ||
  701.        (face == 4 && fall_off_index == 0) ||
  702.        (face == 5 && fall_off_index == 0)) {
  703.       return max;
  704.    }
  705.    if ((face == 1 && fall_off_index != 0) ||
  706.        (face == 0 && fall_off_index == 1) ||
  707.        (face == 4 && fall_off_index == 1) ||
  708.        (face == 5 && fall_off_index == 1)) {
  709.       return 0;
  710.    }
  711.    if ((face == 4 && fall_off_index >= 2) ||
  712.        (face == 2 && fall_off_index == 3) ||
  713.        (face == 3 && fall_off_index == 2)) {
  714.       return xc;
  715.    }
  716.    if ((face == 5 && fall_off_index >= 2) ||
  717.        (face == 2 && fall_off_index == 2) ||
  718.        (face == 3 && fall_off_index == 3)) {
  719.       return max - xc;
  720.    }
  721.    if ((face == 2 && fall_off_index == 0) ||
  722.        (face == 3 && fall_off_index == 1)) {
  723.       return yc;
  724.    }
  725.    /* (face == 2 && fall_off_index == 1) ||
  726.       (face == 3 && fall_off_index == 0)) */
  727.    return max - yc;
  728. }
  729.  
  730. /*
  731.  * return a new ycoord based on old face, old coords, cube size
  732.  * and fall_off_index (0 for x-, 1 for x+, 2 for y-, 3 for y+)
  733.  */
  734. static INLINE int
  735. get_next_ycoord(unsigned face, unsigned fall_off_index, int max, int xc, int yc)
  736. {
  737.    if ((fall_off_index <= 1) && (face <= 1 || face >= 4)) {
  738.       return yc;
  739.    }
  740.    if (face == 2 ||
  741.        (face == 4 && fall_off_index == 3) ||
  742.        (face == 5 && fall_off_index == 2)) {
  743.       return 0;
  744.    }
  745.    if (face == 3 ||
  746.        (face == 4 && fall_off_index == 2) ||
  747.        (face == 5 && fall_off_index == 3)) {
  748.       return max;
  749.    }
  750.    if ((face == 0 && fall_off_index == 3) ||
  751.        (face == 1 && fall_off_index == 2)) {
  752.       return xc;
  753.    }
  754.    /* (face == 0 && fall_off_index == 2) ||
  755.       (face == 1 && fall_off_index == 3) */
  756.    return max - xc;
  757. }
  758.  
  759.  
  760. /* Gather a quad of adjacent texels within a tile:
  761.  */
  762. static INLINE void
  763. get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_view *sp_sview,
  764.                                         union tex_tile_address addr,
  765.                                         unsigned x, unsigned y,
  766.                                         const float *out[4])
  767. {
  768.     const struct softpipe_tex_cached_tile *tile;
  769.  
  770.    addr.bits.x = x / TEX_TILE_SIZE;
  771.    addr.bits.y = y / TEX_TILE_SIZE;
  772.    y %= TEX_TILE_SIZE;
  773.    x %= TEX_TILE_SIZE;
  774.  
  775.    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
  776.      
  777.    out[0] = &tile->data.color[y  ][x  ][0];
  778.    out[1] = &tile->data.color[y  ][x+1][0];
  779.    out[2] = &tile->data.color[y+1][x  ][0];
  780.    out[3] = &tile->data.color[y+1][x+1][0];
  781. }
  782.  
  783.  
  784. /* Gather a quad of potentially non-adjacent texels:
  785.  */
  786. static INLINE void
  787. get_texel_quad_2d_no_border(const struct sp_sampler_view *sp_sview,
  788.                             union tex_tile_address addr,
  789.                             int x0, int y0,
  790.                             int x1, int y1,
  791.                             const float *out[4])
  792. {
  793.    out[0] = get_texel_2d_no_border( sp_sview, addr, x0, y0 );
  794.    out[1] = get_texel_2d_no_border( sp_sview, addr, x1, y0 );
  795.    out[2] = get_texel_2d_no_border( sp_sview, addr, x0, y1 );
  796.    out[3] = get_texel_2d_no_border( sp_sview, addr, x1, y1 );
  797. }
  798.  
  799. /* Can involve a lot of unnecessary checks for border color:
  800.  */
  801. static INLINE void
  802. get_texel_quad_2d(const struct sp_sampler_view *sp_sview,
  803.                   const struct sp_sampler *sp_samp,
  804.                   union tex_tile_address addr,
  805.                   int x0, int y0,
  806.                   int x1, int y1,
  807.                   const float *out[4])
  808. {
  809.    out[0] = get_texel_2d( sp_sview, sp_samp, addr, x0, y0 );
  810.    out[1] = get_texel_2d( sp_sview, sp_samp, addr, x1, y0 );
  811.    out[3] = get_texel_2d( sp_sview, sp_samp, addr, x1, y1 );
  812.    out[2] = get_texel_2d( sp_sview, sp_samp, addr, x0, y1 );
  813. }
  814.  
  815.  
  816.  
  817. /* 3d variants:
  818.  */
  819. static INLINE const float *
  820. get_texel_3d_no_border(const struct sp_sampler_view *sp_sview,
  821.                        union tex_tile_address addr, int x, int y, int z)
  822. {
  823.    const struct softpipe_tex_cached_tile *tile;
  824.  
  825.    addr.bits.x = x / TEX_TILE_SIZE;
  826.    addr.bits.y = y / TEX_TILE_SIZE;
  827.    addr.bits.z = z;
  828.    y %= TEX_TILE_SIZE;
  829.    x %= TEX_TILE_SIZE;
  830.  
  831.    tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
  832.  
  833.    return &tile->data.color[y][x][0];
  834. }
  835.  
  836.  
  837. static INLINE const float *
  838. get_texel_3d(const struct sp_sampler_view *sp_sview,
  839.              const struct sp_sampler *sp_samp,
  840.              union tex_tile_address addr, int x, int y, int z)
  841. {
  842.    const struct pipe_resource *texture = sp_sview->base.texture;
  843.    unsigned level = addr.bits.level;
  844.  
  845.    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
  846.        y < 0 || y >= (int) u_minify(texture->height0, level) ||
  847.        z < 0 || z >= (int) u_minify(texture->depth0, level)) {
  848.       return sp_samp->base.border_color.f;
  849.    }
  850.    else {
  851.       return get_texel_3d_no_border( sp_sview, addr, x, y, z );
  852.    }
  853. }
  854.  
  855.  
  856. /* Get texel pointer for 1D array texture */
  857. static INLINE const float *
  858. get_texel_1d_array(const struct sp_sampler_view *sp_sview,
  859.                    const struct sp_sampler *sp_samp,
  860.                    union tex_tile_address addr, int x, int y)
  861. {
  862.    const struct pipe_resource *texture = sp_sview->base.texture;
  863.    unsigned level = addr.bits.level;
  864.  
  865.    if (x < 0 || x >= (int) u_minify(texture->width0, level)) {
  866.       return sp_samp->base.border_color.f;
  867.    }
  868.    else {
  869.       return get_texel_2d_no_border(sp_sview, addr, x, y);
  870.    }
  871. }
  872.  
  873.  
  874. /* Get texel pointer for 2D array texture */
  875. static INLINE const float *
  876. get_texel_2d_array(const struct sp_sampler_view *sp_sview,
  877.                    const struct sp_sampler *sp_samp,
  878.                    union tex_tile_address addr, int x, int y, int layer)
  879. {
  880.    const struct pipe_resource *texture = sp_sview->base.texture;
  881.    unsigned level = addr.bits.level;
  882.  
  883.    assert(layer < (int) texture->array_size);
  884.    assert(layer >= 0);
  885.  
  886.    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
  887.        y < 0 || y >= (int) u_minify(texture->height0, level)) {
  888.       return sp_samp->base.border_color.f;
  889.    }
  890.    else {
  891.       return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
  892.    }
  893. }
  894.  
  895.  
  896. static INLINE const float *
  897. get_texel_cube_seamless(const struct sp_sampler_view *sp_sview,
  898.                         union tex_tile_address addr, int x, int y,
  899.                         float *corner, int layer, unsigned face)
  900. {
  901.    const struct pipe_resource *texture = sp_sview->base.texture;
  902.    unsigned level = addr.bits.level;
  903.    int new_x, new_y, max_x;
  904.  
  905.    max_x = (int) u_minify(texture->width0, level);
  906.  
  907.    assert(texture->width0 == texture->height0);
  908.    new_x = x;
  909.    new_y = y;
  910.  
  911.    /* change the face */
  912.    if (x < 0) {
  913.       /*
  914.        * Cheat with corners. They are difficult and I believe because we don't get
  915.        * per-pixel faces we can actually have multiple corner texels per pixel,
  916.        * which screws things up majorly in any case (as the per spec behavior is
  917.        * to average the 3 remaining texels, which we might not have).
  918.        * Hence just make sure that the 2nd coord is clamped, will simply pick the
  919.        * sample which would have fallen off the x coord, but not y coord.
  920.        * So the filter weight of the samples will be wrong, but at least this
  921.        * ensures that only valid texels near the corner are used.
  922.        */
  923.       if (y < 0 || y >= max_x) {
  924.          y = CLAMP(y, 0, max_x - 1);
  925.       }
  926.       new_x = get_next_xcoord(face, 0, max_x -1, x, y);
  927.       new_y = get_next_ycoord(face, 0, max_x -1, x, y);
  928.       face = get_next_face(face, 0);
  929.    } else if (x >= max_x) {
  930.       if (y < 0 || y >= max_x) {
  931.          y = CLAMP(y, 0, max_x - 1);
  932.       }
  933.       new_x = get_next_xcoord(face, 1, max_x -1, x, y);
  934.       new_y = get_next_ycoord(face, 1, max_x -1, x, y);
  935.       face = get_next_face(face, 1);
  936.    } else if (y < 0) {
  937.       new_x = get_next_xcoord(face, 2, max_x -1, x, y);
  938.       new_y = get_next_ycoord(face, 2, max_x -1, x, y);
  939.       face = get_next_face(face, 2);
  940.    } else if (y >= max_x) {
  941.       new_x = get_next_xcoord(face, 3, max_x -1, x, y);
  942.       new_y = get_next_ycoord(face, 3, max_x -1, x, y);
  943.       face = get_next_face(face, 3);
  944.    }
  945.  
  946.    return get_texel_3d_no_border(sp_sview, addr, new_x, new_y, layer + face);
  947. }
  948.  
  949.  
  950. /* Get texel pointer for cube array texture */
  951. static INLINE const float *
  952. get_texel_cube_array(const struct sp_sampler_view *sp_sview,
  953.                      const struct sp_sampler *sp_samp,
  954.                      union tex_tile_address addr, int x, int y, int layer)
  955. {
  956.    const struct pipe_resource *texture = sp_sview->base.texture;
  957.    unsigned level = addr.bits.level;
  958.  
  959.    assert(layer < (int) texture->array_size);
  960.    assert(layer >= 0);
  961.  
  962.    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
  963.        y < 0 || y >= (int) u_minify(texture->height0, level)) {
  964.       return sp_samp->base.border_color.f;
  965.    }
  966.    else {
  967.       return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
  968.    }
  969. }
  970. /**
  971.  * Given the logbase2 of a mipmap's base level size and a mipmap level,
  972.  * return the size (in texels) of that mipmap level.
  973.  * For example, if level[0].width = 256 then base_pot will be 8.
  974.  * If level = 2, then we'll return 64 (the width at level=2).
  975.  * Return 1 if level > base_pot.
  976.  */
  977. static INLINE unsigned
  978. pot_level_size(unsigned base_pot, unsigned level)
  979. {
  980.    return (base_pot >= level) ? (1 << (base_pot - level)) : 1;
  981. }
  982.  
  983.  
  984. static void
  985. print_sample(const char *function, const float *rgba)
  986. {
  987.    debug_printf("%s %g %g %g %g\n",
  988.                 function,
  989.                 rgba[0], rgba[TGSI_NUM_CHANNELS], rgba[2*TGSI_NUM_CHANNELS], rgba[3*TGSI_NUM_CHANNELS]);
  990. }
  991.  
  992.  
  993. static void
  994. print_sample_4(const char *function, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  995. {
  996.    debug_printf("%s %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n",
  997.                 function,
  998.                 rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0],
  999.                 rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1],
  1000.                 rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2],
  1001.                 rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]);
  1002. }
  1003.  
  1004.  
  1005. /* Some image-filter fastpaths:
  1006.  */
  1007. static INLINE void
  1008. img_filter_2d_linear_repeat_POT(struct sp_sampler_view *sp_sview,
  1009.                                 struct sp_sampler *sp_samp,
  1010.                                 float s,
  1011.                                 float t,
  1012.                                 float p,
  1013.                                 unsigned level,
  1014.                                 unsigned face_id,
  1015.                                 float *rgba)
  1016. {
  1017.    unsigned xpot = pot_level_size(sp_sview->xpot, level);
  1018.    unsigned ypot = pot_level_size(sp_sview->ypot, level);
  1019.    int xmax = (xpot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, xpot) - 1; */
  1020.    int ymax = (ypot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, ypot) - 1; */
  1021.    union tex_tile_address addr;
  1022.    int c;
  1023.  
  1024.    float u = s * xpot - 0.5F;
  1025.    float v = t * ypot - 0.5F;
  1026.  
  1027.    int uflr = util_ifloor(u);
  1028.    int vflr = util_ifloor(v);
  1029.  
  1030.    float xw = u - (float)uflr;
  1031.    float yw = v - (float)vflr;
  1032.  
  1033.    int x0 = uflr & (xpot - 1);
  1034.    int y0 = vflr & (ypot - 1);
  1035.  
  1036.    const float *tx[4];
  1037.      
  1038.    addr.value = 0;
  1039.    addr.bits.level = level;
  1040.  
  1041.    /* Can we fetch all four at once:
  1042.     */
  1043.    if (x0 < xmax && y0 < ymax) {
  1044.       get_texel_quad_2d_no_border_single_tile(sp_sview, addr, x0, y0, tx);
  1045.    }
  1046.    else {
  1047.       unsigned x1 = (x0 + 1) & (xpot - 1);
  1048.       unsigned y1 = (y0 + 1) & (ypot - 1);
  1049.       get_texel_quad_2d_no_border(sp_sview, addr, x0, y0, x1, y1, tx);
  1050.    }
  1051.  
  1052.    /* interpolate R, G, B, A */
  1053.    for (c = 0; c < TGSI_QUAD_SIZE; c++) {
  1054.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  1055.                                        tx[0][c], tx[1][c],
  1056.                                        tx[2][c], tx[3][c]);
  1057.    }
  1058.  
  1059.    if (DEBUG_TEX) {
  1060.       print_sample(__FUNCTION__, rgba);
  1061.    }
  1062. }
  1063.  
  1064.  
  1065. static INLINE void
  1066. img_filter_2d_nearest_repeat_POT(struct sp_sampler_view *sp_sview,
  1067.                                  struct sp_sampler *sp_samp,
  1068.                                  float s,
  1069.                                  float t,
  1070.                                  float p,
  1071.                                  unsigned level,
  1072.                                  unsigned face_id,
  1073.                                  float rgba[TGSI_QUAD_SIZE])
  1074. {
  1075.    unsigned xpot = pot_level_size(sp_sview->xpot, level);
  1076.    unsigned ypot = pot_level_size(sp_sview->ypot, level);
  1077.    const float *out;
  1078.    union tex_tile_address addr;
  1079.    int c;
  1080.  
  1081.    float u = s * xpot;
  1082.    float v = t * ypot;
  1083.  
  1084.    int uflr = util_ifloor(u);
  1085.    int vflr = util_ifloor(v);
  1086.  
  1087.    int x0 = uflr & (xpot - 1);
  1088.    int y0 = vflr & (ypot - 1);
  1089.  
  1090.    addr.value = 0;
  1091.    addr.bits.level = level;
  1092.  
  1093.    out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
  1094.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1095.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1096.  
  1097.    if (DEBUG_TEX) {
  1098.       print_sample(__FUNCTION__, rgba);
  1099.    }
  1100. }
  1101.  
  1102.  
  1103. static INLINE void
  1104. img_filter_2d_nearest_clamp_POT(struct sp_sampler_view *sp_sview,
  1105.                                 struct sp_sampler *sp_samp,
  1106.                                 float s,
  1107.                                 float t,
  1108.                                 float p,
  1109.                                 unsigned level,
  1110.                                 unsigned face_id,
  1111.                                 float rgba[TGSI_QUAD_SIZE])
  1112. {
  1113.    unsigned xpot = pot_level_size(sp_sview->xpot, level);
  1114.    unsigned ypot = pot_level_size(sp_sview->ypot, level);
  1115.    union tex_tile_address addr;
  1116.    int c;
  1117.  
  1118.    float u = s * xpot;
  1119.    float v = t * ypot;
  1120.  
  1121.    int x0, y0;
  1122.    const float *out;
  1123.  
  1124.    addr.value = 0;
  1125.    addr.bits.level = level;
  1126.  
  1127.    x0 = util_ifloor(u);
  1128.    if (x0 < 0)
  1129.       x0 = 0;
  1130.    else if (x0 > (int) xpot - 1)
  1131.       x0 = xpot - 1;
  1132.  
  1133.    y0 = util_ifloor(v);
  1134.    if (y0 < 0)
  1135.       y0 = 0;
  1136.    else if (y0 > (int) ypot - 1)
  1137.       y0 = ypot - 1;
  1138.    
  1139.    out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
  1140.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1141.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1142.  
  1143.    if (DEBUG_TEX) {
  1144.       print_sample(__FUNCTION__, rgba);
  1145.    }
  1146. }
  1147.  
  1148.  
  1149. static void
  1150. img_filter_1d_nearest(struct sp_sampler_view *sp_sview,
  1151.                       struct sp_sampler *sp_samp,
  1152.                       float s,
  1153.                       float t,
  1154.                       float p,
  1155.                       unsigned level,
  1156.                       unsigned face_id,
  1157.                       float rgba[TGSI_QUAD_SIZE])
  1158. {
  1159.    const struct pipe_resource *texture = sp_sview->base.texture;
  1160.    int width;
  1161.    int x;
  1162.    union tex_tile_address addr;
  1163.    const float *out;
  1164.    int c;
  1165.  
  1166.    width = u_minify(texture->width0, level);
  1167.  
  1168.    assert(width > 0);
  1169.  
  1170.    addr.value = 0;
  1171.    addr.bits.level = level;
  1172.  
  1173.    sp_samp->nearest_texcoord_s(s, width, &x);
  1174.  
  1175.    out = get_texel_2d(sp_sview, sp_samp, addr, x, 0);
  1176.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1177.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1178.  
  1179.    if (DEBUG_TEX) {
  1180.       print_sample(__FUNCTION__, rgba);
  1181.    }
  1182. }
  1183.  
  1184.  
  1185. static void
  1186. img_filter_1d_array_nearest(struct sp_sampler_view *sp_sview,
  1187.                             struct sp_sampler *sp_samp,
  1188.                             float s,
  1189.                             float t,
  1190.                             float p,
  1191.                             unsigned level,
  1192.                             unsigned face_id,
  1193.                             float *rgba)
  1194. {
  1195.    const struct pipe_resource *texture = sp_sview->base.texture;
  1196.    int width;
  1197.    int x, layer;
  1198.    union tex_tile_address addr;
  1199.    const float *out;
  1200.    int c;
  1201.  
  1202.    width = u_minify(texture->width0, level);
  1203.  
  1204.    assert(width > 0);
  1205.  
  1206.    addr.value = 0;
  1207.    addr.bits.level = level;
  1208.  
  1209.    sp_samp->nearest_texcoord_s(s, width, &x);
  1210.    layer = coord_to_layer(t, sp_sview->base.u.tex.first_layer,
  1211.                           sp_sview->base.u.tex.last_layer);
  1212.  
  1213.    out = get_texel_1d_array(sp_sview, sp_samp, addr, x, layer);
  1214.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1215.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1216.  
  1217.    if (DEBUG_TEX) {
  1218.       print_sample(__FUNCTION__, rgba);
  1219.    }
  1220. }
  1221.  
  1222.  
  1223. static void
  1224. img_filter_2d_nearest(struct sp_sampler_view *sp_sview,
  1225.                       struct sp_sampler *sp_samp,
  1226.                       float s,
  1227.                       float t,
  1228.                       float p,
  1229.                       unsigned level,
  1230.                       unsigned face_id,
  1231.                       float *rgba)
  1232. {
  1233.    const struct pipe_resource *texture = sp_sview->base.texture;
  1234.    int width, height;
  1235.    int x, y;
  1236.    union tex_tile_address addr;
  1237.    const float *out;
  1238.    int c;
  1239.  
  1240.    width = u_minify(texture->width0, level);
  1241.    height = u_minify(texture->height0, level);
  1242.  
  1243.    assert(width > 0);
  1244.    assert(height > 0);
  1245.  
  1246.    addr.value = 0;
  1247.    addr.bits.level = level;
  1248.  
  1249.    sp_samp->nearest_texcoord_s(s, width, &x);
  1250.    sp_samp->nearest_texcoord_t(t, height, &y);
  1251.  
  1252.    out = get_texel_2d(sp_sview, sp_samp, addr, x, y);
  1253.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1254.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1255.  
  1256.    if (DEBUG_TEX) {
  1257.       print_sample(__FUNCTION__, rgba);
  1258.    }
  1259. }
  1260.  
  1261.  
  1262. static void
  1263. img_filter_2d_array_nearest(struct sp_sampler_view *sp_sview,
  1264.                             struct sp_sampler *sp_samp,
  1265.                             float s,
  1266.                             float t,
  1267.                             float p,
  1268.                             unsigned level,
  1269.                             unsigned face_id,
  1270.                             float *rgba)
  1271. {
  1272.    const struct pipe_resource *texture = sp_sview->base.texture;
  1273.    int width, height;
  1274.    int x, y, layer;
  1275.    union tex_tile_address addr;
  1276.    const float *out;
  1277.    int c;
  1278.  
  1279.    width = u_minify(texture->width0, level);
  1280.    height = u_minify(texture->height0, level);
  1281.  
  1282.    assert(width > 0);
  1283.    assert(height > 0);
  1284.  
  1285.    addr.value = 0;
  1286.    addr.bits.level = level;
  1287.  
  1288.    sp_samp->nearest_texcoord_s(s, width, &x);
  1289.    sp_samp->nearest_texcoord_t(t, height, &y);
  1290.    layer = coord_to_layer(p, sp_sview->base.u.tex.first_layer,
  1291.                           sp_sview->base.u.tex.last_layer);
  1292.  
  1293.    out = get_texel_2d_array(sp_sview, sp_samp, addr, x, y, layer);
  1294.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1295.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1296.  
  1297.    if (DEBUG_TEX) {
  1298.       print_sample(__FUNCTION__, rgba);
  1299.    }
  1300. }
  1301.  
  1302.  
  1303. static void
  1304. img_filter_cube_nearest(struct sp_sampler_view *sp_sview,
  1305.                         struct sp_sampler *sp_samp,
  1306.                         float s,
  1307.                         float t,
  1308.                         float p,
  1309.                         unsigned level,
  1310.                         unsigned face_id,
  1311.                         float *rgba)
  1312. {
  1313.    const struct pipe_resource *texture = sp_sview->base.texture;
  1314.    int width, height;
  1315.    int x, y, layerface;
  1316.    union tex_tile_address addr;
  1317.    const float *out;
  1318.    int c;
  1319.  
  1320.    width = u_minify(texture->width0, level);
  1321.    height = u_minify(texture->height0, level);
  1322.  
  1323.    assert(width > 0);
  1324.    assert(height > 0);
  1325.  
  1326.    addr.value = 0;
  1327.    addr.bits.level = level;
  1328.  
  1329.    /*
  1330.     * If NEAREST filtering is done within a miplevel, always apply wrap
  1331.     * mode CLAMP_TO_EDGE.
  1332.     */
  1333.    if (sp_samp->base.seamless_cube_map) {
  1334.       wrap_nearest_clamp_to_edge(s, width, &x);
  1335.       wrap_nearest_clamp_to_edge(t, height, &y);
  1336.    } else {
  1337.       /* Would probably make sense to ignore mode and just do edge clamp */
  1338.       sp_samp->nearest_texcoord_s(s, width, &x);
  1339.       sp_samp->nearest_texcoord_t(t, height, &y);
  1340.    }
  1341.  
  1342.    layerface = face_id + sp_sview->base.u.tex.first_layer;
  1343.    out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layerface);
  1344.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1345.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1346.  
  1347.    if (DEBUG_TEX) {
  1348.       print_sample(__FUNCTION__, rgba);
  1349.    }
  1350. }
  1351.  
  1352. static void
  1353. img_filter_cube_array_nearest(struct sp_sampler_view *sp_sview,
  1354.                               struct sp_sampler *sp_samp,
  1355.                               float s,
  1356.                               float t,
  1357.                               float p,
  1358.                               unsigned level,
  1359.                               unsigned face_id,
  1360.                               float *rgba)
  1361. {
  1362.    const struct pipe_resource *texture = sp_sview->base.texture;
  1363.    int width, height;
  1364.    int x, y, layerface;
  1365.    union tex_tile_address addr;
  1366.    const float *out;
  1367.    int c;
  1368.  
  1369.    width = u_minify(texture->width0, level);
  1370.    height = u_minify(texture->height0, level);
  1371.  
  1372.    assert(width > 0);
  1373.    assert(height > 0);
  1374.  
  1375.    addr.value = 0;
  1376.    addr.bits.level = level;
  1377.  
  1378.    sp_samp->nearest_texcoord_s(s, width, &x);
  1379.    sp_samp->nearest_texcoord_t(t, height, &y);
  1380.    layerface = coord_to_layer(6 * p + sp_sview->base.u.tex.first_layer,
  1381.                               sp_sview->base.u.tex.first_layer,
  1382.                               sp_sview->base.u.tex.last_layer - 5) + face_id;
  1383.  
  1384.    out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layerface);
  1385.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1386.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1387.  
  1388.    if (DEBUG_TEX) {
  1389.       print_sample(__FUNCTION__, rgba);
  1390.    }
  1391. }
  1392.  
  1393. static void
  1394. img_filter_3d_nearest(struct sp_sampler_view *sp_sview,
  1395.                       struct sp_sampler *sp_samp,
  1396.                       float s,
  1397.                       float t,
  1398.                       float p,
  1399.                       unsigned level,
  1400.                       unsigned face_id,
  1401.                       float *rgba)
  1402. {
  1403.    const struct pipe_resource *texture = sp_sview->base.texture;
  1404.    int width, height, depth;
  1405.    int x, y, z;
  1406.    union tex_tile_address addr;
  1407.    const float *out;
  1408.    int c;
  1409.  
  1410.    width = u_minify(texture->width0, level);
  1411.    height = u_minify(texture->height0, level);
  1412.    depth = u_minify(texture->depth0, level);
  1413.  
  1414.    assert(width > 0);
  1415.    assert(height > 0);
  1416.    assert(depth > 0);
  1417.  
  1418.    sp_samp->nearest_texcoord_s(s, width,  &x);
  1419.    sp_samp->nearest_texcoord_t(t, height, &y);
  1420.    sp_samp->nearest_texcoord_p(p, depth,  &z);
  1421.  
  1422.    addr.value = 0;
  1423.    addr.bits.level = level;
  1424.  
  1425.    out = get_texel_3d(sp_sview, sp_samp, addr, x, y, z);
  1426.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1427.       rgba[TGSI_NUM_CHANNELS*c] = out[c];
  1428. }
  1429.  
  1430.  
  1431. static void
  1432. img_filter_1d_linear(struct sp_sampler_view *sp_sview,
  1433.                      struct sp_sampler *sp_samp,
  1434.                      float s,
  1435.                      float t,
  1436.                      float p,
  1437.                      unsigned level,
  1438.                      unsigned face_id,
  1439.                      float *rgba)
  1440. {
  1441.    const struct pipe_resource *texture = sp_sview->base.texture;
  1442.    int width;
  1443.    int x0, x1;
  1444.    float xw; /* weights */
  1445.    union tex_tile_address addr;
  1446.    const float *tx0, *tx1;
  1447.    int c;
  1448.  
  1449.    width = u_minify(texture->width0, level);
  1450.  
  1451.    assert(width > 0);
  1452.  
  1453.    addr.value = 0;
  1454.    addr.bits.level = level;
  1455.  
  1456.    sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
  1457.  
  1458.    tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, 0);
  1459.    tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, 0);
  1460.  
  1461.    /* interpolate R, G, B, A */
  1462.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1463.       rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
  1464. }
  1465.  
  1466.  
  1467. static void
  1468. img_filter_1d_array_linear(struct sp_sampler_view *sp_sview,
  1469.                            struct sp_sampler *sp_samp,
  1470.                            float s,
  1471.                            float t,
  1472.                            float p,
  1473.                            unsigned level,
  1474.                            unsigned face_id,
  1475.                            float *rgba)
  1476. {
  1477.    const struct pipe_resource *texture = sp_sview->base.texture;
  1478.    int width;
  1479.    int x0, x1, layer;
  1480.    float xw; /* weights */
  1481.    union tex_tile_address addr;
  1482.    const float *tx0, *tx1;
  1483.    int c;
  1484.  
  1485.    width = u_minify(texture->width0, level);
  1486.  
  1487.    assert(width > 0);
  1488.  
  1489.    addr.value = 0;
  1490.    addr.bits.level = level;
  1491.  
  1492.    sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
  1493.    layer = coord_to_layer(t, sp_sview->base.u.tex.first_layer,
  1494.                           sp_sview->base.u.tex.last_layer);
  1495.  
  1496.    tx0 = get_texel_1d_array(sp_sview, sp_samp, addr, x0, layer);
  1497.    tx1 = get_texel_1d_array(sp_sview, sp_samp, addr, x1, layer);
  1498.  
  1499.    /* interpolate R, G, B, A */
  1500.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1501.       rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
  1502. }
  1503.  
  1504.  
  1505. static void
  1506. img_filter_2d_linear(struct sp_sampler_view *sp_sview,
  1507.                      struct sp_sampler *sp_samp,
  1508.                      float s,
  1509.                      float t,
  1510.                      float p,
  1511.                      unsigned level,
  1512.                      unsigned face_id,
  1513.                      float *rgba)
  1514. {
  1515.    const struct pipe_resource *texture = sp_sview->base.texture;
  1516.    int width, height;
  1517.    int x0, y0, x1, y1;
  1518.    float xw, yw; /* weights */
  1519.    union tex_tile_address addr;
  1520.    const float *tx0, *tx1, *tx2, *tx3;
  1521.    int c;
  1522.  
  1523.    width = u_minify(texture->width0, level);
  1524.    height = u_minify(texture->height0, level);
  1525.  
  1526.    assert(width > 0);
  1527.    assert(height > 0);
  1528.  
  1529.    addr.value = 0;
  1530.    addr.bits.level = level;
  1531.  
  1532.    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1533.    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1534.  
  1535.    tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, y0);
  1536.    tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, y0);
  1537.    tx2 = get_texel_2d(sp_sview, sp_samp, addr, x0, y1);
  1538.    tx3 = get_texel_2d(sp_sview, sp_samp, addr, x1, y1);
  1539.  
  1540.    /* interpolate R, G, B, A */
  1541.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1542.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  1543.                                           tx0[c], tx1[c],
  1544.                                           tx2[c], tx3[c]);
  1545. }
  1546.  
  1547.  
  1548. static void
  1549. img_filter_2d_array_linear(struct sp_sampler_view *sp_sview,
  1550.                            struct sp_sampler *sp_samp,
  1551.                            float s,
  1552.                            float t,
  1553.                            float p,
  1554.                            unsigned level,
  1555.                            unsigned face_id,
  1556.                            float *rgba)
  1557. {
  1558.    const struct pipe_resource *texture = sp_sview->base.texture;
  1559.    int width, height;
  1560.    int x0, y0, x1, y1, layer;
  1561.    float xw, yw; /* weights */
  1562.    union tex_tile_address addr;
  1563.    const float *tx0, *tx1, *tx2, *tx3;
  1564.    int c;
  1565.  
  1566.    width = u_minify(texture->width0, level);
  1567.    height = u_minify(texture->height0, level);
  1568.  
  1569.    assert(width > 0);
  1570.    assert(height > 0);
  1571.  
  1572.    addr.value = 0;
  1573.    addr.bits.level = level;
  1574.  
  1575.    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1576.    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1577.    layer = coord_to_layer(p, sp_sview->base.u.tex.first_layer,
  1578.                           sp_sview->base.u.tex.last_layer);
  1579.  
  1580.    tx0 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y0, layer);
  1581.    tx1 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y0, layer);
  1582.    tx2 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y1, layer);
  1583.    tx3 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y1, layer);
  1584.  
  1585.    /* interpolate R, G, B, A */
  1586.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1587.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  1588.                                           tx0[c], tx1[c],
  1589.                                           tx2[c], tx3[c]);
  1590. }
  1591.  
  1592.  
  1593. static void
  1594. img_filter_cube_linear(struct sp_sampler_view *sp_sview,
  1595.                        struct sp_sampler *sp_samp,
  1596.                        float s,
  1597.                        float t,
  1598.                        float p,
  1599.                        unsigned level,
  1600.                        unsigned face_id,
  1601.                        float *rgba)
  1602. {
  1603.    const struct pipe_resource *texture = sp_sview->base.texture;
  1604.    int width, height;
  1605.    int x0, y0, x1, y1, layer;
  1606.    float xw, yw; /* weights */
  1607.    union tex_tile_address addr;
  1608.    const float *tx0, *tx1, *tx2, *tx3;
  1609.    float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE],
  1610.          corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
  1611.    int c;
  1612.  
  1613.    width = u_minify(texture->width0, level);
  1614.    height = u_minify(texture->height0, level);
  1615.  
  1616.    assert(width > 0);
  1617.    assert(height > 0);
  1618.  
  1619.    addr.value = 0;
  1620.    addr.bits.level = level;
  1621.  
  1622.    /*
  1623.     * For seamless if LINEAR filtering is done within a miplevel,
  1624.     * always apply wrap mode CLAMP_TO_BORDER.
  1625.     */
  1626.    if (sp_samp->base.seamless_cube_map) {
  1627.       /* Note this is a bit overkill, actual clamping is not required */
  1628.       wrap_linear_clamp_to_border(s, width, &x0, &x1, &xw);
  1629.       wrap_linear_clamp_to_border(t, height, &y0, &y1, &yw);
  1630.    } else {
  1631.       /* Would probably make sense to ignore mode and just do edge clamp */
  1632.       sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1633.       sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1634.    }
  1635.  
  1636.    layer = sp_sview->base.u.tex.first_layer;
  1637.  
  1638.    if (sp_samp->base.seamless_cube_map) {
  1639.       tx0 = get_texel_cube_seamless(sp_sview, addr, x0, y0, corner0, layer, face_id);
  1640.       tx1 = get_texel_cube_seamless(sp_sview, addr, x1, y0, corner1, layer, face_id);
  1641.       tx2 = get_texel_cube_seamless(sp_sview, addr, x0, y1, corner2, layer, face_id);
  1642.       tx3 = get_texel_cube_seamless(sp_sview, addr, x1, y1, corner3, layer, face_id);
  1643.    } else {
  1644.       tx0 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer + face_id);
  1645.       tx1 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer + face_id);
  1646.       tx2 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer + face_id);
  1647.       tx3 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer + face_id);
  1648.    }
  1649.  
  1650.    /* interpolate R, G, B, A */
  1651.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1652.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  1653.                                           tx0[c], tx1[c],
  1654.                                           tx2[c], tx3[c]);
  1655. }
  1656.  
  1657.  
  1658. static void
  1659. img_filter_cube_array_linear(struct sp_sampler_view *sp_sview,
  1660.                              struct sp_sampler *sp_samp,
  1661.                              float s,
  1662.                              float t,
  1663.                              float p,
  1664.                              unsigned level,
  1665.                              unsigned face_id,
  1666.                              float *rgba)
  1667. {
  1668.    const struct pipe_resource *texture = sp_sview->base.texture;
  1669.    int width, height;
  1670.    int x0, y0, x1, y1, layer;
  1671.    float xw, yw; /* weights */
  1672.    union tex_tile_address addr;
  1673.    const float *tx0, *tx1, *tx2, *tx3;
  1674.    float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE],
  1675.          corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
  1676.    int c;
  1677.  
  1678.    width = u_minify(texture->width0, level);
  1679.    height = u_minify(texture->height0, level);
  1680.  
  1681.    assert(width > 0);
  1682.    assert(height > 0);
  1683.  
  1684.    addr.value = 0;
  1685.    addr.bits.level = level;
  1686.  
  1687.    /*
  1688.     * For seamless if LINEAR filtering is done within a miplevel,
  1689.     * always apply wrap mode CLAMP_TO_BORDER.
  1690.     */
  1691.    if (sp_samp->base.seamless_cube_map) {
  1692.       /* Note this is a bit overkill, actual clamping is not required */
  1693.       wrap_linear_clamp_to_border(s, width, &x0, &x1, &xw);
  1694.       wrap_linear_clamp_to_border(t, height, &y0, &y1, &yw);
  1695.    } else {
  1696.       /* Would probably make sense to ignore mode and just do edge clamp */
  1697.       sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1698.       sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1699.    }
  1700.  
  1701.    layer = coord_to_layer(6 * p + sp_sview->base.u.tex.first_layer,
  1702.                           sp_sview->base.u.tex.first_layer,
  1703.                           sp_sview->base.u.tex.last_layer - 5);
  1704.  
  1705.    if (sp_samp->base.seamless_cube_map) {
  1706.       tx0 = get_texel_cube_seamless(sp_sview, addr, x0, y0, corner0, layer, face_id);
  1707.       tx1 = get_texel_cube_seamless(sp_sview, addr, x1, y0, corner1, layer, face_id);
  1708.       tx2 = get_texel_cube_seamless(sp_sview, addr, x0, y1, corner2, layer, face_id);
  1709.       tx3 = get_texel_cube_seamless(sp_sview, addr, x1, y1, corner3, layer, face_id);
  1710.    } else {
  1711.       tx0 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer + face_id);
  1712.       tx1 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer + face_id);
  1713.       tx2 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer + face_id);
  1714.       tx3 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer + face_id);
  1715.    }
  1716.  
  1717.    /* interpolate R, G, B, A */
  1718.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1719.       rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
  1720.                                           tx0[c], tx1[c],
  1721.                                           tx2[c], tx3[c]);
  1722. }
  1723.  
  1724. static void
  1725. img_filter_3d_linear(struct sp_sampler_view *sp_sview,
  1726.                      struct sp_sampler *sp_samp,
  1727.                      float s,
  1728.                      float t,
  1729.                      float p,
  1730.                      unsigned level,
  1731.                      unsigned face_id,
  1732.                      float *rgba)
  1733. {
  1734.    const struct pipe_resource *texture = sp_sview->base.texture;
  1735.    int width, height, depth;
  1736.    int x0, x1, y0, y1, z0, z1;
  1737.    float xw, yw, zw; /* interpolation weights */
  1738.    union tex_tile_address addr;
  1739.    const float *tx00, *tx01, *tx02, *tx03, *tx10, *tx11, *tx12, *tx13;
  1740.    int c;
  1741.  
  1742.    width = u_minify(texture->width0, level);
  1743.    height = u_minify(texture->height0, level);
  1744.    depth = u_minify(texture->depth0, level);
  1745.  
  1746.    addr.value = 0;
  1747.    addr.bits.level = level;
  1748.  
  1749.    assert(width > 0);
  1750.    assert(height > 0);
  1751.    assert(depth > 0);
  1752.  
  1753.    sp_samp->linear_texcoord_s(s, width,  &x0, &x1, &xw);
  1754.    sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
  1755.    sp_samp->linear_texcoord_p(p, depth,  &z0, &z1, &zw);
  1756.  
  1757.  
  1758.    tx00 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z0);
  1759.    tx01 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z0);
  1760.    tx02 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z0);
  1761.    tx03 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z0);
  1762.      
  1763.    tx10 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z1);
  1764.    tx11 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z1);
  1765.    tx12 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z1);
  1766.    tx13 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z1);
  1767.      
  1768.       /* interpolate R, G, B, A */
  1769.    for (c = 0; c < TGSI_QUAD_SIZE; c++)
  1770.       rgba[TGSI_NUM_CHANNELS*c] =  lerp_3d(xw, yw, zw,
  1771.                                            tx00[c], tx01[c],
  1772.                                            tx02[c], tx03[c],
  1773.                                            tx10[c], tx11[c],
  1774.                                            tx12[c], tx13[c]);
  1775. }
  1776.  
  1777.  
  1778. /* Calculate level of detail for every fragment,
  1779.  * with lambda already computed.
  1780.  * Note that lambda has already been biased by global LOD bias.
  1781.  * \param biased_lambda per-quad lambda.
  1782.  * \param lod_in per-fragment lod_bias or explicit_lod.
  1783.  * \param lod returns the per-fragment lod.
  1784.  */
  1785. static INLINE void
  1786. compute_lod(const struct pipe_sampler_state *sampler,
  1787.             enum tgsi_sampler_control control,
  1788.             const float biased_lambda,
  1789.             const float lod_in[TGSI_QUAD_SIZE],
  1790.             float lod[TGSI_QUAD_SIZE])
  1791. {
  1792.    float min_lod = sampler->min_lod;
  1793.    float max_lod = sampler->max_lod;
  1794.    uint i;
  1795.  
  1796.    switch (control) {
  1797.    case tgsi_sampler_lod_none:
  1798.    case tgsi_sampler_lod_zero:
  1799.    /* XXX FIXME */
  1800.    case tgsi_sampler_derivs_explicit:
  1801.       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(biased_lambda, min_lod, max_lod);
  1802.       break;
  1803.    case tgsi_sampler_lod_bias:
  1804.       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  1805.          lod[i] = biased_lambda + lod_in[i];
  1806.          lod[i] = CLAMP(lod[i], min_lod, max_lod);
  1807.       }
  1808.       break;
  1809.    case tgsi_sampler_lod_explicit:
  1810.       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  1811.          lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
  1812.       }
  1813.       break;
  1814.    default:
  1815.       assert(0);
  1816.       lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
  1817.    }
  1818. }
  1819.  
  1820.  
  1821. /* Calculate level of detail for every fragment.
  1822.  * \param lod_in per-fragment lod_bias or explicit_lod.
  1823.  * \param lod results per-fragment lod.
  1824.  */
  1825. static INLINE void
  1826. compute_lambda_lod(struct sp_sampler_view *sp_sview,
  1827.                    struct sp_sampler *sp_samp,
  1828.                    const float s[TGSI_QUAD_SIZE],
  1829.                    const float t[TGSI_QUAD_SIZE],
  1830.                    const float p[TGSI_QUAD_SIZE],
  1831.                    const float lod_in[TGSI_QUAD_SIZE],
  1832.                    enum tgsi_sampler_control control,
  1833.                    float lod[TGSI_QUAD_SIZE])
  1834. {
  1835.    const struct pipe_sampler_state *sampler = &sp_samp->base;
  1836.    float lod_bias = sampler->lod_bias;
  1837.    float min_lod = sampler->min_lod;
  1838.    float max_lod = sampler->max_lod;
  1839.    float lambda;
  1840.    uint i;
  1841.  
  1842.    switch (control) {
  1843.    case tgsi_sampler_lod_none:
  1844.       /* XXX FIXME */
  1845.    case tgsi_sampler_derivs_explicit:
  1846.       lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
  1847.       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lambda, min_lod, max_lod);
  1848.       break;
  1849.    case tgsi_sampler_lod_bias:
  1850.       lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
  1851.       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  1852.          lod[i] = lambda + lod_in[i];
  1853.          lod[i] = CLAMP(lod[i], min_lod, max_lod);
  1854.       }
  1855.       break;
  1856.    case tgsi_sampler_lod_explicit:
  1857.       for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  1858.          lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
  1859.       }
  1860.       break;
  1861.    case tgsi_sampler_lod_zero:
  1862.       /* this is all static state in the sampler really need clamp here? */
  1863.       lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lod_bias, min_lod, max_lod);
  1864.       break;
  1865.    default:
  1866.       assert(0);
  1867.       lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
  1868.    }
  1869. }
  1870.  
  1871.  
  1872. static void
  1873. mip_filter_linear(struct sp_sampler_view *sp_sview,
  1874.                   struct sp_sampler *sp_samp,
  1875.                   img_filter_func min_filter,
  1876.                   img_filter_func mag_filter,
  1877.                   const float s[TGSI_QUAD_SIZE],
  1878.                   const float t[TGSI_QUAD_SIZE],
  1879.                   const float p[TGSI_QUAD_SIZE],
  1880.                   const float c0[TGSI_QUAD_SIZE],
  1881.                   const float lod_in[TGSI_QUAD_SIZE],
  1882.                   enum tgsi_sampler_control control,
  1883.                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  1884. {
  1885.    const struct pipe_sampler_view *psview = &sp_sview->base;
  1886.    int j;
  1887.    float lod[TGSI_QUAD_SIZE];
  1888.  
  1889.    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
  1890.  
  1891.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  1892.       int level0 = psview->u.tex.first_level + (int)lod[j];
  1893.  
  1894.       if (lod[j] < 0.0)
  1895.          mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1896.                     psview->u.tex.first_level,
  1897.                     sp_sview->faces[j], &rgba[0][j]);
  1898.  
  1899.       else if (level0 >= (int) psview->u.tex.last_level)
  1900.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], psview->u.tex.last_level,
  1901.                     sp_sview->faces[j], &rgba[0][j]);
  1902.  
  1903.       else {
  1904.          float levelBlend = frac(lod[j]);
  1905.          float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  1906.          int c;
  1907.  
  1908.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0,
  1909.                     sp_sview->faces[j], &rgbax[0][0]);
  1910.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
  1911.                     sp_sview->faces[j], &rgbax[0][1]);
  1912.  
  1913.          for (c = 0; c < 4; c++) {
  1914.             rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
  1915.          }
  1916.       }
  1917.    }
  1918.  
  1919.    if (DEBUG_TEX) {
  1920.       print_sample_4(__FUNCTION__, rgba);
  1921.    }
  1922. }
  1923.  
  1924.  
  1925. /**
  1926.  * Compute nearest mipmap level from texcoords.
  1927.  * Then sample the texture level for four elements of a quad.
  1928.  * \param c0  the LOD bias factors, or absolute LODs (depending on control)
  1929.  */
  1930. static void
  1931. mip_filter_nearest(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.                    const float c0[TGSI_QUAD_SIZE],
  1939.                    const float lod_in[TGSI_QUAD_SIZE],
  1940.                    enum tgsi_sampler_control control,
  1941.                    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  1942. {
  1943.    const struct pipe_sampler_view *psview = &sp_sview->base;
  1944.    float lod[TGSI_QUAD_SIZE];
  1945.    int j;
  1946.  
  1947.    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
  1948.  
  1949.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  1950.       if (lod[j] < 0.0)
  1951.          mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1952.                     psview->u.tex.first_level,
  1953.                     sp_sview->faces[j], &rgba[0][j]);
  1954.       else {
  1955.          int level = psview->u.tex.first_level + (int)(lod[j] + 0.5F);
  1956.          level = MIN2(level, (int)psview->u.tex.last_level);
  1957.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1958.                     level, sp_sview->faces[j], &rgba[0][j]);
  1959.       }
  1960.    }
  1961.  
  1962.    if (DEBUG_TEX) {
  1963.       print_sample_4(__FUNCTION__, rgba);
  1964.    }
  1965. }
  1966.  
  1967.  
  1968. static void
  1969. mip_filter_none(struct sp_sampler_view *sp_sview,
  1970.                 struct sp_sampler *sp_samp,
  1971.                 img_filter_func min_filter,
  1972.                 img_filter_func mag_filter,
  1973.                 const float s[TGSI_QUAD_SIZE],
  1974.                 const float t[TGSI_QUAD_SIZE],
  1975.                 const float p[TGSI_QUAD_SIZE],
  1976.                 const float c0[TGSI_QUAD_SIZE],
  1977.                 const float lod_in[TGSI_QUAD_SIZE],
  1978.                 enum tgsi_sampler_control control,
  1979.                 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  1980. {
  1981.    float lod[TGSI_QUAD_SIZE];
  1982.    int j;
  1983.  
  1984.    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
  1985.  
  1986.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  1987.       if (lod[j] < 0.0) {
  1988.          mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1989.                     sp_sview->base.u.tex.first_level,
  1990.                     sp_sview->faces[j], &rgba[0][j]);
  1991.       }
  1992.       else {
  1993.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  1994.                     sp_sview->base.u.tex.first_level,
  1995.                     sp_sview->faces[j], &rgba[0][j]);
  1996.       }
  1997.    }
  1998. }
  1999.  
  2000.  
  2001. static void
  2002. mip_filter_none_no_filter_select(struct sp_sampler_view *sp_sview,
  2003.                                  struct sp_sampler *sp_samp,
  2004.                                  img_filter_func min_filter,
  2005.                                  img_filter_func mag_filter,
  2006.                                  const float s[TGSI_QUAD_SIZE],
  2007.                                  const float t[TGSI_QUAD_SIZE],
  2008.                                  const float p[TGSI_QUAD_SIZE],
  2009.                                  const float c0[TGSI_QUAD_SIZE],
  2010.                                  const float lod_in[TGSI_QUAD_SIZE],
  2011.                                  enum tgsi_sampler_control control,
  2012.                                  float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2013. {
  2014.    int j;
  2015.  
  2016.    for (j = 0; j < TGSI_QUAD_SIZE; j++)
  2017.       mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
  2018.                  sp_sview->base.u.tex.first_level,
  2019.                  sp_sview->faces[j], &rgba[0][j]);
  2020. }
  2021.  
  2022.  
  2023. /* For anisotropic filtering */
  2024. #define WEIGHT_LUT_SIZE 1024
  2025.  
  2026. static float *weightLut = NULL;
  2027.  
  2028. /**
  2029.  * Creates the look-up table used to speed-up EWA sampling
  2030.  */
  2031. static void
  2032. create_filter_table(void)
  2033. {
  2034.    unsigned i;
  2035.    if (!weightLut) {
  2036.       weightLut = (float *) MALLOC(WEIGHT_LUT_SIZE * sizeof(float));
  2037.  
  2038.       for (i = 0; i < WEIGHT_LUT_SIZE; ++i) {
  2039.          float alpha = 2;
  2040.          float r2 = (float) i / (float) (WEIGHT_LUT_SIZE - 1);
  2041.          float weight = (float) exp(-alpha * r2);
  2042.          weightLut[i] = weight;
  2043.       }
  2044.    }
  2045. }
  2046.  
  2047.  
  2048. /**
  2049.  * Elliptical weighted average (EWA) filter for producing high quality
  2050.  * anisotropic filtered results.
  2051.  * Based on the Higher Quality Elliptical Weighted Average Filter
  2052.  * published by Paul S. Heckbert in his Master's Thesis
  2053.  * "Fundamentals of Texture Mapping and Image Warping" (1989)
  2054.  */
  2055. static void
  2056. img_filter_2d_ewa(struct sp_sampler_view *sp_sview,
  2057.                   struct sp_sampler *sp_samp,
  2058.                   img_filter_func min_filter,
  2059.                   img_filter_func mag_filter,
  2060.                   const float s[TGSI_QUAD_SIZE],
  2061.                   const float t[TGSI_QUAD_SIZE],
  2062.                   const float p[TGSI_QUAD_SIZE],
  2063.                   unsigned level,
  2064.                   const float dudx, const float dvdx,
  2065.                   const float dudy, const float dvdy,
  2066.                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2067. {
  2068.    const struct pipe_resource *texture = sp_sview->base.texture;
  2069.  
  2070.    // ??? Won't the image filters blow up if level is negative?
  2071.    unsigned level0 = level > 0 ? level : 0;
  2072.    float scaling = 1.0f / (1 << level0);
  2073.    int width = u_minify(texture->width0, level0);
  2074.    int height = u_minify(texture->height0, level0);
  2075.  
  2076.    float ux = dudx * scaling;
  2077.    float vx = dvdx * scaling;
  2078.    float uy = dudy * scaling;
  2079.    float vy = dvdy * scaling;
  2080.  
  2081.    /* compute ellipse coefficients to bound the region:
  2082.     * A*x*x + B*x*y + C*y*y = F.
  2083.     */
  2084.    float A = vx*vx+vy*vy+1;
  2085.    float B = -2*(ux*vx+uy*vy);
  2086.    float C = ux*ux+uy*uy+1;
  2087.    float F = A*C-B*B/4.0f;
  2088.  
  2089.    /* check if it is an ellipse */
  2090.    /* assert(F > 0.0); */
  2091.  
  2092.    /* Compute the ellipse's (u,v) bounding box in texture space */
  2093.    float d = -B*B+4.0f*C*A;
  2094.    float box_u = 2.0f / d * sqrtf(d*C*F); /* box_u -> half of bbox with   */
  2095.    float box_v = 2.0f / d * sqrtf(A*d*F); /* box_v -> half of bbox height */
  2096.  
  2097.    float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  2098.    float s_buffer[TGSI_QUAD_SIZE];
  2099.    float t_buffer[TGSI_QUAD_SIZE];
  2100.    float weight_buffer[TGSI_QUAD_SIZE];
  2101.    unsigned buffer_next;
  2102.    int j;
  2103.    float den; /* = 0.0F; */
  2104.    float ddq;
  2105.    float U; /* = u0 - tex_u; */
  2106.    int v;
  2107.  
  2108.    /* Scale ellipse formula to directly index the Filter Lookup Table.
  2109.     * i.e. scale so that F = WEIGHT_LUT_SIZE-1
  2110.     */
  2111.    double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F;
  2112.    A *= formScale;
  2113.    B *= formScale;
  2114.    C *= formScale;
  2115.    /* F *= formScale; */ /* no need to scale F as we don't use it below here */
  2116.  
  2117.    /* For each quad, the du and dx values are the same and so the ellipse is
  2118.     * also the same. Note that texel/image access can only be performed using
  2119.     * a quad, i.e. it is not possible to get the pixel value for a single
  2120.     * tex coord. In order to have a better performance, the access is buffered
  2121.     * using the s_buffer/t_buffer and weight_buffer. Only when the buffer is
  2122.     * full, then the pixel values are read from the image.
  2123.     */
  2124.    ddq = 2 * A;
  2125.    
  2126.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2127.       /* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
  2128.        * and incrementally update the value of Ax^2+Bxy*Cy^2; when this
  2129.        * value, q, is less than F, we're inside the ellipse
  2130.        */
  2131.       float tex_u = -0.5F + s[j] * texture->width0 * scaling;
  2132.       float tex_v = -0.5F + t[j] * texture->height0 * scaling;
  2133.  
  2134.       int u0 = (int) floorf(tex_u - box_u);
  2135.       int u1 = (int) ceilf(tex_u + box_u);
  2136.       int v0 = (int) floorf(tex_v - box_v);
  2137.       int v1 = (int) ceilf(tex_v + box_v);
  2138.  
  2139.       float num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
  2140.       buffer_next = 0;
  2141.       den = 0;
  2142.       U = u0 - tex_u;
  2143.       for (v = v0; v <= v1; ++v) {
  2144.          float V = v - tex_v;
  2145.          float dq = A * (2 * U + 1) + B * V;
  2146.          float q = (C * V + B * U) * V + A * U * U;
  2147.  
  2148.          int u;
  2149.          for (u = u0; u <= u1; ++u) {
  2150.             /* Note that the ellipse has been pre-scaled so F =
  2151.              * WEIGHT_LUT_SIZE - 1
  2152.              */
  2153.             if (q < WEIGHT_LUT_SIZE) {
  2154.                /* as a LUT is used, q must never be negative;
  2155.                 * should not happen, though
  2156.                 */
  2157.                const int qClamped = q >= 0.0F ? q : 0;
  2158.                float weight = weightLut[qClamped];
  2159.  
  2160.                weight_buffer[buffer_next] = weight;
  2161.                s_buffer[buffer_next] = u / ((float) width);
  2162.                t_buffer[buffer_next] = v / ((float) height);
  2163.            
  2164.                buffer_next++;
  2165.                if (buffer_next == TGSI_QUAD_SIZE) {
  2166.                   /* 4 texel coords are in the buffer -> read it now */
  2167.                   unsigned jj;
  2168.                   /* it is assumed that samp->min_img_filter is set to
  2169.                    * img_filter_2d_nearest or one of the
  2170.                    * accelerated img_filter_2d_nearest_XXX functions.
  2171.                    */
  2172.                   for (jj = 0; jj < buffer_next; jj++) {
  2173.                      min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
  2174.                                 level, sp_sview->faces[j], &rgba_temp[0][jj]);
  2175.                      num[0] += weight_buffer[jj] * rgba_temp[0][jj];
  2176.                      num[1] += weight_buffer[jj] * rgba_temp[1][jj];
  2177.                      num[2] += weight_buffer[jj] * rgba_temp[2][jj];
  2178.                      num[3] += weight_buffer[jj] * rgba_temp[3][jj];
  2179.                   }
  2180.  
  2181.                   buffer_next = 0;
  2182.                }
  2183.  
  2184.                den += weight;
  2185.             }
  2186.             q += dq;
  2187.             dq += ddq;
  2188.          }
  2189.       }
  2190.  
  2191.       /* if the tex coord buffer contains unread values, we will read
  2192.        * them now.
  2193.        */
  2194.       if (buffer_next > 0) {
  2195.          unsigned jj;
  2196.          /* it is assumed that samp->min_img_filter is set to
  2197.           * img_filter_2d_nearest or one of the
  2198.           * accelerated img_filter_2d_nearest_XXX functions.
  2199.           */
  2200.          for (jj = 0; jj < buffer_next; jj++) {
  2201.             min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
  2202.                        level, sp_sview->faces[j], &rgba_temp[0][jj]);
  2203.             num[0] += weight_buffer[jj] * rgba_temp[0][jj];
  2204.             num[1] += weight_buffer[jj] * rgba_temp[1][jj];
  2205.             num[2] += weight_buffer[jj] * rgba_temp[2][jj];
  2206.             num[3] += weight_buffer[jj] * rgba_temp[3][jj];
  2207.          }
  2208.       }
  2209.  
  2210.       if (den <= 0.0F) {
  2211.          /* Reaching this place would mean that no pixels intersected
  2212.           * the ellipse.  This should never happen because the filter
  2213.           * we use always intersects at least one pixel.
  2214.           */
  2215.  
  2216.          /*rgba[0]=0;
  2217.          rgba[1]=0;
  2218.          rgba[2]=0;
  2219.          rgba[3]=0;*/
  2220.          /* not enough pixels in resampling, resort to direct interpolation */
  2221.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level,
  2222.                     sp_sview->faces[j], &rgba_temp[0][j]);
  2223.          den = 1;
  2224.          num[0] = rgba_temp[0][j];
  2225.          num[1] = rgba_temp[1][j];
  2226.          num[2] = rgba_temp[2][j];
  2227.          num[3] = rgba_temp[3][j];
  2228.       }
  2229.  
  2230.       rgba[0][j] = num[0] / den;
  2231.       rgba[1][j] = num[1] / den;
  2232.       rgba[2][j] = num[2] / den;
  2233.       rgba[3][j] = num[3] / den;
  2234.    }
  2235. }
  2236.  
  2237.  
  2238. /**
  2239.  * Sample 2D texture using an anisotropic filter.
  2240.  */
  2241. static void
  2242. mip_filter_linear_aniso(struct sp_sampler_view *sp_sview,
  2243.                         struct sp_sampler *sp_samp,
  2244.                         img_filter_func min_filter,
  2245.                         img_filter_func mag_filter,
  2246.                         const float s[TGSI_QUAD_SIZE],
  2247.                         const float t[TGSI_QUAD_SIZE],
  2248.                         const float p[TGSI_QUAD_SIZE],
  2249.                         const float c0[TGSI_QUAD_SIZE],
  2250.                         const float lod_in[TGSI_QUAD_SIZE],
  2251.                         enum tgsi_sampler_control control,
  2252.                         float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2253. {
  2254.    const struct pipe_resource *texture = sp_sview->base.texture;
  2255.    const struct pipe_sampler_view *psview = &sp_sview->base;
  2256.    int level0;
  2257.    float lambda;
  2258.    float lod[TGSI_QUAD_SIZE];
  2259.  
  2260.    float s_to_u = u_minify(texture->width0, psview->u.tex.first_level);
  2261.    float t_to_v = u_minify(texture->height0, psview->u.tex.first_level);
  2262.    float dudx = (s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
  2263.    float dudy = (s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT]) * s_to_u;
  2264.    float dvdx = (t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
  2265.    float dvdy = (t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT]) * t_to_v;
  2266.    
  2267.    if (control == tgsi_sampler_lod_bias ||
  2268.        control == tgsi_sampler_lod_none ||
  2269.        /* XXX FIXME */
  2270.        control == tgsi_sampler_derivs_explicit) {
  2271.       /* note: instead of working with Px and Py, we will use the
  2272.        * squared length instead, to avoid sqrt.
  2273.        */
  2274.       float Px2 = dudx * dudx + dvdx * dvdx;
  2275.       float Py2 = dudy * dudy + dvdy * dvdy;
  2276.  
  2277.       float Pmax2;
  2278.       float Pmin2;
  2279.       float e;
  2280.       const float maxEccentricity = sp_samp->base.max_anisotropy * sp_samp->base.max_anisotropy;
  2281.      
  2282.       if (Px2 < Py2) {
  2283.          Pmax2 = Py2;
  2284.          Pmin2 = Px2;
  2285.       }
  2286.       else {
  2287.          Pmax2 = Px2;
  2288.          Pmin2 = Py2;
  2289.       }
  2290.      
  2291.       /* if the eccentricity of the ellipse is too big, scale up the shorter
  2292.        * of the two vectors to limit the maximum amount of work per pixel
  2293.        */
  2294.       e = Pmax2 / Pmin2;
  2295.       if (e > maxEccentricity) {
  2296.          /* float s=e / maxEccentricity;
  2297.             minor[0] *= s;
  2298.             minor[1] *= s;
  2299.             Pmin2 *= s; */
  2300.          Pmin2 = Pmax2 / maxEccentricity;
  2301.       }
  2302.      
  2303.       /* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
  2304.        * this since 0.5*log(x) = log(sqrt(x))
  2305.        */
  2306.       lambda = 0.5F * util_fast_log2(Pmin2) + sp_samp->base.lod_bias;
  2307.       compute_lod(&sp_samp->base, control, lambda, lod_in, lod);
  2308.    }
  2309.    else {
  2310.       assert(control == tgsi_sampler_lod_explicit ||
  2311.              control == tgsi_sampler_lod_zero);
  2312.       compute_lod(&sp_samp->base, control, sp_samp->base.lod_bias, lod_in, lod);
  2313.    }
  2314.    
  2315.    /* XXX: Take into account all lod values.
  2316.     */
  2317.    lambda = lod[0];
  2318.    level0 = psview->u.tex.first_level + (int)lambda;
  2319.  
  2320.    /* If the ellipse covers the whole image, we can
  2321.     * simply return the average of the whole image.
  2322.     */
  2323.    if (level0 >= (int) psview->u.tex.last_level) {
  2324.       int j;
  2325.       for (j = 0; j < TGSI_QUAD_SIZE; j++)
  2326.          min_filter(sp_sview, sp_samp, s[j], t[j], p[j], psview->u.tex.last_level,
  2327.                     sp_sview->faces[j], &rgba[0][j]);
  2328.    }
  2329.    else {
  2330.       /* don't bother interpolating between multiple LODs; it doesn't
  2331.        * seem to be worth the extra running time.
  2332.        */
  2333.       img_filter_2d_ewa(sp_sview, sp_samp, min_filter, mag_filter,
  2334.                         s, t, p, level0,
  2335.                         dudx, dvdx, dudy, dvdy, rgba);
  2336.    }
  2337.  
  2338.    if (DEBUG_TEX) {
  2339.       print_sample_4(__FUNCTION__, rgba);
  2340.    }
  2341. }
  2342.  
  2343.  
  2344. /**
  2345.  * Specialized version of mip_filter_linear with hard-wired calls to
  2346.  * 2d lambda calculation and 2d_linear_repeat_POT img filters.
  2347.  */
  2348. static void
  2349. mip_filter_linear_2d_linear_repeat_POT(
  2350.    struct sp_sampler_view *sp_sview,
  2351.    struct sp_sampler *sp_samp,
  2352.    img_filter_func min_filter,
  2353.    img_filter_func mag_filter,
  2354.    const float s[TGSI_QUAD_SIZE],
  2355.    const float t[TGSI_QUAD_SIZE],
  2356.    const float p[TGSI_QUAD_SIZE],
  2357.    const float c0[TGSI_QUAD_SIZE],
  2358.    const float lod_in[TGSI_QUAD_SIZE],
  2359.    enum tgsi_sampler_control control,
  2360.    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2361. {
  2362.    const struct pipe_sampler_view *psview = &sp_sview->base;
  2363.    int j;
  2364.    float lod[TGSI_QUAD_SIZE];
  2365.  
  2366.    compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
  2367.  
  2368.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2369.       int level0 = psview->u.tex.first_level + (int)lod[j];
  2370.  
  2371.       /* Catches both negative and large values of level0:
  2372.        */
  2373.       if ((unsigned)level0 >= psview->u.tex.last_level) {
  2374.          if (level0 < 0)
  2375.             img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
  2376.                                             psview->u.tex.first_level,
  2377.                                             sp_sview->faces[j], &rgba[0][j]);
  2378.          else
  2379.             img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
  2380.                                             psview->u.tex.last_level,
  2381.                                             sp_sview->faces[j], &rgba[0][j]);
  2382.  
  2383.       }
  2384.       else {
  2385.          float levelBlend = frac(lod[j]);
  2386.          float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  2387.          int c;
  2388.  
  2389.          img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0,
  2390.                                          sp_sview->faces[j], &rgbax[0][0]);
  2391.          img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
  2392.                                          sp_sview->faces[j], &rgbax[0][1]);
  2393.  
  2394.          for (c = 0; c < TGSI_NUM_CHANNELS; c++)
  2395.             rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
  2396.       }
  2397.    }
  2398.  
  2399.    if (DEBUG_TEX) {
  2400.       print_sample_4(__FUNCTION__, rgba);
  2401.    }
  2402. }
  2403.  
  2404.  
  2405. /**
  2406.  * Do shadow/depth comparisons.
  2407.  */
  2408. static void
  2409. sample_compare(struct sp_sampler_view *sp_sview,
  2410.                struct sp_sampler *sp_samp,
  2411.                const float s[TGSI_QUAD_SIZE],
  2412.                const float t[TGSI_QUAD_SIZE],
  2413.                const float p[TGSI_QUAD_SIZE],
  2414.                const float c0[TGSI_QUAD_SIZE],
  2415.                const float c1[TGSI_QUAD_SIZE],
  2416.                enum tgsi_sampler_control control,
  2417.                float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2418. {
  2419.    const struct pipe_sampler_state *sampler = &sp_samp->base;
  2420.    int j;
  2421.    int k[4];
  2422.    float pc[4];
  2423.    const struct util_format_description *format_desc;
  2424.    unsigned chan_type;
  2425.  
  2426.    /**
  2427.     * Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
  2428.     * for 2D Array texture we need to use the 'c0' (aka Q).
  2429.     * When we sampled the depth texture, the depth value was put into all
  2430.     * RGBA channels.  We look at the red channel here.
  2431.     */
  2432.  
  2433.    if (sp_sview->base.target == PIPE_TEXTURE_2D_ARRAY ||
  2434.        sp_sview->base.target == PIPE_TEXTURE_CUBE) {
  2435.       pc[0] = c0[0];
  2436.       pc[1] = c0[1];
  2437.       pc[2] = c0[2];
  2438.       pc[3] = c0[3];
  2439.    } else if (sp_sview->base.target == PIPE_TEXTURE_CUBE_ARRAY) {
  2440.       pc[0] = c1[0];
  2441.       pc[1] = c1[1];
  2442.       pc[2] = c1[2];
  2443.       pc[3] = c1[3];
  2444.    } else {
  2445.       pc[0] = p[0];
  2446.       pc[1] = p[1];
  2447.       pc[2] = p[2];
  2448.       pc[3] = p[3];
  2449.    }
  2450.  
  2451.    format_desc = util_format_description(sp_sview->base.format);
  2452.    /* not entirely sure we couldn't end up with non-valid swizzle here */
  2453.    chan_type = format_desc->swizzle[0] <= UTIL_FORMAT_SWIZZLE_W ?
  2454.                   format_desc->channel[format_desc->swizzle[0]].type :
  2455.                   UTIL_FORMAT_TYPE_FLOAT;
  2456.    if (chan_type != UTIL_FORMAT_TYPE_FLOAT) {
  2457.       /*
  2458.        * clamping is a result of conversion to texture format, hence
  2459.        * doesn't happen with floats. Technically also should do comparison
  2460.        * in texture format (quantization!).
  2461.        */
  2462.       pc[0] = CLAMP(pc[0], 0.0F, 1.0F);
  2463.       pc[1] = CLAMP(pc[1], 0.0F, 1.0F);
  2464.       pc[2] = CLAMP(pc[2], 0.0F, 1.0F);
  2465.       pc[3] = CLAMP(pc[3], 0.0F, 1.0F);
  2466.    }
  2467.  
  2468.    /* compare four texcoords vs. four texture samples */
  2469.    switch (sampler->compare_func) {
  2470.    case PIPE_FUNC_LESS:
  2471.       k[0] = pc[0] < rgba[0][0];
  2472.       k[1] = pc[1] < rgba[0][1];
  2473.       k[2] = pc[2] < rgba[0][2];
  2474.       k[3] = pc[3] < rgba[0][3];
  2475.       break;
  2476.    case PIPE_FUNC_LEQUAL:
  2477.       k[0] = pc[0] <= rgba[0][0];
  2478.       k[1] = pc[1] <= rgba[0][1];
  2479.       k[2] = pc[2] <= rgba[0][2];
  2480.       k[3] = pc[3] <= rgba[0][3];
  2481.       break;
  2482.    case PIPE_FUNC_GREATER:
  2483.       k[0] = pc[0] > rgba[0][0];
  2484.       k[1] = pc[1] > rgba[0][1];
  2485.       k[2] = pc[2] > rgba[0][2];
  2486.       k[3] = pc[3] > rgba[0][3];
  2487.       break;
  2488.    case PIPE_FUNC_GEQUAL:
  2489.       k[0] = pc[0] >= rgba[0][0];
  2490.       k[1] = pc[1] >= rgba[0][1];
  2491.       k[2] = pc[2] >= rgba[0][2];
  2492.       k[3] = pc[3] >= rgba[0][3];
  2493.       break;
  2494.    case PIPE_FUNC_EQUAL:
  2495.       k[0] = pc[0] == rgba[0][0];
  2496.       k[1] = pc[1] == rgba[0][1];
  2497.       k[2] = pc[2] == rgba[0][2];
  2498.       k[3] = pc[3] == rgba[0][3];
  2499.       break;
  2500.    case PIPE_FUNC_NOTEQUAL:
  2501.       k[0] = pc[0] != rgba[0][0];
  2502.       k[1] = pc[1] != rgba[0][1];
  2503.       k[2] = pc[2] != rgba[0][2];
  2504.       k[3] = pc[3] != rgba[0][3];
  2505.       break;
  2506.    case PIPE_FUNC_ALWAYS:
  2507.       k[0] = k[1] = k[2] = k[3] = 1;
  2508.       break;
  2509.    case PIPE_FUNC_NEVER:
  2510.       k[0] = k[1] = k[2] = k[3] = 0;
  2511.       break;
  2512.    default:
  2513.       k[0] = k[1] = k[2] = k[3] = 0;
  2514.       assert(0);
  2515.       break;
  2516.    }
  2517.  
  2518.    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2519.       rgba[0][j] = k[j];
  2520.       rgba[1][j] = k[j];
  2521.       rgba[2][j] = k[j];
  2522.       rgba[3][j] = 1.0F;
  2523.    }
  2524. }
  2525.  
  2526.  
  2527. static void
  2528. do_swizzling(const struct pipe_sampler_view *sview,
  2529.              float in[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
  2530.              float out[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2531. {
  2532.    int j;
  2533.    const unsigned swizzle_r = sview->swizzle_r;
  2534.    const unsigned swizzle_g = sview->swizzle_g;
  2535.    const unsigned swizzle_b = sview->swizzle_b;
  2536.    const unsigned swizzle_a = sview->swizzle_a;
  2537.  
  2538.    switch (swizzle_r) {
  2539.    case PIPE_SWIZZLE_ZERO:
  2540.       for (j = 0; j < 4; j++)
  2541.          out[0][j] = 0.0f;
  2542.       break;
  2543.    case PIPE_SWIZZLE_ONE:
  2544.       for (j = 0; j < 4; j++)
  2545.          out[0][j] = 1.0f;
  2546.       break;
  2547.    default:
  2548.       assert(swizzle_r < 4);
  2549.       for (j = 0; j < 4; j++)
  2550.          out[0][j] = in[swizzle_r][j];
  2551.    }
  2552.  
  2553.    switch (swizzle_g) {
  2554.    case PIPE_SWIZZLE_ZERO:
  2555.       for (j = 0; j < 4; j++)
  2556.          out[1][j] = 0.0f;
  2557.       break;
  2558.    case PIPE_SWIZZLE_ONE:
  2559.       for (j = 0; j < 4; j++)
  2560.          out[1][j] = 1.0f;
  2561.       break;
  2562.    default:
  2563.       assert(swizzle_g < 4);
  2564.       for (j = 0; j < 4; j++)
  2565.          out[1][j] = in[swizzle_g][j];
  2566.    }
  2567.  
  2568.    switch (swizzle_b) {
  2569.    case PIPE_SWIZZLE_ZERO:
  2570.       for (j = 0; j < 4; j++)
  2571.          out[2][j] = 0.0f;
  2572.       break;
  2573.    case PIPE_SWIZZLE_ONE:
  2574.       for (j = 0; j < 4; j++)
  2575.          out[2][j] = 1.0f;
  2576.       break;
  2577.    default:
  2578.       assert(swizzle_b < 4);
  2579.       for (j = 0; j < 4; j++)
  2580.          out[2][j] = in[swizzle_b][j];
  2581.    }
  2582.  
  2583.    switch (swizzle_a) {
  2584.    case PIPE_SWIZZLE_ZERO:
  2585.       for (j = 0; j < 4; j++)
  2586.          out[3][j] = 0.0f;
  2587.       break;
  2588.    case PIPE_SWIZZLE_ONE:
  2589.       for (j = 0; j < 4; j++)
  2590.          out[3][j] = 1.0f;
  2591.       break;
  2592.    default:
  2593.       assert(swizzle_a < 4);
  2594.       for (j = 0; j < 4; j++)
  2595.          out[3][j] = in[swizzle_a][j];
  2596.    }
  2597. }
  2598.  
  2599.  
  2600. static wrap_nearest_func
  2601. get_nearest_unorm_wrap(unsigned mode)
  2602. {
  2603.    switch (mode) {
  2604.    case PIPE_TEX_WRAP_CLAMP:
  2605.       return wrap_nearest_unorm_clamp;
  2606.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  2607.       return wrap_nearest_unorm_clamp_to_edge;
  2608.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  2609.       return wrap_nearest_unorm_clamp_to_border;
  2610.    default:
  2611.       debug_printf("illegal wrap mode %d with non-normalized coords\n", mode);
  2612.       return wrap_nearest_unorm_clamp;
  2613.    }
  2614. }
  2615.  
  2616.  
  2617. static wrap_nearest_func
  2618. get_nearest_wrap(unsigned mode)
  2619. {
  2620.    switch (mode) {
  2621.    case PIPE_TEX_WRAP_REPEAT:
  2622.       return wrap_nearest_repeat;
  2623.    case PIPE_TEX_WRAP_CLAMP:
  2624.       return wrap_nearest_clamp;
  2625.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  2626.       return wrap_nearest_clamp_to_edge;
  2627.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  2628.       return wrap_nearest_clamp_to_border;
  2629.    case PIPE_TEX_WRAP_MIRROR_REPEAT:
  2630.       return wrap_nearest_mirror_repeat;
  2631.    case PIPE_TEX_WRAP_MIRROR_CLAMP:
  2632.       return wrap_nearest_mirror_clamp;
  2633.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
  2634.       return wrap_nearest_mirror_clamp_to_edge;
  2635.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
  2636.       return wrap_nearest_mirror_clamp_to_border;
  2637.    default:
  2638.       assert(0);
  2639.       return wrap_nearest_repeat;
  2640.    }
  2641. }
  2642.  
  2643.  
  2644. static wrap_linear_func
  2645. get_linear_unorm_wrap(unsigned mode)
  2646. {
  2647.    switch (mode) {
  2648.    case PIPE_TEX_WRAP_CLAMP:
  2649.       return wrap_linear_unorm_clamp;
  2650.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  2651.       return wrap_linear_unorm_clamp_to_edge;
  2652.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  2653.       return wrap_linear_unorm_clamp_to_border;
  2654.    default:
  2655.       debug_printf("illegal wrap mode %d with non-normalized coords\n", mode);
  2656.       return wrap_linear_unorm_clamp;
  2657.    }
  2658. }
  2659.  
  2660.  
  2661. static wrap_linear_func
  2662. get_linear_wrap(unsigned mode)
  2663. {
  2664.    switch (mode) {
  2665.    case PIPE_TEX_WRAP_REPEAT:
  2666.       return wrap_linear_repeat;
  2667.    case PIPE_TEX_WRAP_CLAMP:
  2668.       return wrap_linear_clamp;
  2669.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  2670.       return wrap_linear_clamp_to_edge;
  2671.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  2672.       return wrap_linear_clamp_to_border;
  2673.    case PIPE_TEX_WRAP_MIRROR_REPEAT:
  2674.       return wrap_linear_mirror_repeat;
  2675.    case PIPE_TEX_WRAP_MIRROR_CLAMP:
  2676.       return wrap_linear_mirror_clamp;
  2677.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
  2678.       return wrap_linear_mirror_clamp_to_edge;
  2679.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
  2680.       return wrap_linear_mirror_clamp_to_border;
  2681.    default:
  2682.       assert(0);
  2683.       return wrap_linear_repeat;
  2684.    }
  2685. }
  2686.  
  2687.  
  2688. /**
  2689.  * Is swizzling needed for the given state key?
  2690.  */
  2691. static INLINE bool
  2692. any_swizzle(const struct pipe_sampler_view *view)
  2693. {
  2694.    return (view->swizzle_r != PIPE_SWIZZLE_RED ||
  2695.            view->swizzle_g != PIPE_SWIZZLE_GREEN ||
  2696.            view->swizzle_b != PIPE_SWIZZLE_BLUE ||
  2697.            view->swizzle_a != PIPE_SWIZZLE_ALPHA);
  2698. }
  2699.  
  2700.  
  2701. static img_filter_func
  2702. get_img_filter(const struct sp_sampler_view *sp_sview,
  2703.                const struct pipe_sampler_state *sampler,
  2704.                unsigned filter)
  2705. {
  2706.    switch (sp_sview->base.target) {
  2707.    case PIPE_BUFFER:
  2708.    case PIPE_TEXTURE_1D:
  2709.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2710.          return img_filter_1d_nearest;
  2711.       else
  2712.          return img_filter_1d_linear;
  2713.       break;
  2714.    case PIPE_TEXTURE_1D_ARRAY:
  2715.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2716.          return img_filter_1d_array_nearest;
  2717.       else
  2718.          return img_filter_1d_array_linear;
  2719.       break;
  2720.    case PIPE_TEXTURE_2D:
  2721.    case PIPE_TEXTURE_RECT:
  2722.       /* Try for fast path:
  2723.        */
  2724.       if (sp_sview->pot2d &&
  2725.           sampler->wrap_s == sampler->wrap_t &&
  2726.           sampler->normalized_coords)
  2727.       {
  2728.          switch (sampler->wrap_s) {
  2729.          case PIPE_TEX_WRAP_REPEAT:
  2730.             switch (filter) {
  2731.             case PIPE_TEX_FILTER_NEAREST:
  2732.                return img_filter_2d_nearest_repeat_POT;
  2733.             case PIPE_TEX_FILTER_LINEAR:
  2734.                return img_filter_2d_linear_repeat_POT;
  2735.             default:
  2736.                break;
  2737.             }
  2738.             break;
  2739.          case PIPE_TEX_WRAP_CLAMP:
  2740.             switch (filter) {
  2741.             case PIPE_TEX_FILTER_NEAREST:
  2742.                return img_filter_2d_nearest_clamp_POT;
  2743.             default:
  2744.                break;
  2745.             }
  2746.          }
  2747.       }
  2748.       /* Otherwise use default versions:
  2749.        */
  2750.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2751.          return img_filter_2d_nearest;
  2752.       else
  2753.          return img_filter_2d_linear;
  2754.       break;
  2755.    case PIPE_TEXTURE_2D_ARRAY:
  2756.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2757.          return img_filter_2d_array_nearest;
  2758.       else
  2759.          return img_filter_2d_array_linear;
  2760.       break;
  2761.    case PIPE_TEXTURE_CUBE:
  2762.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2763.          return img_filter_cube_nearest;
  2764.       else
  2765.          return img_filter_cube_linear;
  2766.       break;
  2767.    case PIPE_TEXTURE_CUBE_ARRAY:
  2768.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2769.          return img_filter_cube_array_nearest;
  2770.       else
  2771.          return img_filter_cube_array_linear;
  2772.       break;
  2773.    case PIPE_TEXTURE_3D:
  2774.       if (filter == PIPE_TEX_FILTER_NEAREST)
  2775.          return img_filter_3d_nearest;
  2776.       else
  2777.          return img_filter_3d_linear;
  2778.       break;
  2779.    default:
  2780.       assert(0);
  2781.       return img_filter_1d_nearest;
  2782.    }
  2783. }
  2784.  
  2785.  
  2786. static void
  2787. sample_mip(struct sp_sampler_view *sp_sview,
  2788.            struct sp_sampler *sp_samp,
  2789.            const float s[TGSI_QUAD_SIZE],
  2790.            const float t[TGSI_QUAD_SIZE],
  2791.            const float p[TGSI_QUAD_SIZE],
  2792.            const float c0[TGSI_QUAD_SIZE],
  2793.            const float lod[TGSI_QUAD_SIZE],
  2794.            enum tgsi_sampler_control control,
  2795.            float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2796. {
  2797.    mip_filter_func mip_filter;
  2798.    img_filter_func min_img_filter = NULL;
  2799.    img_filter_func mag_img_filter = NULL;
  2800.  
  2801.    if (sp_sview->pot2d & sp_samp->min_mag_equal_repeat_linear) {
  2802.       mip_filter = mip_filter_linear_2d_linear_repeat_POT;
  2803.    }
  2804.    else {
  2805.       mip_filter = sp_samp->mip_filter;
  2806.       min_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->min_img_filter);
  2807.       if (sp_samp->min_mag_equal) {
  2808.          mag_img_filter = min_img_filter;
  2809.       }
  2810.       else {
  2811.          mag_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->base.mag_img_filter);
  2812.       }
  2813.    }
  2814.  
  2815.    mip_filter(sp_sview, sp_samp, min_img_filter, mag_img_filter,
  2816.               s, t, p, c0, lod, control, rgba);
  2817.  
  2818.    if (sp_samp->base.compare_mode != PIPE_TEX_COMPARE_NONE) {
  2819.       sample_compare(sp_sview, sp_samp, s, t, p, c0, lod, control, rgba);
  2820.    }
  2821.  
  2822.    if (sp_sview->need_swizzle) {
  2823.       float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  2824.       memcpy(rgba_temp, rgba, sizeof(rgba_temp));
  2825.       do_swizzling(&sp_sview->base, rgba_temp, rgba);
  2826.    }
  2827.  
  2828. }
  2829.  
  2830.  
  2831. /**
  2832.  * Use 3D texcoords to choose a cube face, then sample the 2D cube faces.
  2833.  * Put face info into the sampler faces[] array.
  2834.  */
  2835. static void
  2836. sample_cube(struct sp_sampler_view *sp_sview,
  2837.             struct sp_sampler *sp_samp,
  2838.             const float s[TGSI_QUAD_SIZE],
  2839.             const float t[TGSI_QUAD_SIZE],
  2840.             const float p[TGSI_QUAD_SIZE],
  2841.             const float c0[TGSI_QUAD_SIZE],
  2842.             const float c1[TGSI_QUAD_SIZE],
  2843.             enum tgsi_sampler_control control,
  2844.             float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2845. {
  2846.    unsigned j;
  2847.    float ssss[4], tttt[4];
  2848.  
  2849.    /* Not actually used, but the intermediate steps that do the
  2850.     * dereferencing don't know it.
  2851.     */
  2852.    static float pppp[4] = { 0, 0, 0, 0 };
  2853.  
  2854.    pppp[0] = c0[0];
  2855.    pppp[1] = c0[1];
  2856.    pppp[2] = c0[2];
  2857.    pppp[3] = c0[3];
  2858.    /*
  2859.      major axis
  2860.      direction    target                             sc     tc    ma
  2861.      ----------   -------------------------------    ---    ---   ---
  2862.      +rx          TEXTURE_CUBE_MAP_POSITIVE_X_EXT    -rz    -ry   rx
  2863.      -rx          TEXTURE_CUBE_MAP_NEGATIVE_X_EXT    +rz    -ry   rx
  2864.      +ry          TEXTURE_CUBE_MAP_POSITIVE_Y_EXT    +rx    +rz   ry
  2865.      -ry          TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT    +rx    -rz   ry
  2866.      +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
  2867.      -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
  2868.    */
  2869.  
  2870.    /* Choose the cube face and compute new s/t coords for the 2D face.
  2871.     *
  2872.     * Use the same cube face for all four pixels in the quad.
  2873.     *
  2874.     * This isn't ideal, but if we want to use a different cube face
  2875.     * per pixel in the quad, we'd have to also compute the per-face
  2876.     * LOD here too.  That's because the four post-face-selection
  2877.     * texcoords are no longer related to each other (they're
  2878.     * per-face!)  so we can't use subtraction to compute the partial
  2879.     * deriviates to compute the LOD.  Doing so (near cube edges
  2880.     * anyway) gives us pretty much random values.
  2881.     */
  2882.    {
  2883.       /* use the average of the four pixel's texcoords to choose the face */
  2884.       const float rx = 0.25F * (s[0] + s[1] + s[2] + s[3]);
  2885.       const float ry = 0.25F * (t[0] + t[1] + t[2] + t[3]);
  2886.       const float rz = 0.25F * (p[0] + p[1] + p[2] + p[3]);
  2887.       const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
  2888.  
  2889.       if (arx >= ary && arx >= arz) {
  2890.          float sign = (rx >= 0.0F) ? 1.0F : -1.0F;
  2891.          uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X;
  2892.          for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2893.             const float ima = -0.5F / fabsf(s[j]);
  2894.             ssss[j] = sign *  p[j] * ima + 0.5F;
  2895.             tttt[j] =         t[j] * ima + 0.5F;
  2896.             sp_sview->faces[j] = face;
  2897.          }
  2898.       }
  2899.       else if (ary >= arx && ary >= arz) {
  2900.          float sign = (ry >= 0.0F) ? 1.0F : -1.0F;
  2901.          uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y;
  2902.          for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2903.             const float ima = -0.5F / fabsf(t[j]);
  2904.             ssss[j] =        -s[j] * ima + 0.5F;
  2905.             tttt[j] = sign * -p[j] * ima + 0.5F;
  2906.             sp_sview->faces[j] = face;
  2907.          }
  2908.       }
  2909.       else {
  2910.          float sign = (rz >= 0.0F) ? 1.0F : -1.0F;
  2911.          uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z;
  2912.          for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  2913.             const float ima = -0.5F / fabsf(p[j]);
  2914.             ssss[j] = sign * -s[j] * ima + 0.5F;
  2915.             tttt[j] =         t[j] * ima + 0.5F;
  2916.             sp_sview->faces[j] = face;
  2917.          }
  2918.       }
  2919.    }
  2920.  
  2921.    sample_mip(sp_sview, sp_samp, ssss, tttt, pppp, c0, c1, control, rgba);
  2922. }
  2923.  
  2924.  
  2925. static void
  2926. sp_get_dims(struct sp_sampler_view *sp_sview, int level,
  2927.             int dims[4])
  2928. {
  2929.    const struct pipe_sampler_view *view = &sp_sview->base;
  2930.    const struct pipe_resource *texture = view->texture;
  2931.  
  2932.    if (view->target == PIPE_BUFFER) {
  2933.       dims[0] = (view->u.buf.last_element - view->u.buf.first_element) + 1;
  2934.       /* the other values are undefined, but let's avoid potential valgrind
  2935.        * warnings.
  2936.        */
  2937.       dims[1] = dims[2] = dims[3] = 0;
  2938.       return;
  2939.    }
  2940.  
  2941.    /* undefined according to EXT_gpu_program */
  2942.    level += view->u.tex.first_level;
  2943.    if (level > view->u.tex.last_level)
  2944.       return;
  2945.  
  2946.    dims[3] = view->u.tex.last_level - view->u.tex.first_level + 1;
  2947.    dims[0] = u_minify(texture->width0, level);
  2948.  
  2949.    switch (view->target) {
  2950.    case PIPE_TEXTURE_1D_ARRAY:
  2951.       dims[1] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
  2952.       /* fallthrough */
  2953.    case PIPE_TEXTURE_1D:
  2954.       return;
  2955.    case PIPE_TEXTURE_2D_ARRAY:
  2956.       dims[2] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
  2957.       /* fallthrough */
  2958.    case PIPE_TEXTURE_2D:
  2959.    case PIPE_TEXTURE_CUBE:
  2960.    case PIPE_TEXTURE_RECT:
  2961.       dims[1] = u_minify(texture->height0, level);
  2962.       return;
  2963.    case PIPE_TEXTURE_3D:
  2964.       dims[1] = u_minify(texture->height0, level);
  2965.       dims[2] = u_minify(texture->depth0, level);
  2966.       return;
  2967.    case PIPE_TEXTURE_CUBE_ARRAY:
  2968.       dims[1] = u_minify(texture->height0, level);
  2969.       dims[2] = (view->u.tex.last_layer - view->u.tex.first_layer + 1) / 6;
  2970.       break;
  2971.    default:
  2972.       assert(!"unexpected texture target in sp_get_dims()");
  2973.       return;
  2974.    }
  2975. }
  2976.  
  2977. /**
  2978.  * This function is only used for getting unfiltered texels via the
  2979.  * TXF opcode.  The GL spec says that out-of-bounds texel fetches
  2980.  * produce undefined results.  Instead of crashing, lets just clamp
  2981.  * coords to the texture image size.
  2982.  */
  2983. static void
  2984. sp_get_texels(struct sp_sampler_view *sp_sview,
  2985.               const int v_i[TGSI_QUAD_SIZE],
  2986.               const int v_j[TGSI_QUAD_SIZE],
  2987.               const int v_k[TGSI_QUAD_SIZE],
  2988.               const int lod[TGSI_QUAD_SIZE],
  2989.               const int8_t offset[3],
  2990.               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  2991. {
  2992.    union tex_tile_address addr;
  2993.    const struct pipe_resource *texture = sp_sview->base.texture;
  2994.    int j, c;
  2995.    const float *tx;
  2996.    int width, height, depth;
  2997.  
  2998.    addr.value = 0;
  2999.    /* TODO write a better test for LOD */
  3000.    addr.bits.level = sp_sview->base.target == PIPE_BUFFER ? 0 :
  3001.                         CLAMP(lod[0] + sp_sview->base.u.tex.first_level,
  3002.                               sp_sview->base.u.tex.first_level,
  3003.                               sp_sview->base.u.tex.last_level);
  3004.  
  3005.    width = u_minify(texture->width0, addr.bits.level);
  3006.    height = u_minify(texture->height0, addr.bits.level);
  3007.    depth = u_minify(texture->depth0, addr.bits.level);
  3008.  
  3009.    switch (sp_sview->base.target) {
  3010.    case PIPE_BUFFER:
  3011.    case PIPE_TEXTURE_1D:
  3012.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  3013.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  3014.          tx = get_texel_2d_no_border(sp_sview, addr, x, 0);
  3015.          for (c = 0; c < 4; c++) {
  3016.             rgba[c][j] = tx[c];
  3017.          }
  3018.       }
  3019.       break;
  3020.    case PIPE_TEXTURE_1D_ARRAY:
  3021.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  3022.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  3023.          int y = CLAMP(v_j[j], sp_sview->base.u.tex.first_layer,
  3024.                        sp_sview->base.u.tex.last_layer);
  3025.          tx = get_texel_2d_no_border(sp_sview, addr, x, y);
  3026.          for (c = 0; c < 4; c++) {
  3027.             rgba[c][j] = tx[c];
  3028.          }
  3029.       }
  3030.       break;
  3031.    case PIPE_TEXTURE_2D:
  3032.    case PIPE_TEXTURE_RECT:
  3033.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  3034.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  3035.          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
  3036.          tx = get_texel_2d_no_border(sp_sview, addr, x, y);
  3037.          for (c = 0; c < 4; c++) {
  3038.             rgba[c][j] = tx[c];
  3039.          }
  3040.       }
  3041.       break;
  3042.    case PIPE_TEXTURE_2D_ARRAY:
  3043.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  3044.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  3045.          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
  3046.          int layer = CLAMP(v_k[j], sp_sview->base.u.tex.first_layer,
  3047.                            sp_sview->base.u.tex.last_layer);
  3048.          tx = get_texel_3d_no_border(sp_sview, addr, x, y, layer);
  3049.          for (c = 0; c < 4; c++) {
  3050.             rgba[c][j] = tx[c];
  3051.          }
  3052.       }
  3053.       break;
  3054.    case PIPE_TEXTURE_3D:
  3055.       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  3056.          int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
  3057.          int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
  3058.          int z = CLAMP(v_k[j] + offset[2], 0, depth - 1);
  3059.          tx = get_texel_3d_no_border(sp_sview, addr, x, y, z);
  3060.          for (c = 0; c < 4; c++) {
  3061.             rgba[c][j] = tx[c];
  3062.          }
  3063.       }
  3064.       break;
  3065.    case PIPE_TEXTURE_CUBE: /* TXF can't work on CUBE according to spec */
  3066.    default:
  3067.       assert(!"Unknown or CUBE texture type in TXF processing\n");
  3068.       break;
  3069.    }
  3070.  
  3071.    if (sp_sview->need_swizzle) {
  3072.       float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
  3073.       memcpy(rgba_temp, rgba, sizeof(rgba_temp));
  3074.       do_swizzling(&sp_sview->base, rgba_temp, rgba);
  3075.    }
  3076. }
  3077.  
  3078.  
  3079. void *
  3080. softpipe_create_sampler_state(struct pipe_context *pipe,
  3081.                               const struct pipe_sampler_state *sampler)
  3082. {
  3083.    struct sp_sampler *samp = CALLOC_STRUCT(sp_sampler);
  3084.  
  3085.    samp->base = *sampler;
  3086.  
  3087.    /* Note that (for instance) linear_texcoord_s and
  3088.     * nearest_texcoord_s may be active at the same time, if the
  3089.     * sampler min_img_filter differs from its mag_img_filter.
  3090.     */
  3091.    if (sampler->normalized_coords) {
  3092.       samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
  3093.       samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
  3094.       samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
  3095.  
  3096.       samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
  3097.       samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
  3098.       samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
  3099.    }
  3100.    else {
  3101.       samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
  3102.       samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
  3103.       samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
  3104.  
  3105.       samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
  3106.       samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
  3107.       samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
  3108.    }
  3109.  
  3110.    samp->min_img_filter = sampler->min_img_filter;
  3111.  
  3112.    switch (sampler->min_mip_filter) {
  3113.    case PIPE_TEX_MIPFILTER_NONE:
  3114.       if (sampler->min_img_filter == sampler->mag_img_filter)
  3115.          samp->mip_filter = mip_filter_none_no_filter_select;
  3116.       else
  3117.          samp->mip_filter = mip_filter_none;
  3118.       break;
  3119.  
  3120.    case PIPE_TEX_MIPFILTER_NEAREST:
  3121.       samp->mip_filter = mip_filter_nearest;
  3122.       break;
  3123.  
  3124.    case PIPE_TEX_MIPFILTER_LINEAR:
  3125.       if (sampler->min_img_filter == sampler->mag_img_filter &&
  3126.           sampler->normalized_coords &&
  3127.           sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
  3128.           sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
  3129.           sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
  3130.           sampler->max_anisotropy <= 1) {
  3131.          samp->min_mag_equal_repeat_linear = TRUE;
  3132.       }
  3133.       samp->mip_filter = mip_filter_linear;
  3134.  
  3135.       /* Anisotropic filtering extension. */
  3136.       if (sampler->max_anisotropy > 1) {
  3137.          samp->mip_filter = mip_filter_linear_aniso;
  3138.  
  3139.          /* Override min_img_filter:
  3140.           * min_img_filter needs to be set to NEAREST since we need to access
  3141.           * each texture pixel as it is and weight it later; using linear
  3142.           * filters will have incorrect results.
  3143.           * By setting the filter to NEAREST here, we can avoid calling the
  3144.           * generic img_filter_2d_nearest in the anisotropic filter function,
  3145.           * making it possible to use one of the accelerated implementations
  3146.           */
  3147.          samp->min_img_filter = PIPE_TEX_FILTER_NEAREST;
  3148.  
  3149.          /* on first access create the lookup table containing the filter weights. */
  3150.         if (!weightLut) {
  3151.            create_filter_table();
  3152.         }
  3153.       }
  3154.       break;
  3155.    }
  3156.    if (samp->min_img_filter == sampler->mag_img_filter) {
  3157.       samp->min_mag_equal = TRUE;
  3158.    }
  3159.  
  3160.    return (void *)samp;
  3161. }
  3162.  
  3163.  
  3164. compute_lambda_func
  3165. softpipe_get_lambda_func(const struct pipe_sampler_view *view, unsigned shader)
  3166. {
  3167.    if (shader != PIPE_SHADER_FRAGMENT)
  3168.       return compute_lambda_vert;
  3169.  
  3170.    switch (view->target) {
  3171.    case PIPE_BUFFER:
  3172.    case PIPE_TEXTURE_1D:
  3173.    case PIPE_TEXTURE_1D_ARRAY:
  3174.       return compute_lambda_1d;
  3175.    case PIPE_TEXTURE_2D:
  3176.    case PIPE_TEXTURE_2D_ARRAY:
  3177.    case PIPE_TEXTURE_RECT:
  3178.    case PIPE_TEXTURE_CUBE:
  3179.    case PIPE_TEXTURE_CUBE_ARRAY:
  3180.       return compute_lambda_2d;
  3181.    case PIPE_TEXTURE_3D:
  3182.       return compute_lambda_3d;
  3183.    default:
  3184.       assert(0);
  3185.       return compute_lambda_1d;
  3186.    }
  3187. }
  3188.  
  3189.  
  3190. struct pipe_sampler_view *
  3191. softpipe_create_sampler_view(struct pipe_context *pipe,
  3192.                              struct pipe_resource *resource,
  3193.                              const struct pipe_sampler_view *templ)
  3194. {
  3195.    struct sp_sampler_view *sview = CALLOC_STRUCT(sp_sampler_view);
  3196.    struct softpipe_resource *spr = (struct softpipe_resource *)resource;
  3197.  
  3198.    if (sview) {
  3199.       struct pipe_sampler_view *view = &sview->base;
  3200.       *view = *templ;
  3201.       view->reference.count = 1;
  3202.       view->texture = NULL;
  3203.       pipe_resource_reference(&view->texture, resource);
  3204.       view->context = pipe;
  3205.  
  3206. #ifdef DEBUG
  3207.      /*
  3208.       * This is possibly too lenient, but the primary reason is just
  3209.       * to catch state trackers which forget to initialize this, so
  3210.       * it only catches clearly impossible view targets.
  3211.       */
  3212.       if (view->target != resource->target) {
  3213.          if (view->target == PIPE_TEXTURE_1D)
  3214.             assert(resource->target == PIPE_TEXTURE_1D_ARRAY);
  3215.          else if (view->target == PIPE_TEXTURE_1D_ARRAY)
  3216.             assert(resource->target == PIPE_TEXTURE_1D);
  3217.          else if (view->target == PIPE_TEXTURE_2D)
  3218.             assert(resource->target == PIPE_TEXTURE_2D_ARRAY ||
  3219.                    resource->target == PIPE_TEXTURE_CUBE ||
  3220.                    resource->target == PIPE_TEXTURE_CUBE_ARRAY);
  3221.          else if (view->target == PIPE_TEXTURE_2D_ARRAY)
  3222.             assert(resource->target == PIPE_TEXTURE_2D ||
  3223.                    resource->target == PIPE_TEXTURE_CUBE ||
  3224.                    resource->target == PIPE_TEXTURE_CUBE_ARRAY);
  3225.          else if (view->target == PIPE_TEXTURE_CUBE)
  3226.             assert(resource->target == PIPE_TEXTURE_CUBE_ARRAY ||
  3227.                    resource->target == PIPE_TEXTURE_2D_ARRAY);
  3228.          else if (view->target == PIPE_TEXTURE_CUBE_ARRAY)
  3229.             assert(resource->target == PIPE_TEXTURE_CUBE ||
  3230.                    resource->target == PIPE_TEXTURE_2D_ARRAY);
  3231.          else
  3232.             assert(0);
  3233.       }
  3234. #endif
  3235.  
  3236.       if (any_swizzle(view)) {
  3237.          sview->need_swizzle = TRUE;
  3238.       }
  3239.  
  3240.       if (view->target == PIPE_TEXTURE_CUBE ||
  3241.           view->target == PIPE_TEXTURE_CUBE_ARRAY)
  3242.          sview->get_samples = sample_cube;
  3243.       else {
  3244.          sview->get_samples = sample_mip;
  3245.       }
  3246.       sview->pot2d = spr->pot &&
  3247.                      (view->target == PIPE_TEXTURE_2D ||
  3248.                       view->target == PIPE_TEXTURE_RECT);
  3249.  
  3250.       sview->xpot = util_logbase2( resource->width0 );
  3251.       sview->ypot = util_logbase2( resource->height0 );
  3252.    }
  3253.  
  3254.    return (struct pipe_sampler_view *) sview;
  3255. }
  3256.  
  3257.  
  3258. static void
  3259. sp_tgsi_get_dims(struct tgsi_sampler *tgsi_sampler,
  3260.                  const unsigned sview_index,
  3261.                  int level, int dims[4])
  3262. {
  3263.    struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
  3264.  
  3265.    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
  3266.    /* always have a view here but texture is NULL if no sampler view was set. */
  3267.    if (!sp_samp->sp_sview[sview_index].base.texture) {
  3268.       dims[0] = dims[1] = dims[2] = dims[3] = 0;
  3269.       return;
  3270.    }
  3271.    sp_get_dims(&sp_samp->sp_sview[sview_index], level, dims);
  3272. }
  3273.  
  3274.  
  3275. static void
  3276. sp_tgsi_get_samples(struct tgsi_sampler *tgsi_sampler,
  3277.                     const unsigned sview_index,
  3278.                     const unsigned sampler_index,
  3279.                     const float s[TGSI_QUAD_SIZE],
  3280.                     const float t[TGSI_QUAD_SIZE],
  3281.                     const float p[TGSI_QUAD_SIZE],
  3282.                     const float c0[TGSI_QUAD_SIZE],
  3283.                     const float lod[TGSI_QUAD_SIZE],
  3284.                     float derivs[3][2][TGSI_QUAD_SIZE],
  3285.                     const int8_t offset[3],
  3286.                     enum tgsi_sampler_control control,
  3287.                     float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  3288. {
  3289.    struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
  3290.  
  3291.    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
  3292.    assert(sampler_index < PIPE_MAX_SAMPLERS);
  3293.    assert(sp_samp->sp_sampler[sampler_index]);
  3294.    /* always have a view here but texture is NULL if no sampler view was set. */
  3295.    if (!sp_samp->sp_sview[sview_index].base.texture) {
  3296.       int i, j;
  3297.       for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
  3298.          for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  3299.             rgba[j][i] = 0.0f;
  3300.          }
  3301.       }
  3302.       return;
  3303.    }
  3304.    sp_samp->sp_sview[sview_index].get_samples(&sp_samp->sp_sview[sview_index],
  3305.                                               sp_samp->sp_sampler[sampler_index],
  3306.                                               s, t, p, c0, lod, control, rgba);
  3307. }
  3308.  
  3309.  
  3310. static void
  3311. sp_tgsi_get_texel(struct tgsi_sampler *tgsi_sampler,
  3312.                   const unsigned sview_index,
  3313.                   const int i[TGSI_QUAD_SIZE],
  3314.                   const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
  3315.                   const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
  3316.                   float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  3317. {
  3318.    struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
  3319.  
  3320.    assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
  3321.    /* always have a view here but texture is NULL if no sampler view was set. */
  3322.    if (!sp_samp->sp_sview[sview_index].base.texture) {
  3323.       int i, j;
  3324.       for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
  3325.          for (i = 0; i < TGSI_QUAD_SIZE; i++) {
  3326.             rgba[j][i] = 0.0f;
  3327.          }
  3328.       }
  3329.       return;
  3330.    }
  3331.    sp_get_texels(&sp_samp->sp_sview[sview_index], i, j, k, lod, offset, rgba);
  3332. }
  3333.  
  3334.  
  3335. struct sp_tgsi_sampler *
  3336. sp_create_tgsi_sampler(void)
  3337. {
  3338.    struct sp_tgsi_sampler *samp = CALLOC_STRUCT(sp_tgsi_sampler);
  3339.    if (!samp)
  3340.       return NULL;
  3341.  
  3342.    samp->base.get_dims = sp_tgsi_get_dims;
  3343.    samp->base.get_samples = sp_tgsi_get_samples;
  3344.    samp->base.get_texel = sp_tgsi_get_texel;
  3345.  
  3346.    return samp;
  3347. }
  3348.  
  3349.