• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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
sampler_validate_gen6_non_normalized(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)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
sampler_validate_gen6_sampler(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)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
sampler_get_gen6_integer_filters(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)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
sampler_get_gen6_3d_filters(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)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
get_gen6_addr_controls(const struct ilo_dev * dev,enum gen_texcoord_mode tcx_ctrl,enum gen_texcoord_mode tcy_ctrl,enum gen_texcoord_mode tcz_ctrl)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
sampler_get_gen6_1d_addr_controls(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)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
sampler_get_gen6_2d_3d_addr_controls(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)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
sampler_get_gen6_cube_addr_controls(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)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
get_gen6_lod_bias(const struct ilo_dev * dev,float bias)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
get_gen6_lod_clamp(const struct ilo_dev * dev,float clamp)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
sampler_set_gen6_SAMPLER_STATE(struct ilo_state_sampler * sampler,const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)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
sampler_border_set_gen6_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border * border,const struct ilo_dev * dev,const struct ilo_state_sampler_border_info * info)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
sampler_border_set_gen7_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border * border,const struct ilo_dev * dev,const struct ilo_state_sampler_border_info * info)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
ilo_state_sampler_init(struct ilo_state_sampler * sampler,const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)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
ilo_state_sampler_init_disabled(struct ilo_state_sampler * sampler,const struct ilo_dev * dev)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
ilo_state_sampler_set_surface(struct ilo_state_sampler * sampler,const struct ilo_dev * dev,const struct ilo_state_surface * surf)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
ilo_state_sampler_border_init(struct ilo_state_sampler_border * border,const struct ilo_dev * dev,const struct ilo_state_sampler_border_info * info)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