2 * Mesa 3-D graphics library
4 * Copyright (C) 2012-2015 LunarG, Inc.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
25 * Chia-I Wu <olv@lunarg.com>
28 #include "util/u_half.h"
30 #include "ilo_debug.h"
31 #include "ilo_state_surface.h"
32 #include "ilo_state_sampler.h"
35 sampler_validate_gen6_non_normalized(const struct ilo_dev
*dev
,
36 const struct ilo_state_sampler_info
*info
)
38 const enum gen_texcoord_mode addr_ctrls
[3] = {
39 info
->tcx_ctrl
, info
->tcy_ctrl
, info
->tcz_ctrl
,
43 ILO_DEV_ASSERT(dev
, 6, 8);
46 * From the Ivy Bridge PRM, volume 4 part 1, page 98:
48 * "The following state must be set as indicated if this field
49 * (Non-normalized Coordinate Enable) is enabled:
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
56 * - Min Mode Filter must be MAPFILTER_NEAREST or
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."
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
:
72 assert(!"bad non-normalized coordinate wrap mode");
77 assert(info
->mip_filter
== GEN6_MIPFILTER_NONE
);
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
));
84 assert(info
->min_lod
== 0.0f
&&
85 info
->max_lod
== 0.0f
&&
86 info
->lod_bias
== 0.0f
);
92 sampler_validate_gen6_sampler(const struct ilo_dev
*dev
,
93 const struct ilo_state_sampler_info
*info
)
95 ILO_DEV_ASSERT(dev
, 6, 8);
97 if (info
->non_normalized
&&
98 !sampler_validate_gen6_non_normalized(dev
, info
))
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
);
111 sampler_get_gen6_integer_filters(const struct ilo_dev
*dev
,
112 const struct ilo_state_sampler_info
*info
)
115 * From the Sandy Bridge PRM, volume 4 part 1, page 103:
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."
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.
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
;
131 ILO_DEV_ASSERT(dev
, 6, 8);
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
;
139 sampler_get_gen6_3d_filters(const struct ilo_dev
*dev
,
140 const struct ilo_state_sampler_info
*info
)
142 const enum gen_mip_filter mip_filter
= info
->mip_filter
;
144 * From the Sandy Bridge PRM, volume 4 part 1, page 103:
146 * "Only MAPFILTER_NEAREST and MAPFILTER_LINEAR are supported for
147 * surfaces of type SURFTYPE_3D."
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
;
158 ILO_DEV_ASSERT(dev
, 6, 8);
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
;
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
)
171 ILO_DEV_ASSERT(dev
, 6, 8);
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
;
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
;
185 sampler_get_gen6_1d_addr_controls(const struct ilo_dev
*dev
,
186 const struct ilo_state_sampler_info
*info
)
188 const enum gen_texcoord_mode tcx_ctrl
=
189 (info
->tcx_ctrl
== GEN6_TEXCOORDMODE_CUBE
) ?
190 GEN6_TEXCOORDMODE_CLAMP
: info
->tcx_ctrl
;
192 * From the Ivy Bridge PRM, volume 4 part 1, page 100:
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."
199 const enum gen_texcoord_mode tcy_ctrl
= GEN6_TEXCOORDMODE_CLAMP
;
200 const enum gen_texcoord_mode tcz_ctrl
= GEN6_TEXCOORDMODE_CLAMP
;
202 ILO_DEV_ASSERT(dev
, 6, 8);
204 return get_gen6_addr_controls(dev
, tcx_ctrl
, tcy_ctrl
, tcz_ctrl
);
208 sampler_get_gen6_2d_3d_addr_controls(const struct ilo_dev
*dev
,
209 const struct ilo_state_sampler_info
*info
)
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
;
218 * From the Sandy Bridge PRM, volume 4 part 1, page 108:
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"
224 * From the Ivy Bridge PRM, volume 4 part 1, page 100:
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."
230 * Do we want to do something here?
232 const enum gen_texcoord_mode tcz_ctrl
=
233 (info
->tcz_ctrl
== GEN6_TEXCOORDMODE_CUBE
) ?
234 GEN6_TEXCOORDMODE_CLAMP
: info
->tcz_ctrl
;
236 ILO_DEV_ASSERT(dev
, 6, 8);
238 return get_gen6_addr_controls(dev
, tcx_ctrl
, tcy_ctrl
, tcz_ctrl
);
242 sampler_get_gen6_cube_addr_controls(const struct ilo_dev
*dev
,
243 const struct ilo_state_sampler_info
*info
)
246 * From the Ivy Bridge PRM, volume 4 part 1, page 99:
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.
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
256 * From the Haswell PRM, volume 2d, page 278:
258 * "When using cube map texture coordinates, each TC component must
259 * have the same Address Control Mode.
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
265 * We always enable all cube faces and only need to make sure all address
266 * control modes are the same.
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
;
276 ILO_DEV_ASSERT(dev
, 6, 8);
278 return get_gen6_addr_controls(dev
, tcx_ctrl
, tcy_ctrl
, tcz_ctrl
);
282 get_gen6_lod_bias(const struct ilo_dev
*dev
, float bias
)
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;
292 ILO_DEV_ASSERT(dev
, 6, 8);
296 else if (bias
< -max
)
299 scaled
= (int) (bias
* scale
);
300 if (scaled
> scaled_max
)
303 return (scaled
& mask
);
307 get_gen6_lod_clamp(const struct ilo_dev
*dev
, float clamp
)
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
);
314 ILO_DEV_ASSERT(dev
, 6, 8);
318 else if (clamp
< 0.0f
)
321 return (int) (clamp
* scale
);
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
)
329 uint16_t lod_bias
, max_lod
, min_lod
;
330 uint32_t dw0
, dw1
, dw3
;
332 ILO_DEV_ASSERT(dev
, 6, 8);
334 if (!sampler_validate_gen6_sampler(dev
, info
))
338 * From the Ivy Bridge PRM, volume 4 part 1, page 15:
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
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"
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.
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:
371 * if (MipFilter == MIPFILTER_NONE && MinLod) {
373 * MagFilter = MinFilter;
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
);
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
;
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
;
391 if (info
->min_filter
== GEN6_MAPFILTER_ANISOTROPIC
||
392 info
->mag_filter
== GEN6_MAPFILTER_ANISOTROPIC
)
393 dw0
|= GEN7_SAMPLER_DW0_ANISO_ALGO_EWA
;
395 dw0
|= lod_bias
<< GEN6_SAMPLER_DW0_LOD_BIAS__SHIFT
|
396 info
->shadow_func
<< GEN6_SAMPLER_DW0_SHADOW_FUNC__SHIFT
;
399 * From the Sandy Bridge PRM, volume 4 part 1, page 102:
401 * "(Min and Mag State Not Equal) Must be set to 1 if any of the
402 * following are true:
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"
412 * We set address rounding for U, V, and R uniformly. Only need to
415 if (info
->min_filter
!= info
->mag_filter
)
416 dw0
|= GEN6_SAMPLER_DW0_MIN_MAG_NOT_EQUAL
;
421 if (ilo_dev_gen(dev
) >= ILO_GEN(7)) {
423 * From the Ivy Bridge PRM, volume 4 part 1, page 96:
425 * "This field (Cube Surface Control Mode) must be set to
426 * CUBECTRLMODE_PROGRAMMED"
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
;
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
;
441 dw3
= info
->max_anisotropy
<< GEN6_SAMPLER_DW3_MAX_ANISO__SHIFT
;
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
;
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
;
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
;
461 if (info
->non_normalized
)
462 dw3
|= GEN7_SAMPLER_DW3_NON_NORMALIZED_COORD
;
464 if (info
->non_normalized
)
465 dw3
|= GEN6_SAMPLER_DW3_NON_NORMALIZED_COORD
;
468 STATIC_ASSERT(ARRAY_SIZE(sampler
->sampler
) >= 3);
469 sampler
->sampler
[0] = dw0
;
470 sampler
->sampler
[1] = dw1
;
471 sampler
->sampler
[2] = dw3
;
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
);
479 sampler
->non_normalized
= info
->non_normalized
;
482 * From the Sandy Bridge PRM, volume 4 part 1, page 21:
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:
489 * MagMode = (LOD + SurfMinLOD - Base <= 0)"
491 * As a way to work around that, request Base to be set to SurfMinLod.
493 if (ilo_dev_gen(dev
) == ILO_GEN(6) &&
494 info
->min_filter
!= info
->mag_filter
)
495 sampler
->base_to_surf_min_lod
= true;
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
)
509 * From the Ivy Bridge PRM, volume 4 part 1, page 117:
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
518 * XXX We do not honor info->is_integer yet.
521 ILO_DEV_ASSERT(dev
, 6, 6);
523 /* make a copy so that we can clamp for SNORM and UNORM */
524 memcpy(rgba
, info
->rgba
.f
, sizeof(rgba
));
527 dw
[1] = fui(rgba
[0]);
528 dw
[2] = fui(rgba
[1]);
529 dw
[3] = fui(rgba
[2]);
530 dw
[4] = fui(rgba
[3]);
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;
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
);
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;
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;
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
);
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;
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;
574 STATIC_ASSERT(ARRAY_SIZE(border
->color
) >= 12);
575 memcpy(border
->color
, dw
, sizeof(dw
));
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
)
585 ILO_DEV_ASSERT(dev
, 7, 8);
588 * From the Ivy Bridge PRM, volume 4 part 1, page 116:
590 * "In DX10/OGL mode, the format of the border color is
591 * R32G32B32A32_FLOAT, regardless of the surface format chosen."
593 * From the Haswell PRM, volume 2d, page 240:
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."
598 * From the Broadwell PRM, volume 2d, page 297:
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."
606 * XXX every Gen is different
609 STATIC_ASSERT(ARRAY_SIZE(border
->color
) >= 4);
610 memcpy(border
->color
, info
->rgba
.f
, sizeof(info
->rgba
.f
));
616 ilo_state_sampler_init(struct ilo_state_sampler
*sampler
,
617 const struct ilo_dev
*dev
,
618 const struct ilo_state_sampler_info
*info
)
622 assert(ilo_is_zeroed(sampler
, sizeof(*sampler
)));
624 ret
&= sampler_set_gen6_SAMPLER_STATE(sampler
, dev
, info
);
632 ilo_state_sampler_init_disabled(struct ilo_state_sampler
*sampler
,
633 const struct ilo_dev
*dev
)
635 ILO_DEV_ASSERT(dev
, 6, 8);
637 assert(ilo_is_zeroed(sampler
, sizeof(*sampler
)));
639 sampler
->sampler
[0] = GEN6_SAMPLER_DW0_DISABLE
;
640 sampler
->sampler
[1] = 0;
641 sampler
->sampler
[2] = 0;
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.
651 ilo_state_sampler_set_surface(struct ilo_state_sampler
*sampler
,
652 const struct ilo_dev
*dev
,
653 const struct ilo_state_surface
*surf
)
657 ILO_DEV_ASSERT(dev
, 6, 8);
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
);
666 if (sampler
->base_to_surf_min_lod
) {
667 const uint8_t base
= surf
->min_lod
<< GEN6_SAMPLER_DW0_BASE_LOD__RADIX
;
669 sampler
->sampler
[0] =
670 (sampler
->sampler
[0] & ~GEN6_SAMPLER_DW0_BASE_LOD__MASK
) |
671 base
<< GEN6_SAMPLER_DW0_BASE_LOD__SHIFT
;
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
;
681 assert((filter
& mask
) == filter
);
682 sampler
->sampler
[0] = (sampler
->sampler
[0] & ~mask
) |
686 switch (surf
->type
) {
687 case GEN6_SURFTYPE_1D
:
688 addr_ctrl
= sampler
->addr_ctrl_1d
;
690 case GEN6_SURFTYPE_2D
:
691 case GEN6_SURFTYPE_3D
:
692 addr_ctrl
= sampler
->addr_ctrl_2d_3d
;
694 case GEN6_SURFTYPE_CUBE
:
695 addr_ctrl
= sampler
->addr_ctrl_cube
;
698 assert(!"unexpected surface type");
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
);
708 assert((addr_ctrl
& mask
) == addr_ctrl
);
709 sampler
->sampler
[2] = (sampler
->sampler
[2] & ~mask
) |
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
);
716 assert((addr_ctrl
& mask
) == addr_ctrl
);
717 sampler
->sampler
[1] = (sampler
->sampler
[1] & ~mask
) |
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
)
731 if (ilo_dev_gen(dev
) >= ILO_GEN(7)) {
732 ret
&= sampler_border_set_gen7_SAMPLER_BORDER_COLOR_STATE(border
,
735 ret
&= sampler_border_set_gen6_SAMPLER_BORDER_COLOR_STATE(border
,