Home | History | Annotate | Download | only in core
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 2012-2015 LunarG, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Chia-I Wu <olv (at) lunarg.com>
     26  */
     27 
     28 #include "util/u_half.h"
     29 
     30 #include "ilo_debug.h"
     31 #include "ilo_state_surface.h"
     32 #include "ilo_state_sampler.h"
     33 
     34 static bool
     35 sampler_validate_gen6_non_normalized(const struct ilo_dev *dev,
     36                                      const struct ilo_state_sampler_info *info)
     37 {
     38    const enum gen_texcoord_mode addr_ctrls[3] = {
     39       info->tcx_ctrl, info->tcy_ctrl, info->tcz_ctrl,
     40    };
     41    int i;
     42 
     43    ILO_DEV_ASSERT(dev, 6, 8);
     44 
     45    /*
     46     * From the Ivy Bridge PRM, volume 4 part 1, page 98:
     47     *
     48     *     "The following state must be set as indicated if this field
     49     *      (Non-normalized Coordinate Enable) is enabled:
     50     *
     51     *      - TCX/Y/Z Address Control Mode must be TEXCOORDMODE_CLAMP,
     52     *        TEXCOORDMODE_HALF_BORDER, or TEXCOORDMODE_CLAMP_BORDER.
     53     *      - Surface Type must be SURFTYPE_2D or SURFTYPE_3D.
     54     *      - Mag Mode Filter must be MAPFILTER_NEAREST or
     55     *        MAPFILTER_LINEAR.
     56     *      - Min Mode Filter must be MAPFILTER_NEAREST or
     57     *        MAPFILTER_LINEAR.
     58     *      - Mip Mode Filter must be MIPFILTER_NONE.
     59     *      - Min LOD must be 0.
     60     *      - Max LOD must be 0.
     61     *      - MIP Count must be 0.
     62     *      - Surface Min LOD must be 0.
     63     *      - Texture LOD Bias must be 0."
     64     */
     65    for (i = 0; i < 3; i++) {
     66       switch (addr_ctrls[i]) {
     67       case GEN6_TEXCOORDMODE_CLAMP:
     68       case GEN6_TEXCOORDMODE_CLAMP_BORDER:
     69       case GEN8_TEXCOORDMODE_HALF_BORDER:
     70          break;
     71       default:
     72          assert(!"bad non-normalized coordinate wrap mode");
     73          break;
     74       }
     75    }
     76 
     77    assert(info->mip_filter == GEN6_MIPFILTER_NONE);
     78 
     79    assert((info->min_filter == GEN6_MAPFILTER_NEAREST ||
     80            info->min_filter == GEN6_MAPFILTER_LINEAR) &&
     81           (info->mag_filter == GEN6_MAPFILTER_NEAREST ||
     82            info->mag_filter == GEN6_MAPFILTER_LINEAR));
     83 
     84    assert(info->min_lod == 0.0f &&
     85           info->max_lod == 0.0f &&
     86           info->lod_bias == 0.0f);
     87 
     88    return true;
     89 }
     90 
     91 static bool
     92 sampler_validate_gen6_sampler(const struct ilo_dev *dev,
     93                               const struct ilo_state_sampler_info *info)
     94 {
     95    ILO_DEV_ASSERT(dev, 6, 8);
     96 
     97    if (info->non_normalized &&
     98        !sampler_validate_gen6_non_normalized(dev, info))
     99       return false;
    100 
    101    if (ilo_dev_gen(dev) < ILO_GEN(8)) {
    102        assert(info->tcx_ctrl != GEN8_TEXCOORDMODE_HALF_BORDER &&
    103               info->tcy_ctrl != GEN8_TEXCOORDMODE_HALF_BORDER &&
    104               info->tcz_ctrl != GEN8_TEXCOORDMODE_HALF_BORDER);
    105    }
    106 
    107    return true;
    108 }
    109 
    110 static uint32_t
    111 sampler_get_gen6_integer_filters(const struct ilo_dev *dev,
    112                                  const struct ilo_state_sampler_info *info)
    113 {
    114    /*
    115     * From the Sandy Bridge PRM, volume 4 part 1, page 103:
    116     *
    117     *     "MIPFILTER_LINEAR is not supported for surface formats that do not
    118     *      support "Sampling Engine Filtering" as indicated in the Surface
    119     *      Formats table unless using the sample_c message type."
    120     *
    121     *     "Only MAPFILTER_NEAREST is supported for surface formats that do not
    122     *      support "Sampling Engine Filtering" as indicated in the Surface
    123     *      Formats table unless using the sample_c message type.
    124     */
    125    const enum gen_mip_filter mip_filter =
    126       (info->mip_filter == GEN6_MIPFILTER_LINEAR) ?
    127       GEN6_MIPFILTER_NEAREST : info->mip_filter;
    128    const enum gen_map_filter min_filter = GEN6_MAPFILTER_NEAREST;
    129    const enum gen_map_filter mag_filter = GEN6_MAPFILTER_NEAREST;
    130 
    131    ILO_DEV_ASSERT(dev, 6, 8);
    132 
    133    return mip_filter << GEN6_SAMPLER_DW0_MIP_FILTER__SHIFT |
    134           mag_filter << GEN6_SAMPLER_DW0_MAG_FILTER__SHIFT |
    135           min_filter << GEN6_SAMPLER_DW0_MIN_FILTER__SHIFT;
    136 }
    137 
    138 static uint32_t
    139 sampler_get_gen6_3d_filters(const struct ilo_dev *dev,
    140                             const struct ilo_state_sampler_info *info)
    141 {
    142    const enum gen_mip_filter mip_filter = info->mip_filter;
    143    /*
    144     * From the Sandy Bridge PRM, volume 4 part 1, page 103:
    145     *
    146     *     "Only MAPFILTER_NEAREST and MAPFILTER_LINEAR are supported for
    147     *      surfaces of type SURFTYPE_3D."
    148     */
    149    const enum gen_map_filter min_filter =
    150       (info->min_filter == GEN6_MAPFILTER_NEAREST ||
    151        info->min_filter == GEN6_MAPFILTER_LINEAR) ?
    152       info->min_filter : GEN6_MAPFILTER_LINEAR;
    153    const enum gen_map_filter mag_filter =
    154       (info->mag_filter == GEN6_MAPFILTER_NEAREST ||
    155        info->mag_filter == GEN6_MAPFILTER_LINEAR) ?
    156        info->mag_filter : GEN6_MAPFILTER_LINEAR;
    157 
    158    ILO_DEV_ASSERT(dev, 6, 8);
    159 
    160    return mip_filter << GEN6_SAMPLER_DW0_MIP_FILTER__SHIFT |
    161           mag_filter << GEN6_SAMPLER_DW0_MAG_FILTER__SHIFT |
    162           min_filter << GEN6_SAMPLER_DW0_MIN_FILTER__SHIFT;
    163 }
    164 
    165 static uint32_t
    166 get_gen6_addr_controls(const struct ilo_dev *dev,
    167                        enum gen_texcoord_mode tcx_ctrl,
    168                        enum gen_texcoord_mode tcy_ctrl,
    169                        enum gen_texcoord_mode tcz_ctrl)
    170 {
    171    ILO_DEV_ASSERT(dev, 6, 8);
    172 
    173    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
    174       return tcx_ctrl << GEN7_SAMPLER_DW3_U_WRAP__SHIFT |
    175              tcy_ctrl << GEN7_SAMPLER_DW3_V_WRAP__SHIFT |
    176              tcz_ctrl << GEN7_SAMPLER_DW3_R_WRAP__SHIFT;
    177    } else {
    178       return tcx_ctrl << GEN6_SAMPLER_DW1_U_WRAP__SHIFT |
    179              tcy_ctrl << GEN6_SAMPLER_DW1_V_WRAP__SHIFT |
    180              tcz_ctrl << GEN6_SAMPLER_DW1_R_WRAP__SHIFT;
    181    }
    182 }
    183 
    184 static uint32_t
    185 sampler_get_gen6_1d_addr_controls(const struct ilo_dev *dev,
    186                                   const struct ilo_state_sampler_info *info)
    187 {
    188    const enum gen_texcoord_mode tcx_ctrl =
    189       (info->tcx_ctrl == GEN6_TEXCOORDMODE_CUBE) ?
    190       GEN6_TEXCOORDMODE_CLAMP : info->tcx_ctrl;
    191    /*
    192     * From the Ivy Bridge PRM, volume 4 part 1, page 100:
    193     *
    194     *     "If this field (TCY Address Control Mode) is set to
    195     *      TEXCOORDMODE_CLAMP_BORDER or TEXCOORDMODE_HALF_BORDER and a 1D
    196     *      surface is sampled, incorrect blending with the border color in the
    197     *      vertical direction may occur."
    198     */
    199    const enum gen_texcoord_mode tcy_ctrl = GEN6_TEXCOORDMODE_CLAMP;
    200    const enum gen_texcoord_mode tcz_ctrl = GEN6_TEXCOORDMODE_CLAMP;
    201 
    202    ILO_DEV_ASSERT(dev, 6, 8);
    203 
    204    return get_gen6_addr_controls(dev, tcx_ctrl, tcy_ctrl, tcz_ctrl);
    205 }
    206 
    207 static uint32_t
    208 sampler_get_gen6_2d_3d_addr_controls(const struct ilo_dev *dev,
    209                                      const struct ilo_state_sampler_info *info)
    210 {
    211    const enum gen_texcoord_mode tcx_ctrl =
    212       (info->tcx_ctrl == GEN6_TEXCOORDMODE_CUBE) ?
    213       GEN6_TEXCOORDMODE_CLAMP : info->tcx_ctrl;
    214    const enum gen_texcoord_mode tcy_ctrl =
    215       (info->tcy_ctrl == GEN6_TEXCOORDMODE_CUBE) ?
    216       GEN6_TEXCOORDMODE_CLAMP : info->tcy_ctrl;
    217    /*
    218     * From the Sandy Bridge PRM, volume 4 part 1, page 108:
    219     *
    220     *     "[DevSNB]: if this field (TCZ Address Control Mode) is set to
    221     *      TEXCOORDMODE_CLAMP_BORDER samples outside the map will clamp to 0
    222     *      instead of boarder color"
    223     *
    224     * From the Ivy Bridge PRM, volume 4 part 1, page 100:
    225     *
    226     *     "If this field is set to TEXCOORDMODE_CLAMP_BORDER for 3D maps on
    227     *      formats without an alpha channel, samples straddling the map in the
    228     *      Z direction may have their alpha channels off by 1."
    229     *
    230     * Do we want to do something here?
    231     */
    232    const enum gen_texcoord_mode tcz_ctrl =
    233       (info->tcz_ctrl == GEN6_TEXCOORDMODE_CUBE) ?
    234       GEN6_TEXCOORDMODE_CLAMP : info->tcz_ctrl;
    235 
    236    ILO_DEV_ASSERT(dev, 6, 8);
    237 
    238    return get_gen6_addr_controls(dev, tcx_ctrl, tcy_ctrl, tcz_ctrl);
    239 }
    240 
    241 static uint32_t
    242 sampler_get_gen6_cube_addr_controls(const struct ilo_dev *dev,
    243                                     const struct ilo_state_sampler_info *info)
    244 {
    245    /*
    246     * From the Ivy Bridge PRM, volume 4 part 1, page 99:
    247     *
    248     *     "When using cube map texture coordinates, only TEXCOORDMODE_CLAMP
    249     *      and TEXCOORDMODE_CUBE settings are valid, and each TC component
    250     *      must have the same Address Control mode.
    251     *
    252     *      When TEXCOORDMODE_CUBE is not used accessing a cube map, the map's
    253     *      Cube Face Enable field must be programmed to 111111b (all faces
    254     *      enabled)."
    255     *
    256     * From the Haswell PRM, volume 2d, page 278:
    257     *
    258     *     "When using cube map texture coordinates, each TC component must
    259     *      have the same Address Control Mode.
    260     *
    261     *      When TEXCOORDMODE_CUBE is not used accessing a cube map, the map's
    262     *      Cube Face Enable field must be programmed to 111111b (all faces
    263     *      enabled)."
    264     *
    265     * We always enable all cube faces and only need to make sure all address
    266     * control modes are the same.
    267     */
    268    const enum gen_texcoord_mode tcx_ctrl =
    269       (ilo_dev_gen(dev) >= ILO_GEN(7.5) ||
    270        info->tcx_ctrl == GEN6_TEXCOORDMODE_CUBE ||
    271        info->tcx_ctrl == GEN6_TEXCOORDMODE_CLAMP) ?
    272       info->tcx_ctrl : GEN6_TEXCOORDMODE_CLAMP;
    273    const enum gen_texcoord_mode tcy_ctrl = tcx_ctrl;
    274    const enum gen_texcoord_mode tcz_ctrl = tcx_ctrl;
    275 
    276    ILO_DEV_ASSERT(dev, 6, 8);
    277 
    278    return get_gen6_addr_controls(dev, tcx_ctrl, tcy_ctrl, tcz_ctrl);
    279 }
    280 
    281 static uint16_t
    282 get_gen6_lod_bias(const struct ilo_dev *dev, float bias)
    283 {
    284    /* [-16.0, 16.0) in S4.6 or S4.8 */
    285    const int fbits = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 8 : 6;
    286    const float max = 16.0f;
    287    const float scale = (float) (1 << fbits);
    288    const int mask = (1 << (1 + 4 + fbits)) - 1;
    289    const int scaled_max = (16 << fbits) - 1;
    290    int scaled;
    291 
    292    ILO_DEV_ASSERT(dev, 6, 8);
    293 
    294    if (bias > max)
    295       bias = max;
    296    else if (bias < -max)
    297       bias = -max;
    298 
    299    scaled = (int) (bias * scale);
    300    if (scaled > scaled_max)
    301       scaled = scaled_max;
    302 
    303    return (scaled & mask);
    304 }
    305 
    306 static uint16_t
    307 get_gen6_lod_clamp(const struct ilo_dev *dev, float clamp)
    308 {
    309    /* [0.0, 13.0] in U4.6 or [0.0, 14.0] in U4.8 */
    310    const int fbits = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 8 : 6;
    311    const float max = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 14.0f : 13.0f;
    312    const float scale = (float) (1 << fbits);
    313 
    314    ILO_DEV_ASSERT(dev, 6, 8);
    315 
    316    if (clamp > max)
    317       clamp = max;
    318    else if (clamp < 0.0f)
    319       clamp = 0.0f;
    320 
    321    return (int) (clamp * scale);
    322 }
    323 
    324 static bool
    325 sampler_set_gen6_SAMPLER_STATE(struct ilo_state_sampler *sampler,
    326                                const struct ilo_dev *dev,
    327                                const struct ilo_state_sampler_info *info)
    328 {
    329    uint16_t lod_bias, max_lod, min_lod;
    330    uint32_t dw0, dw1, dw3;
    331 
    332    ILO_DEV_ASSERT(dev, 6, 8);
    333 
    334    if (!sampler_validate_gen6_sampler(dev, info))
    335       return false;
    336 
    337    /*
    338     * From the Ivy Bridge PRM, volume 4 part 1, page 15:
    339     *
    340     *     "The per-pixel LOD is computed in an implementation-dependent manner
    341     *      and approximates the log2 of the texel/pixel ratio at the given
    342     *      pixel. The computation is typically based on the differential
    343     *      texel-space distances associated with a one-pixel differential
    344     *      distance along the screen x- and y-axes. These texel-space
    345     *      distances are computed by evaluating neighboring pixel texture
    346     *      coordinates, these coordinates being in units of texels on the base
    347     *      MIP level (multiplied by the corresponding surface size in
    348     *      texels)."
    349     *
    350     * Judging from the LOD computation pseudocode on page 16-18, the "base MIP
    351     * level" should be given by SurfMinLod.  To summarize, for the "sample"
    352     * message,
    353     *
    354     *   1) LOD is set to log2(texel/pixel ratio).  The number of texels is
    355     *      measured against level SurfMinLod.
    356     *   2) Bias is added to LOD.
    357     *   3) if pre-clamp is enabled, LOD is clamped to [MinLod, MaxLod] first
    358     *   4) LOD is compared with Base to determine whether magnification or
    359     *      minification is needed.
    360     *   5) If magnification is needed, or no mipmapping is requested, LOD is
    361     *      set to floor(MinLod).
    362     *   6) LOD is clamped to [0, MIPCnt], and SurfMinLod is added to LOD.
    363     *
    364     * As an example, we could set SurfMinLod to GL_TEXTURE_BASE_LEVEL and Base
    365     * to 0 to match GL.  But GL expects LOD to be set to 0, instead of
    366     * floor(MinLod), in 5).  Since this is only an issue when MinLod is
    367     * greater than or equal to one, and, with Base being 0, a non-zero MinLod
    368     * implies minification, we only need to deal with the case when mipmapping
    369     * is disabled.  We can thus do:
    370     *
    371     *   if (MipFilter == MIPFILTER_NONE && MinLod) {
    372     *     MinLod = 0;
    373     *     MagFilter = MinFilter;
    374     *   }
    375     */
    376 
    377    lod_bias = get_gen6_lod_bias(dev, info->lod_bias);
    378    min_lod = get_gen6_lod_clamp(dev, info->min_lod);
    379    max_lod = get_gen6_lod_clamp(dev, info->max_lod);
    380 
    381    dw0 = GEN6_SAMPLER_DW0_LOD_PRECLAMP_ENABLE |
    382          0 << GEN6_SAMPLER_DW0_BASE_LOD__SHIFT |
    383          info->mip_filter << GEN6_SAMPLER_DW0_MIP_FILTER__SHIFT |
    384          info->mag_filter << GEN6_SAMPLER_DW0_MAG_FILTER__SHIFT |
    385          info->min_filter << GEN6_SAMPLER_DW0_MIN_FILTER__SHIFT;
    386 
    387    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
    388       dw0 |= GEN7_SAMPLER_DW0_BORDER_COLOR_MODE_DX10_OGL |
    389              lod_bias << GEN7_SAMPLER_DW0_LOD_BIAS__SHIFT;
    390 
    391       if (info->min_filter == GEN6_MAPFILTER_ANISOTROPIC ||
    392           info->mag_filter == GEN6_MAPFILTER_ANISOTROPIC)
    393          dw0 |= GEN7_SAMPLER_DW0_ANISO_ALGO_EWA;
    394    } else {
    395       dw0 |= lod_bias << GEN6_SAMPLER_DW0_LOD_BIAS__SHIFT |
    396              info->shadow_func << GEN6_SAMPLER_DW0_SHADOW_FUNC__SHIFT;
    397 
    398       /*
    399        * From the Sandy Bridge PRM, volume 4 part 1, page 102:
    400        *
    401        *     "(Min and Mag State Not Equal) Must be set to 1 if any of the
    402        *      following are true:
    403        *
    404        *      - Mag Mode Filter and Min Mode Filter are not the same
    405        *      - Address Rounding Enable: U address mag filter and U address
    406        *        min filter are not the same
    407        *      - Address Rounding Enable: V address mag filter and V address
    408        *        min filter are not the same
    409        *      - Address Rounding Enable: R address mag filter and R address
    410        *        min filter are not the same"
    411        *
    412        * We set address rounding for U, V, and R uniformly.  Only need to
    413        * check the filters.
    414        */
    415       if (info->min_filter != info->mag_filter)
    416          dw0 |= GEN6_SAMPLER_DW0_MIN_MAG_NOT_EQUAL;
    417    }
    418 
    419    dw1 = 0;
    420 
    421    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
    422       /*
    423        * From the Ivy Bridge PRM, volume 4 part 1, page 96:
    424        *
    425        *     "This field (Cube Surface Control Mode) must be set to
    426        *      CUBECTRLMODE_PROGRAMMED"
    427        */
    428       dw1 |= min_lod << GEN7_SAMPLER_DW1_MIN_LOD__SHIFT |
    429              max_lod << GEN7_SAMPLER_DW1_MAX_LOD__SHIFT |
    430              info->shadow_func << GEN7_SAMPLER_DW1_SHADOW_FUNC__SHIFT |
    431              GEN7_SAMPLER_DW1_CUBECTRLMODE_PROGRAMMED;
    432    } else {
    433       dw1 |= min_lod << GEN6_SAMPLER_DW1_MIN_LOD__SHIFT |
    434              max_lod << GEN6_SAMPLER_DW1_MAX_LOD__SHIFT |
    435              GEN6_SAMPLER_DW1_CUBECTRLMODE_PROGRAMMED |
    436              info->tcx_ctrl << GEN6_SAMPLER_DW1_U_WRAP__SHIFT |
    437              info->tcy_ctrl << GEN6_SAMPLER_DW1_V_WRAP__SHIFT |
    438              info->tcz_ctrl << GEN6_SAMPLER_DW1_R_WRAP__SHIFT;
    439    }
    440 
    441    dw3 = info->max_anisotropy << GEN6_SAMPLER_DW3_MAX_ANISO__SHIFT;
    442 
    443    /* round the coordinates for linear filtering */
    444    if (info->min_filter != GEN6_MAPFILTER_NEAREST) {
    445       dw3 |= GEN6_SAMPLER_DW3_U_MIN_ROUND |
    446              GEN6_SAMPLER_DW3_V_MIN_ROUND |
    447              GEN6_SAMPLER_DW3_R_MIN_ROUND;
    448    }
    449    if (info->mag_filter != GEN6_MAPFILTER_NEAREST) {
    450       dw3 |= GEN6_SAMPLER_DW3_U_MAG_ROUND |
    451              GEN6_SAMPLER_DW3_V_MAG_ROUND |
    452              GEN6_SAMPLER_DW3_R_MAG_ROUND;
    453    }
    454 
    455    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
    456       dw3 |= GEN7_SAMPLER_DW3_TRIQUAL_FULL |
    457              info->tcx_ctrl << GEN7_SAMPLER_DW3_U_WRAP__SHIFT |
    458              info->tcy_ctrl << GEN7_SAMPLER_DW3_V_WRAP__SHIFT |
    459              info->tcz_ctrl << GEN7_SAMPLER_DW3_R_WRAP__SHIFT;
    460 
    461       if (info->non_normalized)
    462          dw3 |= GEN7_SAMPLER_DW3_NON_NORMALIZED_COORD;
    463    } else {
    464       if (info->non_normalized)
    465          dw3 |= GEN6_SAMPLER_DW3_NON_NORMALIZED_COORD;
    466    }
    467 
    468    STATIC_ASSERT(ARRAY_SIZE(sampler->sampler) >= 3);
    469    sampler->sampler[0] = dw0;
    470    sampler->sampler[1] = dw1;
    471    sampler->sampler[2] = dw3;
    472 
    473    sampler->filter_integer = sampler_get_gen6_integer_filters(dev, info);
    474    sampler->filter_3d = sampler_get_gen6_3d_filters(dev, info);
    475    sampler->addr_ctrl_1d = sampler_get_gen6_1d_addr_controls(dev, info);
    476    sampler->addr_ctrl_2d_3d = sampler_get_gen6_2d_3d_addr_controls(dev, info);
    477    sampler->addr_ctrl_cube = sampler_get_gen6_cube_addr_controls(dev, info);
    478 
    479    sampler->non_normalized = info->non_normalized;
    480 
    481    /*
    482     * From the Sandy Bridge PRM, volume 4 part 1, page 21:
    483     *
    484     *     "[DevSNB] Errata: Incorrect behavior is observed in cases where the
    485     *      min and mag mode filters are different and SurfMinLOD is nonzero.
    486     *      The determination of MagMode uses the following equation instead of
    487     *      the one in the above pseudocode:
    488     *
    489     *      MagMode = (LOD + SurfMinLOD - Base <= 0)"
    490     *
    491     * As a way to work around that, request Base to be set to SurfMinLod.
    492     */
    493    if (ilo_dev_gen(dev) == ILO_GEN(6) &&
    494        info->min_filter != info->mag_filter)
    495       sampler->base_to_surf_min_lod = true;
    496 
    497    return true;
    498 }
    499 
    500 static bool
    501 sampler_border_set_gen6_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border *border,
    502                                                    const struct ilo_dev *dev,
    503                                                    const struct ilo_state_sampler_border_info *info)
    504 {
    505    uint32_t dw[12];
    506    float rgba[4];
    507 
    508    /*
    509     * From the Ivy Bridge PRM, volume 4 part 1, page 117:
    510     *
    511     *     "For ([DevSNB]), if border color is used, all formats must be
    512     *      provided.  Hardware will choose the appropriate format based on
    513     *      Surface Format and Texture Border Color Mode. The values
    514     *      represented by each format should be the same (other than being
    515     *      subject to range-based clamping and precision) to avoid unexpected
    516     *      behavior."
    517     *
    518     * XXX We do not honor info->is_integer yet.
    519     */
    520 
    521    ILO_DEV_ASSERT(dev, 6, 6);
    522 
    523    /* make a copy so that we can clamp for SNORM and UNORM */
    524    memcpy(rgba, info->rgba.f, sizeof(rgba));
    525 
    526    /* IEEE_FP */
    527    dw[1] = fui(rgba[0]);
    528    dw[2] = fui(rgba[1]);
    529    dw[3] = fui(rgba[2]);
    530    dw[4] = fui(rgba[3]);
    531 
    532    /* FLOAT_16 */
    533    dw[5] = util_float_to_half(rgba[0]) |
    534            util_float_to_half(rgba[1]) << 16;
    535    dw[6] = util_float_to_half(rgba[2]) |
    536            util_float_to_half(rgba[3]) << 16;
    537 
    538    /* clamp to [-1.0f, 1.0f] */
    539    rgba[0] = CLAMP(rgba[0], -1.0f, 1.0f);
    540    rgba[1] = CLAMP(rgba[1], -1.0f, 1.0f);
    541    rgba[2] = CLAMP(rgba[2], -1.0f, 1.0f);
    542    rgba[3] = CLAMP(rgba[3], -1.0f, 1.0f);
    543 
    544    /* SNORM16 */
    545    dw[9] =  (int16_t) util_iround(rgba[0] * 32767.0f) |
    546             (int16_t) util_iround(rgba[1] * 32767.0f) << 16;
    547    dw[10] = (int16_t) util_iround(rgba[2] * 32767.0f) |
    548             (int16_t) util_iround(rgba[3] * 32767.0f) << 16;
    549 
    550    /* SNORM8 */
    551    dw[11] = (int8_t) util_iround(rgba[0] * 127.0f) |
    552             (int8_t) util_iround(rgba[1] * 127.0f) << 8 |
    553             (int8_t) util_iround(rgba[2] * 127.0f) << 16 |
    554             (int8_t) util_iround(rgba[3] * 127.0f) << 24;
    555 
    556    /* clamp to [0.0f, 1.0f] */
    557    rgba[0] = CLAMP(rgba[0], 0.0f, 1.0f);
    558    rgba[1] = CLAMP(rgba[1], 0.0f, 1.0f);
    559    rgba[2] = CLAMP(rgba[2], 0.0f, 1.0f);
    560    rgba[3] = CLAMP(rgba[3], 0.0f, 1.0f);
    561 
    562    /* UNORM8 */
    563    dw[0] = (uint8_t) util_iround(rgba[0] * 255.0f) |
    564            (uint8_t) util_iround(rgba[1] * 255.0f) << 8 |
    565            (uint8_t) util_iround(rgba[2] * 255.0f) << 16 |
    566            (uint8_t) util_iround(rgba[3] * 255.0f) << 24;
    567 
    568    /* UNORM16 */
    569    dw[7] = (uint16_t) util_iround(rgba[0] * 65535.0f) |
    570            (uint16_t) util_iround(rgba[1] * 65535.0f) << 16;
    571    dw[8] = (uint16_t) util_iround(rgba[2] * 65535.0f) |
    572            (uint16_t) util_iround(rgba[3] * 65535.0f) << 16;
    573 
    574    STATIC_ASSERT(ARRAY_SIZE(border->color) >= 12);
    575    memcpy(border->color, dw, sizeof(dw));
    576 
    577    return true;
    578 }
    579 
    580 static bool
    581 sampler_border_set_gen7_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border *border,
    582                                                    const struct ilo_dev *dev,
    583                                                    const struct ilo_state_sampler_border_info *info)
    584 {
    585    ILO_DEV_ASSERT(dev, 7, 8);
    586 
    587    /*
    588     * From the Ivy Bridge PRM, volume 4 part 1, page 116:
    589     *
    590     *     "In DX10/OGL mode, the format of the border color is
    591     *      R32G32B32A32_FLOAT, regardless of the surface format chosen."
    592     *
    593     * From the Haswell PRM, volume 2d, page 240:
    594     *
    595     *     "So, SW will have to program the table in SAMPLER_BORDER_COLOR_STATE
    596     *      at offsets DWORD16 to 19, as per the integer surface format type."
    597     *
    598     * From the Broadwell PRM, volume 2d, page 297:
    599     *
    600     *     "DX10/OGL mode: the format of the border color depends on the format
    601     *      of the surface being sampled. If the map format is UINT, then the
    602     *      border color format is R32G32B32A32_UINT. If the map format is
    603     *      SINT, then the border color format is R32G32B32A32_SINT. Otherwise,
    604     *      the border color format is R32G32B32A32_FLOAT."
    605     *
    606     * XXX every Gen is different
    607     */
    608 
    609    STATIC_ASSERT(ARRAY_SIZE(border->color) >= 4);
    610    memcpy(border->color, info->rgba.f, sizeof(info->rgba.f));
    611 
    612    return true;
    613 }
    614 
    615 bool
    616 ilo_state_sampler_init(struct ilo_state_sampler *sampler,
    617                        const struct ilo_dev *dev,
    618                        const struct ilo_state_sampler_info *info)
    619 {
    620    bool ret = true;
    621 
    622    assert(ilo_is_zeroed(sampler, sizeof(*sampler)));
    623 
    624    ret &= sampler_set_gen6_SAMPLER_STATE(sampler, dev, info);
    625 
    626    assert(ret);
    627 
    628    return ret;
    629 }
    630 
    631 bool
    632 ilo_state_sampler_init_disabled(struct ilo_state_sampler *sampler,
    633                                 const struct ilo_dev *dev)
    634 {
    635    ILO_DEV_ASSERT(dev, 6, 8);
    636 
    637    assert(ilo_is_zeroed(sampler, sizeof(*sampler)));
    638 
    639    sampler->sampler[0] = GEN6_SAMPLER_DW0_DISABLE;
    640    sampler->sampler[1] = 0;
    641    sampler->sampler[2] = 0;
    642 
    643    return true;
    644 }
    645 
    646 /**
    647  * Modify \p sampler to work with \p surf.  There will be loss of information.
    648  * Callers should make a copy of the orignal sampler first.
    649  */
    650 bool
    651 ilo_state_sampler_set_surface(struct ilo_state_sampler *sampler,
    652                               const struct ilo_dev *dev,
    653                               const struct ilo_state_surface *surf)
    654 {
    655    uint32_t addr_ctrl;
    656 
    657    ILO_DEV_ASSERT(dev, 6, 8);
    658 
    659    if (sampler->non_normalized) {
    660       /* see sampler_validate_gen6_non_normalized() */
    661       assert(surf->type == GEN6_SURFTYPE_2D ||
    662              surf->type == GEN6_SURFTYPE_3D);
    663       assert(!surf->min_lod && !surf->mip_count);
    664    }
    665 
    666    if (sampler->base_to_surf_min_lod) {
    667       const uint8_t base = surf->min_lod << GEN6_SAMPLER_DW0_BASE_LOD__RADIX;
    668 
    669       sampler->sampler[0] =
    670          (sampler->sampler[0] & ~GEN6_SAMPLER_DW0_BASE_LOD__MASK) |
    671          base << GEN6_SAMPLER_DW0_BASE_LOD__SHIFT;
    672    }
    673 
    674    if (surf->is_integer || surf->type == GEN6_SURFTYPE_3D) {
    675       const uint32_t mask = (GEN6_SAMPLER_DW0_MIP_FILTER__MASK |
    676                              GEN6_SAMPLER_DW0_MIN_FILTER__MASK |
    677                              GEN6_SAMPLER_DW0_MAG_FILTER__MASK);
    678       const uint32_t filter = (surf->is_integer) ?
    679          sampler->filter_integer : sampler->filter_3d;
    680 
    681       assert((filter & mask) == filter);
    682       sampler->sampler[0] = (sampler->sampler[0] & ~mask) |
    683                             filter;
    684    }
    685 
    686    switch (surf->type) {
    687    case GEN6_SURFTYPE_1D:
    688       addr_ctrl = sampler->addr_ctrl_1d;
    689       break;
    690    case GEN6_SURFTYPE_2D:
    691    case GEN6_SURFTYPE_3D:
    692       addr_ctrl = sampler->addr_ctrl_2d_3d;
    693       break;
    694    case GEN6_SURFTYPE_CUBE:
    695       addr_ctrl = sampler->addr_ctrl_cube;
    696       break;
    697    default:
    698       assert(!"unexpected surface type");
    699       addr_ctrl = 0;
    700       break;
    701    }
    702 
    703    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
    704       const uint32_t mask = (GEN7_SAMPLER_DW3_U_WRAP__MASK |
    705                              GEN7_SAMPLER_DW3_V_WRAP__MASK |
    706                              GEN7_SAMPLER_DW3_R_WRAP__MASK);
    707 
    708       assert((addr_ctrl & mask) == addr_ctrl);
    709       sampler->sampler[2] = (sampler->sampler[2] & ~mask) |
    710                             addr_ctrl;
    711    } else {
    712       const uint32_t mask = (GEN6_SAMPLER_DW1_U_WRAP__MASK |
    713                              GEN6_SAMPLER_DW1_V_WRAP__MASK |
    714                              GEN6_SAMPLER_DW1_R_WRAP__MASK);
    715 
    716       assert((addr_ctrl & mask) == addr_ctrl);
    717       sampler->sampler[1] = (sampler->sampler[1] & ~mask) |
    718                             addr_ctrl;
    719    }
    720 
    721    return true;
    722 }
    723 
    724 bool
    725 ilo_state_sampler_border_init(struct ilo_state_sampler_border *border,
    726                               const struct ilo_dev *dev,
    727                               const struct ilo_state_sampler_border_info *info)
    728 {
    729    bool ret = true;
    730 
    731    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
    732       ret &= sampler_border_set_gen7_SAMPLER_BORDER_COLOR_STATE(border,
    733             dev, info);
    734    } else {
    735       ret &= sampler_border_set_gen6_SAMPLER_BORDER_COLOR_STATE(border,
    736             dev, info);
    737    }
    738 
    739    assert(ret);
    740 
    741    return ret;
    742 }
    743