Subversion Repositories Kolibri OS

Rev

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

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2009 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /**
  29.  * @file
  30.  * Texture sampling -- SoA.
  31.  *
  32.  * @author Jose Fonseca <jfonseca@vmware.com>
  33.  * @author Brian Paul <brianp@vmware.com>
  34.  */
  35.  
  36. #include "pipe/p_defines.h"
  37. #include "pipe/p_state.h"
  38. #include "pipe/p_shader_tokens.h"
  39. #include "util/u_debug.h"
  40. #include "util/u_dump.h"
  41. #include "util/u_memory.h"
  42. #include "util/u_math.h"
  43. #include "util/u_format.h"
  44. #include "util/u_cpu_detect.h"
  45. #include "lp_bld_debug.h"
  46. #include "lp_bld_type.h"
  47. #include "lp_bld_const.h"
  48. #include "lp_bld_conv.h"
  49. #include "lp_bld_arit.h"
  50. #include "lp_bld_bitarit.h"
  51. #include "lp_bld_logic.h"
  52. #include "lp_bld_printf.h"
  53. #include "lp_bld_swizzle.h"
  54. #include "lp_bld_flow.h"
  55. #include "lp_bld_gather.h"
  56. #include "lp_bld_format.h"
  57. #include "lp_bld_sample.h"
  58. #include "lp_bld_sample_aos.h"
  59. #include "lp_bld_struct.h"
  60. #include "lp_bld_quad.h"
  61. #include "lp_bld_pack.h"
  62.  
  63.  
  64. /**
  65.  * Generate code to fetch a texel from a texture at int coords (x, y, z).
  66.  * The computation depends on whether the texture is 1D, 2D or 3D.
  67.  * The result, texel, will be float vectors:
  68.  *   texel[0] = red values
  69.  *   texel[1] = green values
  70.  *   texel[2] = blue values
  71.  *   texel[3] = alpha values
  72.  */
  73. static void
  74. lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
  75.                           unsigned sampler_unit,
  76.                           LLVMValueRef width,
  77.                           LLVMValueRef height,
  78.                           LLVMValueRef depth,
  79.                           LLVMValueRef x,
  80.                           LLVMValueRef y,
  81.                           LLVMValueRef z,
  82.                           LLVMValueRef y_stride,
  83.                           LLVMValueRef z_stride,
  84.                           LLVMValueRef data_ptr,
  85.                           LLVMValueRef mipoffsets,
  86.                           LLVMValueRef texel_out[4])
  87. {
  88.    const struct lp_static_sampler_state *static_state = bld->static_sampler_state;
  89.    const unsigned dims = bld->dims;
  90.    struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
  91.    LLVMBuilderRef builder = bld->gallivm->builder;
  92.    LLVMValueRef offset;
  93.    LLVMValueRef i, j;
  94.    LLVMValueRef use_border = NULL;
  95.  
  96.    /* use_border = x < 0 || x >= width || y < 0 || y >= height */
  97.    if (lp_sampler_wrap_mode_uses_border_color(static_state->wrap_s,
  98.                                               static_state->min_img_filter,
  99.                                               static_state->mag_img_filter)) {
  100.       LLVMValueRef b1, b2;
  101.       b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, x, int_coord_bld->zero);
  102.       b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, x, width);
  103.       use_border = LLVMBuildOr(builder, b1, b2, "b1_or_b2");
  104.    }
  105.  
  106.    if (dims >= 2 &&
  107.        lp_sampler_wrap_mode_uses_border_color(static_state->wrap_t,
  108.                                               static_state->min_img_filter,
  109.                                               static_state->mag_img_filter)) {
  110.       LLVMValueRef b1, b2;
  111.       b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, y, int_coord_bld->zero);
  112.       b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, y, height);
  113.       if (use_border) {
  114.          use_border = LLVMBuildOr(builder, use_border, b1, "ub_or_b1");
  115.          use_border = LLVMBuildOr(builder, use_border, b2, "ub_or_b2");
  116.       }
  117.       else {
  118.          use_border = LLVMBuildOr(builder, b1, b2, "b1_or_b2");
  119.       }
  120.    }
  121.  
  122.    if (dims == 3 &&
  123.        lp_sampler_wrap_mode_uses_border_color(static_state->wrap_r,
  124.                                               static_state->min_img_filter,
  125.                                               static_state->mag_img_filter)) {
  126.       LLVMValueRef b1, b2;
  127.       b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, z, int_coord_bld->zero);
  128.       b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, z, depth);
  129.       if (use_border) {
  130.          use_border = LLVMBuildOr(builder, use_border, b1, "ub_or_b1");
  131.          use_border = LLVMBuildOr(builder, use_border, b2, "ub_or_b2");
  132.       }
  133.       else {
  134.          use_border = LLVMBuildOr(builder, b1, b2, "b1_or_b2");
  135.       }
  136.    }
  137.  
  138.    /* convert x,y,z coords to linear offset from start of texture, in bytes */
  139.    lp_build_sample_offset(&bld->int_coord_bld,
  140.                           bld->format_desc,
  141.                           x, y, z, y_stride, z_stride,
  142.                           &offset, &i, &j);
  143.    if (mipoffsets) {
  144.       offset = lp_build_add(&bld->int_coord_bld, offset, mipoffsets);
  145.    }
  146.  
  147.    if (use_border) {
  148.       /* If we can sample the border color, it means that texcoords may
  149.        * lie outside the bounds of the texture image.  We need to do
  150.        * something to prevent reading out of bounds and causing a segfault.
  151.        *
  152.        * Simply AND the texture coords with !use_border.  This will cause
  153.        * coords which are out of bounds to become zero.  Zero's guaranteed
  154.        * to be inside the texture image.
  155.        */
  156.       offset = lp_build_andnot(&bld->int_coord_bld, offset, use_border);
  157.    }
  158.  
  159.    lp_build_fetch_rgba_soa(bld->gallivm,
  160.                            bld->format_desc,
  161.                            bld->texel_type,
  162.                            data_ptr, offset,
  163.                            i, j,
  164.                            texel_out);
  165.  
  166.    /*
  167.     * Note: if we find an app which frequently samples the texture border
  168.     * we might want to implement a true conditional here to avoid sampling
  169.     * the texture whenever possible (since that's quite a bit of code).
  170.     * Ex:
  171.     *   if (use_border) {
  172.     *      texel = border_color;
  173.     *   }
  174.     *   else {
  175.     *      texel = sample_texture(coord);
  176.     *   }
  177.     * As it is now, we always sample the texture, then selectively replace
  178.     * the texel color results with the border color.
  179.     */
  180.  
  181.    if (use_border) {
  182.       /* select texel color or border color depending on use_border */
  183.       LLVMValueRef border_color_ptr =
  184.          bld->dynamic_state->border_color(bld->dynamic_state,
  185.                                           bld->gallivm, sampler_unit);
  186.       int chan;
  187.       for (chan = 0; chan < 4; chan++) {
  188.          LLVMValueRef border_chan =
  189.             lp_build_array_get(bld->gallivm, border_color_ptr,
  190.                                lp_build_const_int32(bld->gallivm, chan));
  191.          LLVMValueRef border_chan_vec =
  192.             lp_build_broadcast_scalar(&bld->float_vec_bld, border_chan);
  193.  
  194.          if (!bld->texel_type.floating) {
  195.             border_chan_vec = LLVMBuildBitCast(builder, border_chan_vec,
  196.                                                bld->texel_bld.vec_type, "");
  197.          }
  198.          texel_out[chan] = lp_build_select(&bld->texel_bld, use_border,
  199.                                            border_chan_vec, texel_out[chan]);
  200.       }
  201.    }
  202. }
  203.  
  204.  
  205. /**
  206.  * Helper to compute the mirror function for the PIPE_WRAP_MIRROR modes.
  207.  */
  208. static LLVMValueRef
  209. lp_build_coord_mirror(struct lp_build_sample_context *bld,
  210.                       LLVMValueRef coord)
  211. {
  212.    struct lp_build_context *coord_bld = &bld->coord_bld;
  213.    struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
  214.    LLVMValueRef fract, flr, isOdd;
  215.  
  216.    lp_build_ifloor_fract(coord_bld, coord, &flr, &fract);
  217.  
  218.    /* isOdd = flr & 1 */
  219.    isOdd = LLVMBuildAnd(bld->gallivm->builder, flr, int_coord_bld->one, "");
  220.  
  221.    /* make coord positive or negative depending on isOdd */
  222.    coord = lp_build_set_sign(coord_bld, fract, isOdd);
  223.  
  224.    /* convert isOdd to float */
  225.    isOdd = lp_build_int_to_float(coord_bld, isOdd);
  226.  
  227.    /* add isOdd to coord */
  228.    coord = lp_build_add(coord_bld, coord, isOdd);
  229.  
  230.    return coord;
  231. }
  232.  
  233.  
  234. /**
  235.  * Helper to compute the first coord and the weight for
  236.  * linear wrap repeat npot textures
  237.  */
  238. void
  239. lp_build_coord_repeat_npot_linear(struct lp_build_sample_context *bld,
  240.                                   LLVMValueRef coord_f,
  241.                                   LLVMValueRef length_i,
  242.                                   LLVMValueRef length_f,
  243.                                   LLVMValueRef *coord0_i,
  244.                                   LLVMValueRef *weight_f)
  245. {
  246.    struct lp_build_context *coord_bld = &bld->coord_bld;
  247.    struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
  248.    LLVMValueRef half = lp_build_const_vec(bld->gallivm, coord_bld->type, 0.5);
  249.    LLVMValueRef length_minus_one = lp_build_sub(int_coord_bld, length_i,
  250.                                                 int_coord_bld->one);
  251.    LLVMValueRef mask;
  252.    /* wrap with normalized floats is just fract */
  253.    coord_f = lp_build_fract(coord_bld, coord_f);
  254.    /* mul by size and subtract 0.5 */
  255.    coord_f = lp_build_mul(coord_bld, coord_f, length_f);
  256.    coord_f = lp_build_sub(coord_bld, coord_f, half);
  257.    /*
  258.     * we avoided the 0.5/length division before the repeat wrap,
  259.     * now need to fix up edge cases with selects
  260.     */
  261.    /* convert to int, compute lerp weight */
  262.    lp_build_ifloor_fract(coord_bld, coord_f, coord0_i, weight_f);
  263.    mask = lp_build_compare(int_coord_bld->gallivm, int_coord_bld->type,
  264.                            PIPE_FUNC_LESS, *coord0_i, int_coord_bld->zero);
  265.    *coord0_i = lp_build_select(int_coord_bld, mask, length_minus_one, *coord0_i);
  266. }
  267.  
  268.  
  269. /**
  270.  * Build LLVM code for texture wrap mode for linear filtering.
  271.  * \param x0_out  returns first integer texcoord
  272.  * \param x1_out  returns second integer texcoord
  273.  * \param weight_out  returns linear interpolation weight
  274.  */
  275. static void
  276. lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
  277.                             LLVMValueRef coord,
  278.                             LLVMValueRef length,
  279.                             LLVMValueRef length_f,
  280.                             LLVMValueRef offset,
  281.                             boolean is_pot,
  282.                             unsigned wrap_mode,
  283.                             LLVMValueRef *x0_out,
  284.                             LLVMValueRef *x1_out,
  285.                             LLVMValueRef *weight_out)
  286. {
  287.    struct lp_build_context *coord_bld = &bld->coord_bld;
  288.    struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
  289.    LLVMBuilderRef builder = bld->gallivm->builder;
  290.    LLVMValueRef half = lp_build_const_vec(bld->gallivm, coord_bld->type, 0.5);
  291.    LLVMValueRef length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one);
  292.    LLVMValueRef coord0, coord1, weight;
  293.  
  294.    switch(wrap_mode) {
  295.    case PIPE_TEX_WRAP_REPEAT:
  296.       if (is_pot) {
  297.          /* mul by size and subtract 0.5 */
  298.          coord = lp_build_mul(coord_bld, coord, length_f);
  299.          coord = lp_build_sub(coord_bld, coord, half);
  300.          if (offset) {
  301.             offset = lp_build_int_to_float(coord_bld, offset);
  302.             coord = lp_build_add(coord_bld, coord, offset);
  303.          }
  304.          /* convert to int, compute lerp weight */
  305.          lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
  306.          coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
  307.          /* repeat wrap */
  308.          coord0 = LLVMBuildAnd(builder, coord0, length_minus_one, "");
  309.          coord1 = LLVMBuildAnd(builder, coord1, length_minus_one, "");
  310.       }
  311.       else {
  312.          LLVMValueRef mask;
  313.          if (offset) {
  314.             offset = lp_build_int_to_float(coord_bld, offset);
  315.             offset = lp_build_div(coord_bld, offset, length_f);
  316.             coord = lp_build_add(coord_bld, coord, offset);
  317.          }
  318.          lp_build_coord_repeat_npot_linear(bld, coord,
  319.                                            length, length_f,
  320.                                            &coord0, &weight);
  321.          mask = lp_build_compare(int_coord_bld->gallivm, int_coord_bld->type,
  322.                                  PIPE_FUNC_NOTEQUAL, coord0, length_minus_one);
  323.          coord1 = LLVMBuildAnd(builder,
  324.                                lp_build_add(int_coord_bld, coord0, int_coord_bld->one),
  325.                                mask, "");
  326.       }
  327.       break;
  328.  
  329.    case PIPE_TEX_WRAP_CLAMP:
  330.       if (bld->static_sampler_state->normalized_coords) {
  331.          /* scale coord to length */
  332.          coord = lp_build_mul(coord_bld, coord, length_f);
  333.       }
  334.       if (offset) {
  335.          offset = lp_build_int_to_float(coord_bld, offset);
  336.          coord = lp_build_add(coord_bld, coord, offset);
  337.       }
  338.  
  339.       /* clamp to [0, length] */
  340.       coord = lp_build_clamp(coord_bld, coord, coord_bld->zero, length_f);
  341.  
  342.       coord = lp_build_sub(coord_bld, coord, half);
  343.  
  344.       /* convert to int, compute lerp weight */
  345.       lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
  346.       coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
  347.       break;
  348.  
  349.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  350.       {
  351.          struct lp_build_context abs_coord_bld = bld->coord_bld;
  352.          abs_coord_bld.type.sign = FALSE;
  353.  
  354.          if (bld->static_sampler_state->normalized_coords) {
  355.             /* mul by tex size */
  356.             coord = lp_build_mul(coord_bld, coord, length_f);
  357.          }
  358.          if (offset) {
  359.             offset = lp_build_int_to_float(coord_bld, offset);
  360.             coord = lp_build_add(coord_bld, coord, offset);
  361.          }
  362.  
  363.          /* clamp to length max */
  364.          coord = lp_build_min(coord_bld, coord, length_f);
  365.          /* subtract 0.5 */
  366.          coord = lp_build_sub(coord_bld, coord, half);
  367.          /* clamp to [0, length - 0.5] */
  368.          coord = lp_build_max(coord_bld, coord, coord_bld->zero);
  369.          /* convert to int, compute lerp weight */
  370.          lp_build_ifloor_fract(&abs_coord_bld, coord, &coord0, &weight);
  371.          coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
  372.          /* coord1 = min(coord1, length-1) */
  373.          coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one);
  374.          break;
  375.       }
  376.  
  377.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  378.       if (bld->static_sampler_state->normalized_coords) {
  379.          /* scale coord to length */
  380.          coord = lp_build_mul(coord_bld, coord, length_f);
  381.       }
  382.       if (offset) {
  383.          offset = lp_build_int_to_float(coord_bld, offset);
  384.          coord = lp_build_add(coord_bld, coord, offset);
  385.       }
  386.       /* was: clamp to [-0.5, length + 0.5], then sub 0.5 */
  387.       /* can skip clamp (though might not work for very large coord values */
  388.       coord = lp_build_sub(coord_bld, coord, half);
  389.       /* convert to int, compute lerp weight */
  390.       lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
  391.       coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
  392.       break;
  393.  
  394.    case PIPE_TEX_WRAP_MIRROR_REPEAT:
  395.       /* compute mirror function */
  396.       coord = lp_build_coord_mirror(bld, coord);
  397.  
  398.       /* scale coord to length */
  399.       coord = lp_build_mul(coord_bld, coord, length_f);
  400.       coord = lp_build_sub(coord_bld, coord, half);
  401.       if (offset) {
  402.          offset = lp_build_int_to_float(coord_bld, offset);
  403.          coord = lp_build_add(coord_bld, coord, offset);
  404.       }
  405.  
  406.       /* convert to int, compute lerp weight */
  407.       lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
  408.       coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
  409.  
  410.       /* coord0 = max(coord0, 0) */
  411.       coord0 = lp_build_max(int_coord_bld, coord0, int_coord_bld->zero);
  412.       /* coord1 = min(coord1, length-1) */
  413.       coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one);
  414.       break;
  415.  
  416.    case PIPE_TEX_WRAP_MIRROR_CLAMP:
  417.       if (bld->static_sampler_state->normalized_coords) {
  418.          /* scale coord to length */
  419.          coord = lp_build_mul(coord_bld, coord, length_f);
  420.       }
  421.       if (offset) {
  422.          offset = lp_build_int_to_float(coord_bld, offset);
  423.          coord = lp_build_add(coord_bld, coord, offset);
  424.       }
  425.       coord = lp_build_abs(coord_bld, coord);
  426.  
  427.       /* clamp to [0, length] */
  428.       coord = lp_build_min(coord_bld, coord, length_f);
  429.  
  430.       coord = lp_build_sub(coord_bld, coord, half);
  431.  
  432.       /* convert to int, compute lerp weight */
  433.       lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
  434.       coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
  435.       break;
  436.  
  437.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
  438.       {
  439.          struct lp_build_context abs_coord_bld = bld->coord_bld;
  440.          abs_coord_bld.type.sign = FALSE;
  441.  
  442.          if (bld->static_sampler_state->normalized_coords) {
  443.             /* scale coord to length */
  444.             coord = lp_build_mul(coord_bld, coord, length_f);
  445.          }
  446.          if (offset) {
  447.             offset = lp_build_int_to_float(coord_bld, offset);
  448.             coord = lp_build_add(coord_bld, coord, offset);
  449.          }
  450.          coord = lp_build_abs(coord_bld, coord);
  451.  
  452.          /* clamp to length max */
  453.          coord = lp_build_min(coord_bld, coord, length_f);
  454.          /* subtract 0.5 */
  455.          coord = lp_build_sub(coord_bld, coord, half);
  456.          /* clamp to [0, length - 0.5] */
  457.          coord = lp_build_max(coord_bld, coord, coord_bld->zero);
  458.  
  459.          /* convert to int, compute lerp weight */
  460.          lp_build_ifloor_fract(&abs_coord_bld, coord, &coord0, &weight);
  461.          coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
  462.          /* coord1 = min(coord1, length-1) */
  463.          coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one);
  464.       }
  465.       break;
  466.  
  467.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
  468.       {
  469.          if (bld->static_sampler_state->normalized_coords) {
  470.             /* scale coord to length */
  471.             coord = lp_build_mul(coord_bld, coord, length_f);
  472.          }
  473.          if (offset) {
  474.             offset = lp_build_int_to_float(coord_bld, offset);
  475.             coord = lp_build_add(coord_bld, coord, offset);
  476.          }
  477.          coord = lp_build_abs(coord_bld, coord);
  478.  
  479.          /* was: clamp to [-0.5, length + 0.5] then sub 0.5 */
  480.          /* skip clamp - always positive, and other side
  481.             only potentially matters for very large coords */
  482.          coord = lp_build_sub(coord_bld, coord, half);
  483.  
  484.          /* convert to int, compute lerp weight */
  485.          lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
  486.          coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
  487.       }
  488.       break;
  489.  
  490.    default:
  491.       assert(0);
  492.       coord0 = NULL;
  493.       coord1 = NULL;
  494.       weight = NULL;
  495.    }
  496.  
  497.    *x0_out = coord0;
  498.    *x1_out = coord1;
  499.    *weight_out = weight;
  500. }
  501.  
  502.  
  503. /**
  504.  * Build LLVM code for texture wrap mode for nearest filtering.
  505.  * \param coord  the incoming texcoord (nominally in [0,1])
  506.  * \param length  the texture size along one dimension, as int vector
  507.  * \param length_f  the texture size along one dimension, as float vector
  508.  * \param offset  texel offset along one dimension (as int vector)
  509.  * \param is_pot  if TRUE, length is a power of two
  510.  * \param wrap_mode  one of PIPE_TEX_WRAP_x
  511.  */
  512. static LLVMValueRef
  513. lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
  514.                              LLVMValueRef coord,
  515.                              LLVMValueRef length,
  516.                              LLVMValueRef length_f,
  517.                              LLVMValueRef offset,
  518.                              boolean is_pot,
  519.                              unsigned wrap_mode)
  520. {
  521.    struct lp_build_context *coord_bld = &bld->coord_bld;
  522.    struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
  523.    LLVMBuilderRef builder = bld->gallivm->builder;
  524.    LLVMValueRef length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one);
  525.    LLVMValueRef icoord;
  526.    
  527.    switch(wrap_mode) {
  528.    case PIPE_TEX_WRAP_REPEAT:
  529.       if (is_pot) {
  530.          coord = lp_build_mul(coord_bld, coord, length_f);
  531.          icoord = lp_build_ifloor(coord_bld, coord);
  532.          if (offset) {
  533.             icoord = lp_build_add(int_coord_bld, icoord, offset);
  534.          }
  535.          icoord = LLVMBuildAnd(builder, icoord, length_minus_one, "");
  536.       }
  537.       else {
  538.           if (offset) {
  539.              offset = lp_build_int_to_float(coord_bld, offset);
  540.              offset = lp_build_div(coord_bld, offset, length_f);
  541.              coord = lp_build_add(coord_bld, coord, offset);
  542.           }
  543.           /* take fraction, unnormalize */
  544.           coord = lp_build_fract_safe(coord_bld, coord);
  545.           coord = lp_build_mul(coord_bld, coord, length_f);
  546.           icoord = lp_build_itrunc(coord_bld, coord);
  547.       }
  548.       break;
  549.  
  550.    case PIPE_TEX_WRAP_CLAMP:
  551.    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
  552.       if (bld->static_sampler_state->normalized_coords) {
  553.          /* scale coord to length */
  554.          coord = lp_build_mul(coord_bld, coord, length_f);
  555.       }
  556.  
  557.       /* floor */
  558.       /* use itrunc instead since we clamp to 0 anyway */
  559.       icoord = lp_build_itrunc(coord_bld, coord);
  560.       if (offset) {
  561.          icoord = lp_build_add(int_coord_bld, icoord, offset);
  562.       }
  563.  
  564.       /* clamp to [0, length - 1]. */
  565.       icoord = lp_build_clamp(int_coord_bld, icoord, int_coord_bld->zero,
  566.                               length_minus_one);
  567.       break;
  568.  
  569.    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
  570.       if (bld->static_sampler_state->normalized_coords) {
  571.          /* scale coord to length */
  572.          coord = lp_build_mul(coord_bld, coord, length_f);
  573.       }
  574.       /* no clamp necessary, border masking will handle this */
  575.       icoord = lp_build_ifloor(coord_bld, coord);
  576.       if (offset) {
  577.          icoord = lp_build_add(int_coord_bld, icoord, offset);
  578.       }
  579.       break;
  580.  
  581.    case PIPE_TEX_WRAP_MIRROR_REPEAT:
  582.       if (offset) {
  583.          offset = lp_build_int_to_float(coord_bld, offset);
  584.          offset = lp_build_div(coord_bld, offset, length_f);
  585.          coord = lp_build_add(coord_bld, coord, offset);
  586.       }
  587.       /* compute mirror function */
  588.       coord = lp_build_coord_mirror(bld, coord);
  589.  
  590.       /* scale coord to length */
  591.       assert(bld->static_sampler_state->normalized_coords);
  592.       coord = lp_build_mul(coord_bld, coord, length_f);
  593.  
  594.       /* itrunc == ifloor here */
  595.       icoord = lp_build_itrunc(coord_bld, coord);
  596.  
  597.       /* clamp to [0, length - 1] */
  598.       icoord = lp_build_min(int_coord_bld, icoord, length_minus_one);
  599.       break;
  600.  
  601.    case PIPE_TEX_WRAP_MIRROR_CLAMP:
  602.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
  603.       if (bld->static_sampler_state->normalized_coords) {
  604.          /* scale coord to length */
  605.          coord = lp_build_mul(coord_bld, coord, length_f);
  606.       }
  607.       if (offset) {
  608.          offset = lp_build_int_to_float(coord_bld, offset);
  609.          coord = lp_build_add(coord_bld, coord, offset);
  610.       }
  611.       coord = lp_build_abs(coord_bld, coord);
  612.  
  613.       /* itrunc == ifloor here */
  614.       icoord = lp_build_itrunc(coord_bld, coord);
  615.  
  616.       /* clamp to [0, length - 1] */
  617.       icoord = lp_build_min(int_coord_bld, icoord, length_minus_one);
  618.       break;
  619.  
  620.    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
  621.       if (bld->static_sampler_state->normalized_coords) {
  622.          /* scale coord to length */
  623.          coord = lp_build_mul(coord_bld, coord, length_f);
  624.       }
  625.       if (offset) {
  626.          offset = lp_build_int_to_float(coord_bld, offset);
  627.          coord = lp_build_add(coord_bld, coord, offset);
  628.       }
  629.       coord = lp_build_abs(coord_bld, coord);
  630.  
  631.       /* itrunc == ifloor here */
  632.       icoord = lp_build_itrunc(coord_bld, coord);
  633.       break;
  634.  
  635.    default:
  636.       assert(0);
  637.       icoord = NULL;
  638.    }
  639.  
  640.    return icoord;
  641. }
  642.  
  643.  
  644. /**
  645.  * Generate code to sample a mipmap level with nearest filtering.
  646.  * If sampling a cube texture, r = cube face in [0,5].
  647.  */
  648. static void
  649. lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
  650.                               unsigned sampler_unit,
  651.                               LLVMValueRef size,
  652.                               LLVMValueRef row_stride_vec,
  653.                               LLVMValueRef img_stride_vec,
  654.                               LLVMValueRef data_ptr,
  655.                               LLVMValueRef mipoffsets,
  656.                               LLVMValueRef s,
  657.                               LLVMValueRef t,
  658.                               LLVMValueRef r,
  659.                               const LLVMValueRef *offsets,
  660.                               LLVMValueRef colors_out[4])
  661. {
  662.    const unsigned dims = bld->dims;
  663.    LLVMValueRef width_vec;
  664.    LLVMValueRef height_vec;
  665.    LLVMValueRef depth_vec;
  666.    LLVMValueRef flt_size;
  667.    LLVMValueRef flt_width_vec;
  668.    LLVMValueRef flt_height_vec;
  669.    LLVMValueRef flt_depth_vec;
  670.    LLVMValueRef x, y = NULL, z = NULL;
  671.  
  672.    lp_build_extract_image_sizes(bld,
  673.                                 &bld->int_size_bld,
  674.                                 bld->int_coord_type,
  675.                                 size,
  676.                                 &width_vec, &height_vec, &depth_vec);
  677.  
  678.    flt_size = lp_build_int_to_float(&bld->float_size_bld, size);
  679.  
  680.    lp_build_extract_image_sizes(bld,
  681.                                 &bld->float_size_bld,
  682.                                 bld->coord_type,
  683.                                 flt_size,
  684.                                 &flt_width_vec, &flt_height_vec, &flt_depth_vec);
  685.  
  686.    /*
  687.     * Compute integer texcoords.
  688.     */
  689.    x = lp_build_sample_wrap_nearest(bld, s, width_vec, flt_width_vec, offsets[0],
  690.                                     bld->static_texture_state->pot_width,
  691.                                     bld->static_sampler_state->wrap_s);
  692.    lp_build_name(x, "tex.x.wrapped");
  693.  
  694.    if (dims >= 2) {
  695.       y = lp_build_sample_wrap_nearest(bld, t, height_vec, flt_height_vec, offsets[1],
  696.                                        bld->static_texture_state->pot_height,
  697.                                        bld->static_sampler_state->wrap_t);
  698.       lp_build_name(y, "tex.y.wrapped");
  699.  
  700.       if (dims == 3) {
  701.          z = lp_build_sample_wrap_nearest(bld, r, depth_vec, flt_depth_vec, offsets[2],
  702.                                           bld->static_texture_state->pot_depth,
  703.                                           bld->static_sampler_state->wrap_r);
  704.          lp_build_name(z, "tex.z.wrapped");
  705.       }
  706.    }
  707.    if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
  708.        bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
  709.        bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
  710.       z = r;
  711.       lp_build_name(z, "tex.z.layer");
  712.    }
  713.  
  714.    /*
  715.     * Get texture colors.
  716.     */
  717.    lp_build_sample_texel_soa(bld, sampler_unit,
  718.                              width_vec, height_vec, depth_vec,
  719.                              x, y, z,
  720.                              row_stride_vec, img_stride_vec,
  721.                              data_ptr, mipoffsets, colors_out);
  722. }
  723.  
  724.  
  725. /**
  726.  * Generate code to sample a mipmap level with linear filtering.
  727.  * If sampling a cube texture, r = cube face in [0,5].
  728.  */
  729. static void
  730. lp_build_sample_image_linear(struct lp_build_sample_context *bld,
  731.                              unsigned sampler_unit,
  732.                              LLVMValueRef size,
  733.                              LLVMValueRef row_stride_vec,
  734.                              LLVMValueRef img_stride_vec,
  735.                              LLVMValueRef data_ptr,
  736.                              LLVMValueRef mipoffsets,
  737.                              LLVMValueRef s,
  738.                              LLVMValueRef t,
  739.                              LLVMValueRef r,
  740.                              const LLVMValueRef *offsets,
  741.                              LLVMValueRef colors_out[4])
  742. {
  743.    const unsigned dims = bld->dims;
  744.    LLVMValueRef width_vec;
  745.    LLVMValueRef height_vec;
  746.    LLVMValueRef depth_vec;
  747.    LLVMValueRef flt_size;
  748.    LLVMValueRef flt_width_vec;
  749.    LLVMValueRef flt_height_vec;
  750.    LLVMValueRef flt_depth_vec;
  751.    LLVMValueRef x0, y0 = NULL, z0 = NULL, x1, y1 = NULL, z1 = NULL;
  752.    LLVMValueRef s_fpart, t_fpart = NULL, r_fpart = NULL;
  753.    LLVMValueRef neighbors[2][2][4];
  754.    int chan;
  755.  
  756.    lp_build_extract_image_sizes(bld,
  757.                                 &bld->int_size_bld,
  758.                                 bld->int_coord_type,
  759.                                 size,
  760.                                 &width_vec, &height_vec, &depth_vec);
  761.  
  762.    flt_size = lp_build_int_to_float(&bld->float_size_bld, size);
  763.  
  764.    lp_build_extract_image_sizes(bld,
  765.                                 &bld->float_size_bld,
  766.                                 bld->coord_type,
  767.                                 flt_size,
  768.                                 &flt_width_vec, &flt_height_vec, &flt_depth_vec);
  769.  
  770.    /*
  771.     * Compute integer texcoords.
  772.     */
  773.    lp_build_sample_wrap_linear(bld, s, width_vec, flt_width_vec, offsets[0],
  774.                                bld->static_texture_state->pot_width,
  775.                                bld->static_sampler_state->wrap_s,
  776.                                &x0, &x1, &s_fpart);
  777.    lp_build_name(x0, "tex.x0.wrapped");
  778.    lp_build_name(x1, "tex.x1.wrapped");
  779.  
  780.    if (dims >= 2) {
  781.       lp_build_sample_wrap_linear(bld, t, height_vec, flt_height_vec, offsets[1],
  782.                                   bld->static_texture_state->pot_height,
  783.                                   bld->static_sampler_state->wrap_t,
  784.                                   &y0, &y1, &t_fpart);
  785.       lp_build_name(y0, "tex.y0.wrapped");
  786.       lp_build_name(y1, "tex.y1.wrapped");
  787.  
  788.       if (dims == 3) {
  789.          lp_build_sample_wrap_linear(bld, r, depth_vec, flt_depth_vec, offsets[2],
  790.                                      bld->static_texture_state->pot_depth,
  791.                                      bld->static_sampler_state->wrap_r,
  792.                                      &z0, &z1, &r_fpart);
  793.          lp_build_name(z0, "tex.z0.wrapped");
  794.          lp_build_name(z1, "tex.z1.wrapped");
  795.       }
  796.    }
  797.    if (bld->static_texture_state->target == PIPE_TEXTURE_CUBE ||
  798.        bld->static_texture_state->target == PIPE_TEXTURE_1D_ARRAY ||
  799.        bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY) {
  800.       z0 = z1 = r;  /* cube face or array layer */
  801.       lp_build_name(z0, "tex.z0.layer");
  802.       lp_build_name(z1, "tex.z1.layer");
  803.    }
  804.  
  805.  
  806.    /*
  807.     * Get texture colors.
  808.     */
  809.    /* get x0/x1 texels */
  810.    lp_build_sample_texel_soa(bld, sampler_unit,
  811.                              width_vec, height_vec, depth_vec,
  812.                              x0, y0, z0,
  813.                              row_stride_vec, img_stride_vec,
  814.                              data_ptr, mipoffsets, neighbors[0][0]);
  815.    lp_build_sample_texel_soa(bld, sampler_unit,
  816.                              width_vec, height_vec, depth_vec,
  817.                              x1, y0, z0,
  818.                              row_stride_vec, img_stride_vec,
  819.                              data_ptr, mipoffsets, neighbors[0][1]);
  820.  
  821.    if (dims == 1) {
  822.       /* Interpolate two samples from 1D image to produce one color */
  823.       for (chan = 0; chan < 4; chan++) {
  824.          colors_out[chan] = lp_build_lerp(&bld->texel_bld, s_fpart,
  825.                                           neighbors[0][0][chan],
  826.                                           neighbors[0][1][chan],
  827.                                           0);
  828.       }
  829.    }
  830.    else {
  831.       /* 2D/3D texture */
  832.       LLVMValueRef colors0[4];
  833.  
  834.       /* get x0/x1 texels at y1 */
  835.       lp_build_sample_texel_soa(bld, sampler_unit,
  836.                                 width_vec, height_vec, depth_vec,
  837.                                 x0, y1, z0,
  838.                                 row_stride_vec, img_stride_vec,
  839.                                 data_ptr, mipoffsets, neighbors[1][0]);
  840.       lp_build_sample_texel_soa(bld, sampler_unit,
  841.                                 width_vec, height_vec, depth_vec,
  842.                                 x1, y1, z0,
  843.                                 row_stride_vec, img_stride_vec,
  844.                                 data_ptr, mipoffsets, neighbors[1][1]);
  845.  
  846.       /* Bilinear interpolate the four samples from the 2D image / 3D slice */
  847.       for (chan = 0; chan < 4; chan++) {
  848.          colors0[chan] = lp_build_lerp_2d(&bld->texel_bld,
  849.                                           s_fpart, t_fpart,
  850.                                           neighbors[0][0][chan],
  851.                                           neighbors[0][1][chan],
  852.                                           neighbors[1][0][chan],
  853.                                           neighbors[1][1][chan],
  854.                                           0);
  855.       }
  856.  
  857.       if (dims == 3) {
  858.          LLVMValueRef neighbors1[2][2][4];
  859.          LLVMValueRef colors1[4];
  860.  
  861.          /* get x0/x1/y0/y1 texels at z1 */
  862.          lp_build_sample_texel_soa(bld, sampler_unit,
  863.                                    width_vec, height_vec, depth_vec,
  864.                                    x0, y0, z1,
  865.                                    row_stride_vec, img_stride_vec,
  866.                                    data_ptr, mipoffsets, neighbors1[0][0]);
  867.          lp_build_sample_texel_soa(bld, sampler_unit,
  868.                                    width_vec, height_vec, depth_vec,
  869.                                    x1, y0, z1,
  870.                                    row_stride_vec, img_stride_vec,
  871.                                    data_ptr, mipoffsets, neighbors1[0][1]);
  872.          lp_build_sample_texel_soa(bld, sampler_unit,
  873.                                    width_vec, height_vec, depth_vec,
  874.                                    x0, y1, z1,
  875.                                    row_stride_vec, img_stride_vec,
  876.                                    data_ptr, mipoffsets, neighbors1[1][0]);
  877.          lp_build_sample_texel_soa(bld, sampler_unit,
  878.                                    width_vec, height_vec, depth_vec,
  879.                                    x1, y1, z1,
  880.                                    row_stride_vec, img_stride_vec,
  881.                                    data_ptr, mipoffsets, neighbors1[1][1]);
  882.  
  883.          /* Bilinear interpolate the four samples from the second Z slice */
  884.          for (chan = 0; chan < 4; chan++) {
  885.             colors1[chan] = lp_build_lerp_2d(&bld->texel_bld,
  886.                                              s_fpart, t_fpart,
  887.                                              neighbors1[0][0][chan],
  888.                                              neighbors1[0][1][chan],
  889.                                              neighbors1[1][0][chan],
  890.                                              neighbors1[1][1][chan],
  891.                                              0);
  892.          }
  893.  
  894.          /* Linearly interpolate the two samples from the two 3D slices */
  895.          for (chan = 0; chan < 4; chan++) {
  896.             colors_out[chan] = lp_build_lerp(&bld->texel_bld,
  897.                                              r_fpart,
  898.                                              colors0[chan], colors1[chan],
  899.                                              0);
  900.          }
  901.       }
  902.       else {
  903.          /* 2D tex */
  904.          for (chan = 0; chan < 4; chan++) {
  905.             colors_out[chan] = colors0[chan];
  906.          }
  907.       }
  908.    }
  909. }
  910.  
  911.  
  912. /**
  913.  * Sample the texture/mipmap using given image filter and mip filter.
  914.  * data0_ptr and data1_ptr point to the two mipmap levels to sample
  915.  * from.  width0/1_vec, height0/1_vec, depth0/1_vec indicate their sizes.
  916.  * If we're using nearest miplevel sampling the '1' values will be null/unused.
  917.  */
  918. static void
  919. lp_build_sample_mipmap(struct lp_build_sample_context *bld,
  920.                        unsigned sampler_unit,
  921.                        unsigned img_filter,
  922.                        unsigned mip_filter,
  923.                        LLVMValueRef s,
  924.                        LLVMValueRef t,
  925.                        LLVMValueRef r,
  926.                        const LLVMValueRef *offsets,
  927.                        LLVMValueRef ilevel0,
  928.                        LLVMValueRef ilevel1,
  929.                        LLVMValueRef lod_fpart,
  930.                        LLVMValueRef *colors_out)
  931. {
  932.    LLVMBuilderRef builder = bld->gallivm->builder;
  933.    LLVMValueRef size0 = NULL;
  934.    LLVMValueRef size1 = NULL;
  935.    LLVMValueRef row_stride0_vec = NULL;
  936.    LLVMValueRef row_stride1_vec = NULL;
  937.    LLVMValueRef img_stride0_vec = NULL;
  938.    LLVMValueRef img_stride1_vec = NULL;
  939.    LLVMValueRef data_ptr0 = NULL;
  940.    LLVMValueRef data_ptr1 = NULL;
  941.    LLVMValueRef mipoff0 = NULL;
  942.    LLVMValueRef mipoff1 = NULL;
  943.    LLVMValueRef colors0[4], colors1[4];
  944.    unsigned chan;
  945.  
  946.    /* sample the first mipmap level */
  947.    lp_build_mipmap_level_sizes(bld, ilevel0,
  948.                                &size0,
  949.                                &row_stride0_vec, &img_stride0_vec);
  950.    if (bld->num_lods == 1) {
  951.       data_ptr0 = lp_build_get_mipmap_level(bld, ilevel0);
  952.    }
  953.    else {
  954.       /* This path should work for num_lods 1 too but slightly less efficient */
  955.       data_ptr0 = bld->base_ptr;
  956.       mipoff0 = lp_build_get_mip_offsets(bld, ilevel0);
  957.    }
  958.    if (img_filter == PIPE_TEX_FILTER_NEAREST) {
  959.       lp_build_sample_image_nearest(bld, sampler_unit,
  960.                                     size0,
  961.                                     row_stride0_vec, img_stride0_vec,
  962.                                     data_ptr0, mipoff0, s, t, r, offsets,
  963.                                     colors0);
  964.    }
  965.    else {
  966.       assert(img_filter == PIPE_TEX_FILTER_LINEAR);
  967.       lp_build_sample_image_linear(bld, sampler_unit,
  968.                                    size0,
  969.                                    row_stride0_vec, img_stride0_vec,
  970.                                    data_ptr0, mipoff0, s, t, r, offsets,
  971.                                    colors0);
  972.    }
  973.  
  974.    /* Store the first level's colors in the output variables */
  975.    for (chan = 0; chan < 4; chan++) {
  976.        LLVMBuildStore(builder, colors0[chan], colors_out[chan]);
  977.    }
  978.  
  979.    if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
  980.       struct lp_build_if_state if_ctx;
  981.       LLVMValueRef need_lerp;
  982.  
  983.       /* need_lerp = lod_fpart > 0 */
  984.       if (bld->num_lods == 1) {
  985.          need_lerp = LLVMBuildFCmp(builder, LLVMRealUGT,
  986.                                    lod_fpart, bld->levelf_bld.zero,
  987.                                    "need_lerp");
  988.       }
  989.       else {
  990.          /*
  991.           * We'll do mip filtering if any of the quads (or individual
  992.           * pixel in case of per-pixel lod) need it.
  993.           * It might be better to split the vectors here and only fetch/filter
  994.           * quads which need it.
  995.           */
  996.          /*
  997.           * We unfortunately need to clamp lod_fpart here since we can get
  998.           * negative values which would screw up filtering if not all
  999.           * lod_fpart values have same sign.
  1000.           */
  1001.          lod_fpart = lp_build_max(&bld->levelf_bld, lod_fpart,
  1002.                                   bld->levelf_bld.zero);
  1003.          need_lerp = lp_build_compare(bld->gallivm, bld->levelf_bld.type,
  1004.                                       PIPE_FUNC_GREATER,
  1005.                                       lod_fpart, bld->levelf_bld.zero);
  1006.          need_lerp = lp_build_any_true_range(&bld->leveli_bld, bld->num_lods, need_lerp);
  1007.       }
  1008.  
  1009.       lp_build_if(&if_ctx, bld->gallivm, need_lerp);
  1010.       {
  1011.          /* sample the second mipmap level */
  1012.          lp_build_mipmap_level_sizes(bld, ilevel1,
  1013.                                      &size1,
  1014.                                      &row_stride1_vec, &img_stride1_vec);
  1015.          if (bld->num_lods == 1) {
  1016.             data_ptr1 = lp_build_get_mipmap_level(bld, ilevel1);
  1017.          }
  1018.          else {
  1019.             data_ptr1 = bld->base_ptr;
  1020.             mipoff1 = lp_build_get_mip_offsets(bld, ilevel1);
  1021.          }
  1022.          if (img_filter == PIPE_TEX_FILTER_NEAREST) {
  1023.             lp_build_sample_image_nearest(bld, sampler_unit,
  1024.                                           size1,
  1025.                                           row_stride1_vec, img_stride1_vec,
  1026.                                           data_ptr1, mipoff1, s, t, r, offsets,
  1027.                                           colors1);
  1028.          }
  1029.          else {
  1030.             lp_build_sample_image_linear(bld, sampler_unit,
  1031.                                          size1,
  1032.                                          row_stride1_vec, img_stride1_vec,
  1033.                                          data_ptr1, mipoff1, s, t, r, offsets,
  1034.                                          colors1);
  1035.          }
  1036.  
  1037.          /* interpolate samples from the two mipmap levels */
  1038.  
  1039.          if (bld->num_lods != bld->coord_type.length)
  1040.             lod_fpart = lp_build_unpack_broadcast_aos_scalars(bld->gallivm,
  1041.                                                               bld->levelf_bld.type,
  1042.                                                               bld->texel_bld.type,
  1043.                                                               lod_fpart);
  1044.  
  1045.          for (chan = 0; chan < 4; chan++) {
  1046.             colors0[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart,
  1047.                                           colors0[chan], colors1[chan],
  1048.                                           0);
  1049.             LLVMBuildStore(builder, colors0[chan], colors_out[chan]);
  1050.          }
  1051.       }
  1052.       lp_build_endif(&if_ctx);
  1053.    }
  1054. }
  1055.  
  1056.  
  1057. /**
  1058.  * Clamp layer coord to valid values.
  1059.  */
  1060. static LLVMValueRef
  1061. lp_build_layer_coord(struct lp_build_sample_context *bld,
  1062.                      unsigned texture_unit,
  1063.                      LLVMValueRef layer)
  1064. {
  1065.    LLVMValueRef maxlayer;
  1066.  
  1067.    maxlayer = bld->dynamic_state->depth(bld->dynamic_state,
  1068.                                         bld->gallivm, texture_unit);
  1069.    maxlayer = lp_build_sub(&bld->int_bld, maxlayer, bld->int_bld.one);
  1070.    maxlayer = lp_build_broadcast_scalar(&bld->int_coord_bld, maxlayer);
  1071.    return lp_build_clamp(&bld->int_coord_bld, layer,
  1072.                          bld->int_coord_bld.zero, maxlayer);
  1073.  
  1074. }
  1075.  
  1076.  
  1077. /**
  1078.  * Calculate cube face, lod, mip levels.
  1079.  */
  1080. static void
  1081. lp_build_sample_common(struct lp_build_sample_context *bld,
  1082.                        unsigned texture_index,
  1083.                        unsigned sampler_index,
  1084.                        LLVMValueRef *s,
  1085.                        LLVMValueRef *t,
  1086.                        LLVMValueRef *r,
  1087.                        const struct lp_derivatives *derivs, /* optional */
  1088.                        LLVMValueRef lod_bias, /* optional */
  1089.                        LLVMValueRef explicit_lod, /* optional */
  1090.                        LLVMValueRef *lod_ipart,
  1091.                        LLVMValueRef *lod_fpart,
  1092.                        LLVMValueRef *ilevel0,
  1093.                        LLVMValueRef *ilevel1)
  1094. {
  1095.    const unsigned mip_filter = bld->static_sampler_state->min_mip_filter;
  1096.    const unsigned min_filter = bld->static_sampler_state->min_img_filter;
  1097.    const unsigned mag_filter = bld->static_sampler_state->mag_img_filter;
  1098.    const unsigned target = bld->static_texture_state->target;
  1099.    LLVMValueRef first_level, cube_rho = NULL;
  1100.  
  1101.    /*
  1102.    printf("%s mip %d  min %d  mag %d\n", __FUNCTION__,
  1103.           mip_filter, min_filter, mag_filter);
  1104.    */
  1105.  
  1106.    /*
  1107.     * Choose cube face, recompute texcoords for the chosen face and
  1108.     * compute rho here too (as it requires transform of derivatives).
  1109.     */
  1110.    if (target == PIPE_TEXTURE_CUBE) {
  1111.       LLVMValueRef face, face_s, face_t;
  1112.       boolean need_derivs;
  1113.       need_derivs = ((min_filter != mag_filter ||
  1114.                       mip_filter != PIPE_TEX_MIPFILTER_NONE) &&
  1115.                       !bld->static_sampler_state->min_max_lod_equal &&
  1116.                       !explicit_lod);
  1117.       lp_build_cube_lookup(bld, *s, *t, *r, derivs, &face, &face_s, &face_t,
  1118.                            &cube_rho, need_derivs);
  1119.       *s = face_s; /* vec */
  1120.       *t = face_t; /* vec */
  1121.       /* use 'r' to indicate cube face */
  1122.       *r = face; /* vec */
  1123.    }
  1124.    else if (target == PIPE_TEXTURE_1D_ARRAY) {
  1125.       *r = lp_build_iround(&bld->coord_bld, *t);
  1126.       *r = lp_build_layer_coord(bld, texture_index, *r);
  1127.    }
  1128.    else if (target == PIPE_TEXTURE_2D_ARRAY) {
  1129.       *r = lp_build_iround(&bld->coord_bld, *r);
  1130.       *r = lp_build_layer_coord(bld, texture_index, *r);
  1131.    }
  1132.  
  1133.    /*
  1134.     * Compute the level of detail (float).
  1135.     */
  1136.    if (min_filter != mag_filter ||
  1137.        mip_filter != PIPE_TEX_MIPFILTER_NONE) {
  1138.       /* Need to compute lod either to choose mipmap levels or to
  1139.        * distinguish between minification/magnification with one mipmap level.
  1140.        */
  1141.       lp_build_lod_selector(bld, texture_index, sampler_index,
  1142.                             *s, *t, *r, cube_rho,
  1143.                             derivs, lod_bias, explicit_lod,
  1144.                             mip_filter,
  1145.                             lod_ipart, lod_fpart);
  1146.    } else {
  1147.       *lod_ipart = bld->leveli_bld.zero;
  1148.    }
  1149.  
  1150.    /*
  1151.     * Compute integer mipmap level(s) to fetch texels from: ilevel0, ilevel1
  1152.     */
  1153.    switch (mip_filter) {
  1154.    default:
  1155.       assert(0 && "bad mip_filter value in lp_build_sample_soa()");
  1156.       /* fall-through */
  1157.    case PIPE_TEX_MIPFILTER_NONE:
  1158.       /* always use mip level 0 */
  1159.       if (HAVE_LLVM == 0x0207 && target == PIPE_TEXTURE_CUBE) {
  1160.          /* XXX this is a work-around for an apparent bug in LLVM 2.7.
  1161.           * We should be able to set ilevel0 = const(0) but that causes
  1162.           * bad x86 code to be emitted.
  1163.           */
  1164.          assert(*lod_ipart);
  1165.          lp_build_nearest_mip_level(bld, texture_index, *lod_ipart, ilevel0);
  1166.       }
  1167.       else {
  1168.          first_level = bld->dynamic_state->first_level(bld->dynamic_state,
  1169.                                                        bld->gallivm, texture_index);
  1170.          first_level = lp_build_broadcast_scalar(&bld->leveli_bld, first_level);
  1171.          *ilevel0 = first_level;
  1172.       }
  1173.       break;
  1174.    case PIPE_TEX_MIPFILTER_NEAREST:
  1175.       assert(*lod_ipart);
  1176.       lp_build_nearest_mip_level(bld, texture_index, *lod_ipart, ilevel0);
  1177.       break;
  1178.    case PIPE_TEX_MIPFILTER_LINEAR:
  1179.       assert(*lod_ipart);
  1180.       assert(*lod_fpart);
  1181.       lp_build_linear_mip_levels(bld, texture_index,
  1182.                                  *lod_ipart, lod_fpart,
  1183.                                  ilevel0, ilevel1);
  1184.       break;
  1185.    }
  1186. }
  1187.  
  1188. /**
  1189.  * General texture sampling codegen.
  1190.  * This function handles texture sampling for all texture targets (1D,
  1191.  * 2D, 3D, cube) and all filtering modes.
  1192.  */
  1193. static void
  1194. lp_build_sample_general(struct lp_build_sample_context *bld,
  1195.                         unsigned sampler_unit,
  1196.                         LLVMValueRef s,
  1197.                         LLVMValueRef t,
  1198.                         LLVMValueRef r,
  1199.                         const LLVMValueRef *offsets,
  1200.                         LLVMValueRef lod_ipart,
  1201.                         LLVMValueRef lod_fpart,
  1202.                         LLVMValueRef ilevel0,
  1203.                         LLVMValueRef ilevel1,
  1204.                         LLVMValueRef *colors_out)
  1205. {
  1206.    struct lp_build_context *int_bld = &bld->int_bld;
  1207.    LLVMBuilderRef builder = bld->gallivm->builder;
  1208.    const unsigned mip_filter = bld->static_sampler_state->min_mip_filter;
  1209.    const unsigned min_filter = bld->static_sampler_state->min_img_filter;
  1210.    const unsigned mag_filter = bld->static_sampler_state->mag_img_filter;
  1211.    LLVMValueRef texels[4];
  1212.    unsigned chan;
  1213.  
  1214.    /*
  1215.     * Get/interpolate texture colors.
  1216.     */
  1217.  
  1218.    for (chan = 0; chan < 4; ++chan) {
  1219.      texels[chan] = lp_build_alloca(bld->gallivm, bld->texel_bld.vec_type, "");
  1220.      lp_build_name(texels[chan], "sampler%u_texel_%c_var", sampler_unit, "xyzw"[chan]);
  1221.    }
  1222.  
  1223.    if (min_filter == mag_filter) {
  1224.       /* no need to distinguish between minification and magnification */
  1225.       lp_build_sample_mipmap(bld, sampler_unit,
  1226.                              min_filter, mip_filter,
  1227.                              s, t, r, offsets,
  1228.                              ilevel0, ilevel1, lod_fpart,
  1229.                              texels);
  1230.    }
  1231.    else {
  1232.       /* Emit conditional to choose min image filter or mag image filter
  1233.        * depending on the lod being > 0 or <= 0, respectively.
  1234.        */
  1235.       struct lp_build_if_state if_ctx;
  1236.       LLVMValueRef minify;
  1237.  
  1238.       /*
  1239.        * XXX this should to all lods into account, if some are min
  1240.        * some max probably could hack up the coords/weights in the linear
  1241.        * path with selects to work for nearest.
  1242.        * If that's just two quads sitting next to each other it seems
  1243.        * quite ok to do the same filtering method on both though, at
  1244.        * least unless we have explicit lod (and who uses different
  1245.        * min/mag filter with that?)
  1246.        */
  1247.       if (bld->num_lods > 1)
  1248.          lod_ipart = LLVMBuildExtractElement(builder, lod_ipart,
  1249.                                              lp_build_const_int32(bld->gallivm, 0), "");
  1250.  
  1251.       /* minify = lod >= 0.0 */
  1252.       minify = LLVMBuildICmp(builder, LLVMIntSGE,
  1253.                              lod_ipart, int_bld->zero, "");
  1254.  
  1255.       lp_build_if(&if_ctx, bld->gallivm, minify);
  1256.       {
  1257.          /* Use the minification filter */
  1258.          lp_build_sample_mipmap(bld, sampler_unit,
  1259.                                 min_filter, mip_filter,
  1260.                                 s, t, r, offsets,
  1261.                                 ilevel0, ilevel1, lod_fpart,
  1262.                                 texels);
  1263.       }
  1264.       lp_build_else(&if_ctx);
  1265.       {
  1266.          /* Use the magnification filter */
  1267.          lp_build_sample_mipmap(bld, sampler_unit,
  1268.                                 mag_filter, PIPE_TEX_MIPFILTER_NONE,
  1269.                                 s, t, r, offsets,
  1270.                                 ilevel0, NULL, NULL,
  1271.                                 texels);
  1272.       }
  1273.       lp_build_endif(&if_ctx);
  1274.    }
  1275.  
  1276.    for (chan = 0; chan < 4; ++chan) {
  1277.      colors_out[chan] = LLVMBuildLoad(builder, texels[chan], "");
  1278.      lp_build_name(colors_out[chan], "sampler%u_texel_%c", sampler_unit, "xyzw"[chan]);
  1279.    }
  1280. }
  1281.  
  1282.  
  1283. /**
  1284.  * Texel fetch function.
  1285.  * In contrast to general sampling there is no filtering, no coord minification,
  1286.  * lod (if any) is always explicit uint, coords are uints (in terms of texel units)
  1287.  * directly to be applied to the selected mip level (after adding texel offsets).
  1288.  * This function handles texel fetch for all targets where texel fetch is supported
  1289.  * (no cube maps, but 1d, 2d, 3d are supported, arrays and buffers should be too).
  1290.  */
  1291. static void
  1292. lp_build_fetch_texel(struct lp_build_sample_context *bld,
  1293.                      unsigned texture_unit,
  1294.                      const LLVMValueRef *coords,
  1295.                      LLVMValueRef explicit_lod,
  1296.                      const LLVMValueRef *offsets,
  1297.                      LLVMValueRef *colors_out)
  1298. {
  1299.    struct lp_build_context *perquadi_bld = &bld->leveli_bld;
  1300.    struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
  1301.    unsigned dims = bld->dims, chan;
  1302.    unsigned target = bld->static_texture_state->target;
  1303.    LLVMValueRef size, ilevel;
  1304.    LLVMValueRef row_stride_vec = NULL, img_stride_vec = NULL;
  1305.    LLVMValueRef x = coords[0], y = coords[1], z = coords[2];
  1306.    LLVMValueRef width, height, depth, i, j;
  1307.    LLVMValueRef offset, out_of_bounds, out1;
  1308.  
  1309.    if (explicit_lod && bld->static_texture_state->target != PIPE_BUFFER) {
  1310.       if (bld->num_lods != int_coord_bld->type.length) {
  1311.          ilevel = lp_build_pack_aos_scalars(bld->gallivm, int_coord_bld->type,
  1312.                                             perquadi_bld->type, explicit_lod, 0);
  1313.       }
  1314.       else {
  1315.          ilevel = explicit_lod;
  1316.       }
  1317.       lp_build_nearest_mip_level(bld, texture_unit, ilevel, &ilevel);
  1318.    }
  1319.    else {
  1320.       bld->num_lods = 1;
  1321.       ilevel = lp_build_const_int32(bld->gallivm, 0);
  1322.    }
  1323.    lp_build_mipmap_level_sizes(bld, ilevel,
  1324.                                &size,
  1325.                                &row_stride_vec, &img_stride_vec);
  1326.    lp_build_extract_image_sizes(bld, &bld->int_size_bld, int_coord_bld->type,
  1327.                                 size, &width, &height, &depth);
  1328.  
  1329.    if (target == PIPE_TEXTURE_1D_ARRAY ||
  1330.        target == PIPE_TEXTURE_2D_ARRAY) {
  1331.       if (target == PIPE_TEXTURE_1D_ARRAY) {
  1332.          z = lp_build_layer_coord(bld, texture_unit, y);
  1333.       }
  1334.       else {
  1335.          z = lp_build_layer_coord(bld, texture_unit, z);
  1336.       }
  1337.    }
  1338.  
  1339.    /* This is a lot like border sampling */
  1340.    if (offsets[0]) {
  1341.       /* XXX coords are really unsigned, offsets are signed */
  1342.       x = lp_build_add(int_coord_bld, x, offsets[0]);
  1343.    }
  1344.    out_of_bounds = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, x, int_coord_bld->zero);
  1345.    out1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, x, width);
  1346.    out_of_bounds = lp_build_or(int_coord_bld, out_of_bounds, out1);
  1347.  
  1348.    if (dims >= 2) {
  1349.       if (offsets[1]) {
  1350.          y = lp_build_add(int_coord_bld, y, offsets[1]);
  1351.       }
  1352.       out1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, y, int_coord_bld->zero);
  1353.       out_of_bounds = lp_build_or(int_coord_bld, out_of_bounds, out1);
  1354.       out1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, y, height);
  1355.       out_of_bounds = lp_build_or(int_coord_bld, out_of_bounds, out1);
  1356.  
  1357.       if (dims >= 3) {
  1358.          if (offsets[2]) {
  1359.             z = lp_build_add(int_coord_bld, z, offsets[2]);
  1360.          }
  1361.          out1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, z, int_coord_bld->zero);
  1362.          out_of_bounds = lp_build_or(int_coord_bld, out_of_bounds, out1);
  1363.          out1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, z, depth);
  1364.          out_of_bounds = lp_build_or(int_coord_bld, out_of_bounds, out1);
  1365.       }
  1366.    }
  1367.  
  1368.    lp_build_sample_offset(int_coord_bld,
  1369.                           bld->format_desc,
  1370.                           x, y, z, row_stride_vec, img_stride_vec,
  1371.                           &offset, &i, &j);
  1372.  
  1373.    if (bld->static_texture_state->target != PIPE_BUFFER) {
  1374.       offset = lp_build_add(int_coord_bld, offset,
  1375.                             lp_build_get_mip_offsets(bld, ilevel));
  1376.    }
  1377.  
  1378.    offset = lp_build_andnot(int_coord_bld, offset, out_of_bounds);
  1379.  
  1380.    lp_build_fetch_rgba_soa(bld->gallivm,
  1381.                            bld->format_desc,
  1382.                            bld->texel_type,
  1383.                            bld->base_ptr, offset,
  1384.                            i, j,
  1385.                            colors_out);
  1386.  
  1387.    if (0) {
  1388.       /*
  1389.        * Not needed except for ARB_robust_buffer_access_behavior.
  1390.        * Could use min/max above instead of out-of-bounds comparisons
  1391.        * (in fact cast to unsigned and min only is sufficient)
  1392.        * if we don't care about the result returned for out-of-bounds.
  1393.        */
  1394.       for (chan = 0; chan < 4; chan++) {
  1395.          colors_out[chan] = lp_build_select(&bld->texel_bld, out_of_bounds,
  1396.                                             bld->texel_bld.zero, colors_out[chan]);
  1397.       }
  1398.    }
  1399. }
  1400.  
  1401.  
  1402. /**
  1403.  * Do shadow test/comparison.
  1404.  * \param coords  incoming texcoords
  1405.  * \param texel  the texel to compare against (use the X channel)
  1406.  * Ideally this should really be done per-sample.
  1407.  */
  1408. static void
  1409. lp_build_sample_compare(struct lp_build_sample_context *bld,
  1410.                         const LLVMValueRef *coords,
  1411.                         LLVMValueRef texel[4])
  1412. {
  1413.    struct lp_build_context *texel_bld = &bld->texel_bld;
  1414.    LLVMBuilderRef builder = bld->gallivm->builder;
  1415.    LLVMValueRef res, p;
  1416.    const unsigned chan = 0;
  1417.  
  1418.    if (bld->static_sampler_state->compare_mode == PIPE_TEX_COMPARE_NONE)
  1419.       return;
  1420.  
  1421.    if (bld->static_texture_state->target == PIPE_TEXTURE_2D_ARRAY ||
  1422.        bld->static_texture_state->target == PIPE_TEXTURE_CUBE) {
  1423.       p = coords[3];
  1424.    }
  1425.    else {
  1426.       p = coords[2];
  1427.    }
  1428.  
  1429.    /* debug code */
  1430.    if (0) {
  1431.       LLVMValueRef indx = lp_build_const_int32(bld->gallivm, 0);
  1432.       LLVMValueRef coord = LLVMBuildExtractElement(builder, p, indx, "");
  1433.       LLVMValueRef tex = LLVMBuildExtractElement(builder, texel[chan], indx, "");
  1434.       lp_build_printf(bld->gallivm, "shadow compare coord %f to texture %f\n",
  1435.                       coord, tex);
  1436.    }
  1437.  
  1438.    /* Clamp p coords to [0,1] */
  1439.    p = lp_build_clamp(&bld->coord_bld, p,
  1440.                       bld->coord_bld.zero,
  1441.                       bld->coord_bld.one);
  1442.  
  1443.    /* result = (p FUNC texel) ? 1 : 0 */
  1444.    res = lp_build_cmp(texel_bld, bld->static_sampler_state->compare_func,
  1445.                       p, texel[chan]);
  1446.    res = lp_build_select(texel_bld, res, texel_bld->one, texel_bld->zero);
  1447.  
  1448.    /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
  1449.    texel[0] =
  1450.    texel[1] =
  1451.    texel[2] = res;
  1452.    texel[3] = texel_bld->one;
  1453. }
  1454.  
  1455.  
  1456. /**
  1457.  * Just set texels to white instead of actually sampling the texture.
  1458.  * For debugging.
  1459.  */
  1460. void
  1461. lp_build_sample_nop(struct gallivm_state *gallivm,
  1462.                     struct lp_type type,
  1463.                     const LLVMValueRef *coords,
  1464.                     LLVMValueRef texel_out[4])
  1465. {
  1466.    LLVMValueRef one = lp_build_one(gallivm, type);
  1467.    unsigned chan;
  1468.  
  1469.    for (chan = 0; chan < 4; chan++) {
  1470.       texel_out[chan] = one;
  1471.    }  
  1472. }
  1473.  
  1474.  
  1475. /**
  1476.  * Build texture sampling code.
  1477.  * 'texel' will return a vector of four LLVMValueRefs corresponding to
  1478.  * R, G, B, A.
  1479.  * \param type  vector float type to use for coords, etc.
  1480.  * \param is_fetch  if this is a texel fetch instruction.
  1481.  * \param derivs  partial derivatives of (s,t,r,q) with respect to x and y
  1482.  */
  1483. void
  1484. lp_build_sample_soa(struct gallivm_state *gallivm,
  1485.                     const struct lp_static_texture_state *static_texture_state,
  1486.                     const struct lp_static_sampler_state *static_sampler_state,
  1487.                     struct lp_sampler_dynamic_state *dynamic_state,
  1488.                     struct lp_type type,
  1489.                     boolean is_fetch,
  1490.                     unsigned texture_index,
  1491.                     unsigned sampler_index,
  1492.                     const LLVMValueRef *coords,
  1493.                     const LLVMValueRef *offsets,
  1494.                     const struct lp_derivatives *derivs, /* optional */
  1495.                     LLVMValueRef lod_bias, /* optional */
  1496.                     LLVMValueRef explicit_lod, /* optional */
  1497.                     boolean scalar_lod,
  1498.                     LLVMValueRef texel_out[4])
  1499. {
  1500.    unsigned dims = texture_dims(static_texture_state->target);
  1501.    unsigned num_quads = type.length / 4;
  1502.    unsigned mip_filter;
  1503.    struct lp_build_sample_context bld;
  1504.    struct lp_static_sampler_state derived_sampler_state = *static_sampler_state;
  1505.    LLVMTypeRef i32t = LLVMInt32TypeInContext(gallivm->context);
  1506.    LLVMBuilderRef builder = gallivm->builder;
  1507.    LLVMValueRef tex_width;
  1508.    LLVMValueRef s;
  1509.    LLVMValueRef t;
  1510.    LLVMValueRef r;
  1511.  
  1512.    if (0) {
  1513.       enum pipe_format fmt = static_texture_state->format;
  1514.       debug_printf("Sample from %s\n", util_format_name(fmt));
  1515.    }
  1516.  
  1517.    assert(type.floating);
  1518.  
  1519.    /* Setup our build context */
  1520.    memset(&bld, 0, sizeof bld);
  1521.    bld.gallivm = gallivm;
  1522.    bld.static_sampler_state = &derived_sampler_state;
  1523.    bld.static_texture_state = static_texture_state;
  1524.    bld.dynamic_state = dynamic_state;
  1525.    bld.format_desc = util_format_description(static_texture_state->format);
  1526.    bld.dims = dims;
  1527.  
  1528.    bld.vector_width = lp_type_width(type);
  1529.  
  1530.    bld.float_type = lp_type_float(32);
  1531.    bld.int_type = lp_type_int(32);
  1532.    bld.coord_type = type;
  1533.    bld.int_coord_type = lp_int_type(type);
  1534.    bld.float_size_in_type = lp_type_float(32);
  1535.    bld.float_size_in_type.length = dims > 1 ? 4 : 1;
  1536.    bld.int_size_in_type = lp_int_type(bld.float_size_in_type);
  1537.    bld.texel_type = type;
  1538.  
  1539.    /* always using the first channel hopefully should be safe,
  1540.     * if not things WILL break in other places anyway.
  1541.     */
  1542.    if (bld.format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB &&
  1543.        bld.format_desc->channel[0].pure_integer) {
  1544.       if (bld.format_desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) {
  1545.          bld.texel_type = lp_type_int_vec(type.width, type.width * type.length);
  1546.       }
  1547.       else if (bld.format_desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED) {
  1548.          bld.texel_type = lp_type_uint_vec(type.width, type.width * type.length);
  1549.       }
  1550.    }
  1551.    else if (util_format_has_stencil(bld.format_desc) &&
  1552.        !util_format_has_depth(bld.format_desc)) {
  1553.       /* for stencil only formats, sample stencil (uint) */
  1554.       bld.texel_type = lp_type_int_vec(type.width, type.width * type.length);
  1555.    }
  1556.  
  1557.    if (!static_texture_state->level_zero_only) {
  1558.       derived_sampler_state.min_mip_filter = static_sampler_state->min_mip_filter;
  1559.    } else {
  1560.       derived_sampler_state.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
  1561.    }
  1562.    mip_filter = derived_sampler_state.min_mip_filter;
  1563.  
  1564.    if (0) {
  1565.       debug_printf("  .min_mip_filter = %u\n", derived_sampler_state.min_mip_filter);
  1566.    }
  1567.  
  1568.    /*
  1569.     * This is all a bit complicated different paths are chosen for performance
  1570.     * reasons.
  1571.     * Essentially, there can be 1 lod per element, 1 lod per quad or 1 lod for
  1572.     * everything (the last two options are equivalent for 4-wide case).
  1573.     * If there's per-quad lod but we split to 4-wide so we can use AoS, per-quad
  1574.     * lod is calculated then the lod value extracted afterwards so making this
  1575.     * case basically the same as far as lod handling is concerned for the
  1576.     * further sample/filter code as the 1 lod for everything case.
  1577.     * Different lod handling mostly shows up when building mipmap sizes
  1578.     * (lp_build_mipmap_level_sizes() and friends) and also in filtering
  1579.     * (getting the fractional part of the lod to the right texels).
  1580.     */
  1581.  
  1582.    /*
  1583.     * There are other situations where at least the multiple int lods could be
  1584.     * avoided like min and max lod being equal.
  1585.     */
  1586.    if (explicit_lod && !scalar_lod &&
  1587.        ((is_fetch && bld.static_texture_state->target != PIPE_BUFFER) ||
  1588.         (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)))
  1589.       bld.num_lods = type.length;
  1590.    /* TODO: for true scalar_lod should only use 1 lod value */
  1591.    else if ((is_fetch && explicit_lod && bld.static_texture_state->target != PIPE_BUFFER ) ||
  1592.             (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)) {
  1593.       bld.num_lods = num_quads;
  1594.    }
  1595.    else {
  1596.       bld.num_lods = 1;
  1597.    }
  1598.  
  1599.    bld.levelf_type = type;
  1600.    /* we want native vector size to be able to use our intrinsics */
  1601.    if (bld.num_lods != type.length) {
  1602.       bld.levelf_type.length = type.length > 4 ? ((type.length + 15) / 16) * 4 : 1;
  1603.    }
  1604.    bld.leveli_type = lp_int_type(bld.levelf_type);
  1605.    bld.float_size_type = bld.float_size_in_type;
  1606.    /* Note: size vectors may not be native. They contain minified w/h/d/_ values,
  1607.     * with per-element lod that is w0/h0/d0/_/w1/h1/d1_/... so up to 8x4f32 */
  1608.    if (bld.num_lods > 1) {
  1609.       bld.float_size_type.length = bld.num_lods == type.length ?
  1610.                                       bld.num_lods * bld.float_size_in_type.length :
  1611.                                       type.length;
  1612.    }
  1613.    bld.int_size_type = lp_int_type(bld.float_size_type);
  1614.  
  1615.    lp_build_context_init(&bld.float_bld, gallivm, bld.float_type);
  1616.    lp_build_context_init(&bld.float_vec_bld, gallivm, type);
  1617.    lp_build_context_init(&bld.int_bld, gallivm, bld.int_type);
  1618.    lp_build_context_init(&bld.coord_bld, gallivm, bld.coord_type);
  1619.    lp_build_context_init(&bld.int_coord_bld, gallivm, bld.int_coord_type);
  1620.    lp_build_context_init(&bld.int_size_in_bld, gallivm, bld.int_size_in_type);
  1621.    lp_build_context_init(&bld.float_size_in_bld, gallivm, bld.float_size_in_type);
  1622.    lp_build_context_init(&bld.int_size_bld, gallivm, bld.int_size_type);
  1623.    lp_build_context_init(&bld.float_size_bld, gallivm, bld.float_size_type);
  1624.    lp_build_context_init(&bld.texel_bld, gallivm, bld.texel_type);
  1625.    lp_build_context_init(&bld.levelf_bld, gallivm, bld.levelf_type);
  1626.    lp_build_context_init(&bld.leveli_bld, gallivm, bld.leveli_type);
  1627.  
  1628.    /* Get the dynamic state */
  1629.    tex_width = dynamic_state->width(dynamic_state, gallivm, texture_index);
  1630.    bld.row_stride_array = dynamic_state->row_stride(dynamic_state, gallivm, texture_index);
  1631.    bld.img_stride_array = dynamic_state->img_stride(dynamic_state, gallivm, texture_index);
  1632.    bld.base_ptr = dynamic_state->base_ptr(dynamic_state, gallivm, texture_index);
  1633.    bld.mip_offsets = dynamic_state->mip_offsets(dynamic_state, gallivm, texture_index);
  1634.    /* Note that mip_offsets is an array[level] of offsets to texture images */
  1635.  
  1636.    s = coords[0];
  1637.    t = coords[1];
  1638.    r = coords[2];
  1639.  
  1640.    /* width, height, depth as single int vector */
  1641.    if (dims <= 1) {
  1642.       bld.int_size = tex_width;
  1643.    }
  1644.    else {
  1645.       bld.int_size = LLVMBuildInsertElement(builder, bld.int_size_in_bld.undef,
  1646.                                             tex_width, LLVMConstInt(i32t, 0, 0), "");
  1647.       if (dims >= 2) {
  1648.          LLVMValueRef tex_height =
  1649.             dynamic_state->height(dynamic_state, gallivm, texture_index);
  1650.          bld.int_size = LLVMBuildInsertElement(builder, bld.int_size,
  1651.                                                tex_height, LLVMConstInt(i32t, 1, 0), "");
  1652.          if (dims >= 3) {
  1653.             LLVMValueRef tex_depth =
  1654.                dynamic_state->depth(dynamic_state, gallivm, texture_index);
  1655.             bld.int_size = LLVMBuildInsertElement(builder, bld.int_size,
  1656.                                                   tex_depth, LLVMConstInt(i32t, 2, 0), "");
  1657.          }
  1658.       }
  1659.    }
  1660.  
  1661.    if (0) {
  1662.       /* For debug: no-op texture sampling */
  1663.       lp_build_sample_nop(gallivm,
  1664.                           bld.texel_type,
  1665.                           coords,
  1666.                           texel_out);
  1667.    }
  1668.  
  1669.    else if (is_fetch) {
  1670.       lp_build_fetch_texel(&bld, texture_index, coords,
  1671.                            explicit_lod, offsets,
  1672.                            texel_out);
  1673.    }
  1674.  
  1675.    else {
  1676.       LLVMValueRef lod_ipart = NULL, lod_fpart = NULL;
  1677.       LLVMValueRef ilevel0 = NULL, ilevel1 = NULL;
  1678.       boolean use_aos = util_format_fits_8unorm(bld.format_desc) &&
  1679.                         lp_is_simple_wrap_mode(static_sampler_state->wrap_s) &&
  1680.                         lp_is_simple_wrap_mode(static_sampler_state->wrap_t);
  1681.  
  1682.       if ((gallivm_debug & GALLIVM_DEBUG_PERF) &&
  1683.           !use_aos && util_format_fits_8unorm(bld.format_desc)) {
  1684.          debug_printf("%s: using floating point linear filtering for %s\n",
  1685.                       __FUNCTION__, bld.format_desc->short_name);
  1686.          debug_printf("  min_img %d  mag_img %d  mip %d  wraps %d  wrapt %d\n",
  1687.                       static_sampler_state->min_img_filter,
  1688.                       static_sampler_state->mag_img_filter,
  1689.                       static_sampler_state->min_mip_filter,
  1690.                       static_sampler_state->wrap_s,
  1691.                       static_sampler_state->wrap_t);
  1692.       }
  1693.  
  1694.       lp_build_sample_common(&bld, texture_index, sampler_index,
  1695.                              &s, &t, &r,
  1696.                              derivs, lod_bias, explicit_lod,
  1697.                              &lod_ipart, &lod_fpart,
  1698.                              &ilevel0, &ilevel1);
  1699.  
  1700.       /*
  1701.        * we only try 8-wide sampling with soa as it appears to
  1702.        * be a loss with aos with AVX (but it should work).
  1703.        * (It should be faster if we'd support avx2)
  1704.        */
  1705.       if (num_quads == 1 || !use_aos) {
  1706.  
  1707.          if (num_quads > 1) {
  1708.             if (mip_filter == PIPE_TEX_MIPFILTER_NONE) {
  1709.                LLVMValueRef index0 = lp_build_const_int32(gallivm, 0);
  1710.                /*
  1711.                 * These parameters are the same for all quads,
  1712.                 * could probably simplify.
  1713.                 */
  1714.                lod_ipart = LLVMBuildExtractElement(builder, lod_ipart, index0, "");
  1715.                ilevel0 = LLVMBuildExtractElement(builder, ilevel0, index0, "");
  1716.             }
  1717.          }
  1718.          if (use_aos) {
  1719.             /* do sampling/filtering with fixed pt arithmetic */
  1720.             lp_build_sample_aos(&bld, sampler_index,
  1721.                                 s, t, r, offsets,
  1722.                                 lod_ipart, lod_fpart,
  1723.                                 ilevel0, ilevel1,
  1724.                                 texel_out);
  1725.          }
  1726.  
  1727.          else {
  1728.             lp_build_sample_general(&bld, sampler_index,
  1729.                                     s, t, r, offsets,
  1730.                                     lod_ipart, lod_fpart,
  1731.                                     ilevel0, ilevel1,
  1732.                                     texel_out);
  1733.          }
  1734.       }
  1735.       else {
  1736.          unsigned j;
  1737.          struct lp_build_sample_context bld4;
  1738.          struct lp_type type4 = type;
  1739.          unsigned i;
  1740.          LLVMValueRef texelout4[4];
  1741.          LLVMValueRef texelouttmp[4][LP_MAX_VECTOR_LENGTH/16];
  1742.  
  1743.          type4.length = 4;
  1744.  
  1745.          /* Setup our build context */
  1746.          memset(&bld4, 0, sizeof bld4);
  1747.          bld4.gallivm = bld.gallivm;
  1748.          bld4.static_texture_state = bld.static_texture_state;
  1749.          bld4.static_sampler_state = bld.static_sampler_state;
  1750.          bld4.dynamic_state = bld.dynamic_state;
  1751.          bld4.format_desc = bld.format_desc;
  1752.          bld4.dims = bld.dims;
  1753.          bld4.row_stride_array = bld.row_stride_array;
  1754.          bld4.img_stride_array = bld.img_stride_array;
  1755.          bld4.base_ptr = bld.base_ptr;
  1756.          bld4.mip_offsets = bld.mip_offsets;
  1757.          bld4.int_size = bld.int_size;
  1758.  
  1759.          bld4.vector_width = lp_type_width(type4);
  1760.  
  1761.          bld4.float_type = lp_type_float(32);
  1762.          bld4.int_type = lp_type_int(32);
  1763.          bld4.coord_type = type4;
  1764.          bld4.int_coord_type = lp_int_type(type4);
  1765.          bld4.float_size_in_type = lp_type_float(32);
  1766.          bld4.float_size_in_type.length = dims > 1 ? 4 : 1;
  1767.          bld4.int_size_in_type = lp_int_type(bld4.float_size_in_type);
  1768.          bld4.texel_type = bld.texel_type;
  1769.          bld4.texel_type.length = 4;
  1770.          bld4.levelf_type = type4;
  1771.          /* we want native vector size to be able to use our intrinsics */
  1772.          bld4.levelf_type.length = 1;
  1773.          bld4.leveli_type = lp_int_type(bld4.levelf_type);
  1774.  
  1775.          if (explicit_lod && !scalar_lod &&
  1776.              ((is_fetch && bld.static_texture_state->target != PIPE_BUFFER) ||
  1777.               (!is_fetch && mip_filter != PIPE_TEX_MIPFILTER_NONE)))
  1778.             bld4.num_lods = type4.length;
  1779.          else
  1780.             bld4.num_lods = 1;
  1781.  
  1782.          bld4.levelf_type = type4;
  1783.          /* we want native vector size to be able to use our intrinsics */
  1784.          if (bld4.num_lods != type4.length) {
  1785.             bld4.levelf_type.length = 1;
  1786.          }
  1787.          bld4.leveli_type = lp_int_type(bld4.levelf_type);
  1788.          bld4.float_size_type = bld4.float_size_in_type;
  1789.          if (bld4.num_lods > 1) {
  1790.             bld4.float_size_type.length = bld4.num_lods == type4.length ?
  1791.                                             bld4.num_lods * bld4.float_size_in_type.length :
  1792.                                             type4.length;
  1793.          }
  1794.          bld4.int_size_type = lp_int_type(bld4.float_size_type);
  1795.  
  1796.          lp_build_context_init(&bld4.float_bld, gallivm, bld4.float_type);
  1797.          lp_build_context_init(&bld4.float_vec_bld, gallivm, type4);
  1798.          lp_build_context_init(&bld4.int_bld, gallivm, bld4.int_type);
  1799.          lp_build_context_init(&bld4.coord_bld, gallivm, bld4.coord_type);
  1800.          lp_build_context_init(&bld4.int_coord_bld, gallivm, bld4.int_coord_type);
  1801.          lp_build_context_init(&bld4.int_size_in_bld, gallivm, bld4.int_size_in_type);
  1802.          lp_build_context_init(&bld4.float_size_in_bld, gallivm, bld4.float_size_in_type);
  1803.          lp_build_context_init(&bld4.int_size_bld, gallivm, bld4.int_size_type);
  1804.          lp_build_context_init(&bld4.float_size_bld, gallivm, bld4.float_size_type);
  1805.          lp_build_context_init(&bld4.texel_bld, gallivm, bld4.texel_type);
  1806.          lp_build_context_init(&bld4.levelf_bld, gallivm, bld4.levelf_type);
  1807.          lp_build_context_init(&bld4.leveli_bld, gallivm, bld4.leveli_type);
  1808.  
  1809.          for (i = 0; i < num_quads; i++) {
  1810.             LLVMValueRef s4, t4, r4;
  1811.             LLVMValueRef lod_ipart4, lod_fpart4 = NULL;
  1812.             LLVMValueRef ilevel04, ilevel14 = NULL;
  1813.             LLVMValueRef offsets4[4] = { NULL };
  1814.             unsigned num_lods = bld4.num_lods;
  1815.  
  1816.             s4 = lp_build_extract_range(gallivm, s, 4*i, 4);
  1817.             t4 = lp_build_extract_range(gallivm, t, 4*i, 4);
  1818.             r4 = lp_build_extract_range(gallivm, r, 4*i, 4);
  1819.  
  1820.             if (offsets[0]) {
  1821.                offsets4[0] = lp_build_extract_range(gallivm, offsets[0], 4*i, 4);
  1822.                if (dims > 1) {
  1823.                   offsets4[1] = lp_build_extract_range(gallivm, offsets[1], 4*i, 4);
  1824.                   if (dims > 2) {
  1825.                      offsets4[2] = lp_build_extract_range(gallivm, offsets[2], 4*i, 4);
  1826.                   }
  1827.                }
  1828.             }
  1829.             lod_ipart4 = lp_build_extract_range(gallivm, lod_ipart, num_lods * i, num_lods);
  1830.             ilevel04 = lp_build_extract_range(gallivm, ilevel0, num_lods * i, num_lods);
  1831.             if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
  1832.                ilevel14 = lp_build_extract_range(gallivm, ilevel1, num_lods * i, num_lods);
  1833.                lod_fpart4 = lp_build_extract_range(gallivm, lod_fpart, num_lods * i, num_lods);
  1834.             }
  1835.  
  1836.             if (use_aos) {
  1837.                /* do sampling/filtering with fixed pt arithmetic */
  1838.                lp_build_sample_aos(&bld4, sampler_index,
  1839.                                    s4, t4, r4, offsets4,
  1840.                                    lod_ipart4, lod_fpart4,
  1841.                                    ilevel04, ilevel14,
  1842.                                    texelout4);
  1843.             }
  1844.  
  1845.             else {
  1846.                lp_build_sample_general(&bld4, sampler_index,
  1847.                                        s4, t4, r4, offsets4,
  1848.                                        lod_ipart4, lod_fpart4,
  1849.                                        ilevel04, ilevel14,
  1850.                                        texelout4);
  1851.             }
  1852.             for (j = 0; j < 4; j++) {
  1853.                texelouttmp[j][i] = texelout4[j];
  1854.             }
  1855.          }
  1856.  
  1857.          for (j = 0; j < 4; j++) {
  1858.             texel_out[j] = lp_build_concat(gallivm, texelouttmp[j], type4, num_quads);
  1859.          }
  1860.       }
  1861.  
  1862.       lp_build_sample_compare(&bld, coords, texel_out);
  1863.    }
  1864.  
  1865.    if (static_texture_state->target != PIPE_BUFFER) {
  1866.       apply_sampler_swizzle(&bld, texel_out);
  1867.    }
  1868.  
  1869.    /*
  1870.     * texel type can be a (32bit) int/uint (for pure int formats only),
  1871.     * however we are expected to always return floats (storage is untyped).
  1872.     */
  1873.    if (!bld.texel_type.floating) {
  1874.       unsigned chan;
  1875.       for (chan = 0; chan < 4; chan++) {
  1876.          texel_out[chan] = LLVMBuildBitCast(builder, texel_out[chan],
  1877.                                             lp_build_vec_type(gallivm, type), "");
  1878.       }
  1879.    }
  1880. }
  1881.  
  1882. void
  1883. lp_build_size_query_soa(struct gallivm_state *gallivm,
  1884.                         const struct lp_static_texture_state *static_state,
  1885.                         struct lp_sampler_dynamic_state *dynamic_state,
  1886.                         struct lp_type int_type,
  1887.                         unsigned texture_unit,
  1888.                         boolean need_nr_mips,
  1889.                         LLVMValueRef explicit_lod,
  1890.                         LLVMValueRef *sizes_out)
  1891. {
  1892.    LLVMValueRef lod;
  1893.    LLVMValueRef size;
  1894.    LLVMValueRef first_level = NULL;
  1895.    int dims, i;
  1896.    boolean has_array;
  1897.    struct lp_build_context bld_int_vec;
  1898.  
  1899.    dims = texture_dims(static_state->target);
  1900.  
  1901.    switch (static_state->target) {
  1902.    case PIPE_TEXTURE_1D_ARRAY:
  1903.    case PIPE_TEXTURE_2D_ARRAY:
  1904.       has_array = TRUE;
  1905.       break;
  1906.    default:
  1907.       has_array = FALSE;
  1908.       break;
  1909.    }
  1910.  
  1911.    assert(!int_type.floating);
  1912.  
  1913.    lp_build_context_init(&bld_int_vec, gallivm, lp_type_int_vec(32, 128));
  1914.  
  1915.    if (explicit_lod) {
  1916.       /* FIXME: this needs to honor per-element lod */
  1917.       lod = LLVMBuildExtractElement(gallivm->builder, explicit_lod, lp_build_const_int32(gallivm, 0), "");
  1918.       first_level = dynamic_state->first_level(dynamic_state, gallivm, texture_unit);
  1919.       lod = lp_build_broadcast_scalar(&bld_int_vec,
  1920.                                       LLVMBuildAdd(gallivm->builder, lod, first_level, "lod"));
  1921.  
  1922.    } else {
  1923.       lod = bld_int_vec.zero;
  1924.    }
  1925.  
  1926.    if (need_nr_mips) {
  1927.       size = bld_int_vec.zero;
  1928.    }
  1929.    else {
  1930.       size = bld_int_vec.undef;
  1931.    }
  1932.  
  1933.    size = LLVMBuildInsertElement(gallivm->builder, size,
  1934.                                  dynamic_state->width(dynamic_state, gallivm, texture_unit),
  1935.                                  lp_build_const_int32(gallivm, 0), "");
  1936.  
  1937.    if (dims >= 2) {
  1938.       size = LLVMBuildInsertElement(gallivm->builder, size,
  1939.                                     dynamic_state->height(dynamic_state, gallivm, texture_unit),
  1940.                                     lp_build_const_int32(gallivm, 1), "");
  1941.    }
  1942.  
  1943.    if (dims >= 3) {
  1944.       size = LLVMBuildInsertElement(gallivm->builder, size,
  1945.                                     dynamic_state->depth(dynamic_state, gallivm, texture_unit),
  1946.                                     lp_build_const_int32(gallivm, 2), "");
  1947.    }
  1948.  
  1949.    size = lp_build_minify(&bld_int_vec, size, lod);
  1950.  
  1951.    if (has_array)
  1952.       size = LLVMBuildInsertElement(gallivm->builder, size,
  1953.                                     dynamic_state->depth(dynamic_state, gallivm, texture_unit),
  1954.                                     lp_build_const_int32(gallivm, dims), "");
  1955.  
  1956.    /*
  1957.     * XXX for out-of-bounds lod, should set size to zero vector here
  1958.     * (for dx10-style only, i.e. need_nr_mips)
  1959.     */
  1960.  
  1961.    for (i = 0; i < dims + (has_array ? 1 : 0); i++) {
  1962.       sizes_out[i] = lp_build_extract_broadcast(gallivm, bld_int_vec.type, int_type,
  1963.                                                 size,
  1964.                                                 lp_build_const_int32(gallivm, i));
  1965.    }
  1966.  
  1967.    /*
  1968.     * if there's no explicit_lod (buffers, rects) queries requiring nr of
  1969.     * mips would be illegal.
  1970.     */
  1971.    if (need_nr_mips && explicit_lod) {
  1972.       struct lp_build_context bld_int_scalar;
  1973.       LLVMValueRef num_levels;
  1974.       lp_build_context_init(&bld_int_scalar, gallivm, lp_type_int(32));
  1975.  
  1976.       if (static_state->level_zero_only) {
  1977.          num_levels = bld_int_scalar.one;
  1978.       }
  1979.       else {
  1980.          LLVMValueRef last_level;
  1981.  
  1982.          last_level = dynamic_state->last_level(dynamic_state, gallivm, texture_unit);
  1983.          num_levels = lp_build_sub(&bld_int_scalar, last_level, first_level);
  1984.          num_levels = lp_build_add(&bld_int_scalar, num_levels, bld_int_scalar.one);
  1985.       }
  1986.       sizes_out[3] = lp_build_broadcast(gallivm, lp_build_vec_type(gallivm, int_type),
  1987.                                         num_levels);
  1988.    }
  1989. }
  1990.