2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics to
4 develop this 3D driver.
6 Permission is hereby granted, free of charge, to any person obtaining
7 a 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, sublicense, 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:
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial
16 portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **********************************************************************/
29 * Keith Whitwell <keithw@vmware.com>
33 * @file brw_sampler_state.c
35 * This file contains code for emitting SAMPLER_STATE structures, which
36 * specifies filter modes, wrap modes, border color, and so on.
39 #include "brw_context.h"
40 #include "brw_state.h"
41 #include "brw_defines.h"
42 #include "intel_batchbuffer.h"
43 #include "intel_mipmap_tree.h"
45 #include "main/macros.h"
46 #include "main/samplerobj.h"
49 * Emit a 3DSTATE_SAMPLER_STATE_POINTERS_{VS,HS,GS,DS,PS} packet.
52 gen7_emit_sampler_state_pointers_xs(struct brw_context
*brw
,
53 struct brw_stage_state
*stage_state
)
55 static const uint16_t packet_headers
[] = {
56 [MESA_SHADER_VERTEX
] = _3DSTATE_SAMPLER_STATE_POINTERS_VS
,
57 [MESA_SHADER_GEOMETRY
] = _3DSTATE_SAMPLER_STATE_POINTERS_GS
,
58 [MESA_SHADER_FRAGMENT
] = _3DSTATE_SAMPLER_STATE_POINTERS_PS
,
61 /* Ivybridge requires a workaround flush before VS packets. */
62 if (brw
->gen
== 7 && !brw
->is_haswell
&& !brw
->is_baytrail
&&
63 stage_state
->stage
== MESA_SHADER_VERTEX
) {
64 gen7_emit_vs_workaround_flush(brw
);
68 OUT_BATCH(packet_headers
[stage_state
->stage
] << 16 | (2 - 2));
69 OUT_BATCH(stage_state
->sampler_offset
);
74 translate_wrap_mode(struct brw_context
*brw
, GLenum wrap
, bool using_nearest
)
78 return BRW_TEXCOORDMODE_WRAP
;
80 /* GL_CLAMP is the weird mode where coordinates are clamped to
81 * [0.0, 1.0], so linear filtering of coordinates outside of
82 * [0.0, 1.0] give you half edge texel value and half border
85 * Gen8+ supports this natively.
88 return GEN8_TEXCOORDMODE_HALF_BORDER
;
90 /* On Gen4-7.5, we clamp the coordinates in the fragment shader
91 * and set clamp_border here, which gets the result desired.
92 * We just use clamp(_to_edge) for nearest, because for nearest
93 * clamping to 1.0 gives border color instead of the desired
97 return BRW_TEXCOORDMODE_CLAMP
;
99 return BRW_TEXCOORDMODE_CLAMP_BORDER
;
100 case GL_CLAMP_TO_EDGE
:
101 return BRW_TEXCOORDMODE_CLAMP
;
102 case GL_CLAMP_TO_BORDER
:
103 return BRW_TEXCOORDMODE_CLAMP_BORDER
;
104 case GL_MIRRORED_REPEAT
:
105 return BRW_TEXCOORDMODE_MIRROR
;
106 case GL_MIRROR_CLAMP_TO_EDGE
:
107 return BRW_TEXCOORDMODE_MIRROR_ONCE
;
109 return BRW_TEXCOORDMODE_WRAP
;
114 * Upload SAMPLER_BORDER_COLOR_STATE.
117 upload_default_color(struct brw_context
*brw
,
118 struct gl_sampler_object
*sampler
,
120 uint32_t *sdc_offset
)
122 struct gl_context
*ctx
= &brw
->ctx
;
123 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
124 struct gl_texture_object
*texObj
= texUnit
->_Current
;
125 struct gl_texture_image
*firstImage
= texObj
->Image
[0][texObj
->BaseLevel
];
128 switch (firstImage
->_BaseFormat
) {
129 case GL_DEPTH_COMPONENT
:
130 /* GL specs that border color for depth textures is taken from the
131 * R channel, while the hardware uses A. Spam R into all the
132 * channels for safety.
134 color
[0] = sampler
->BorderColor
.f
[0];
135 color
[1] = sampler
->BorderColor
.f
[0];
136 color
[2] = sampler
->BorderColor
.f
[0];
137 color
[3] = sampler
->BorderColor
.f
[0];
143 color
[3] = sampler
->BorderColor
.f
[3];
146 color
[0] = sampler
->BorderColor
.f
[0];
147 color
[1] = sampler
->BorderColor
.f
[0];
148 color
[2] = sampler
->BorderColor
.f
[0];
149 color
[3] = sampler
->BorderColor
.f
[0];
152 color
[0] = sampler
->BorderColor
.f
[0];
153 color
[1] = sampler
->BorderColor
.f
[0];
154 color
[2] = sampler
->BorderColor
.f
[0];
157 case GL_LUMINANCE_ALPHA
:
158 color
[0] = sampler
->BorderColor
.f
[0];
159 color
[1] = sampler
->BorderColor
.f
[0];
160 color
[2] = sampler
->BorderColor
.f
[0];
161 color
[3] = sampler
->BorderColor
.f
[3];
164 color
[0] = sampler
->BorderColor
.f
[0];
165 color
[1] = sampler
->BorderColor
.f
[1];
166 color
[2] = sampler
->BorderColor
.f
[2];
167 color
[3] = sampler
->BorderColor
.f
[3];
171 /* In some cases we use an RGBA surface format for GL RGB textures,
172 * where we've initialized the A channel to 1.0. We also have to set
173 * the border color alpha to 1.0 in that case.
175 if (firstImage
->_BaseFormat
== GL_RGB
)
179 /* On Broadwell, the border color is represented as four 32-bit floats,
180 * integers, or unsigned values, interpreted according to the surface
181 * format. This matches the sampler->BorderColor union exactly. Since
182 * we use floats both here and in the above reswizzling code, we preserve
183 * the original bit pattern. So we actually handle all three formats.
185 float *sdc
= brw_state_batch(brw
, AUB_TRACE_SAMPLER_DEFAULT_COLOR
,
186 4 * 4, 64, sdc_offset
);
187 COPY_4FV(sdc
, color
);
188 } else if (brw
->gen
== 5 || brw
->gen
== 6) {
189 struct gen5_sampler_default_color
*sdc
;
191 sdc
= brw_state_batch(brw
, AUB_TRACE_SAMPLER_DEFAULT_COLOR
,
192 sizeof(*sdc
), 32, sdc_offset
);
194 memset(sdc
, 0, sizeof(*sdc
));
196 UNCLAMPED_FLOAT_TO_UBYTE(sdc
->ub
[0], color
[0]);
197 UNCLAMPED_FLOAT_TO_UBYTE(sdc
->ub
[1], color
[1]);
198 UNCLAMPED_FLOAT_TO_UBYTE(sdc
->ub
[2], color
[2]);
199 UNCLAMPED_FLOAT_TO_UBYTE(sdc
->ub
[3], color
[3]);
201 UNCLAMPED_FLOAT_TO_USHORT(sdc
->us
[0], color
[0]);
202 UNCLAMPED_FLOAT_TO_USHORT(sdc
->us
[1], color
[1]);
203 UNCLAMPED_FLOAT_TO_USHORT(sdc
->us
[2], color
[2]);
204 UNCLAMPED_FLOAT_TO_USHORT(sdc
->us
[3], color
[3]);
206 UNCLAMPED_FLOAT_TO_SHORT(sdc
->s
[0], color
[0]);
207 UNCLAMPED_FLOAT_TO_SHORT(sdc
->s
[1], color
[1]);
208 UNCLAMPED_FLOAT_TO_SHORT(sdc
->s
[2], color
[2]);
209 UNCLAMPED_FLOAT_TO_SHORT(sdc
->s
[3], color
[3]);
211 sdc
->hf
[0] = _mesa_float_to_half(color
[0]);
212 sdc
->hf
[1] = _mesa_float_to_half(color
[1]);
213 sdc
->hf
[2] = _mesa_float_to_half(color
[2]);
214 sdc
->hf
[3] = _mesa_float_to_half(color
[3]);
216 sdc
->b
[0] = sdc
->s
[0] >> 8;
217 sdc
->b
[1] = sdc
->s
[1] >> 8;
218 sdc
->b
[2] = sdc
->s
[2] >> 8;
219 sdc
->b
[3] = sdc
->s
[3] >> 8;
221 sdc
->f
[0] = color
[0];
222 sdc
->f
[1] = color
[1];
223 sdc
->f
[2] = color
[2];
224 sdc
->f
[3] = color
[3];
226 float *sdc
= brw_state_batch(brw
, AUB_TRACE_SAMPLER_DEFAULT_COLOR
,
227 4 * 4, 32, sdc_offset
);
228 memcpy(sdc
, color
, 4 * 4);
233 * Sets the sampler state for a single unit based off of the sampler key
237 brw_update_sampler_state(struct brw_context
*brw
,
239 struct brw_sampler_state
*sampler
,
240 uint32_t batch_offset_for_sampler_state
)
242 struct gl_context
*ctx
= &brw
->ctx
;
243 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
244 struct gl_texture_object
*texObj
= texUnit
->_Current
;
245 struct gl_sampler_object
*gl_sampler
= _mesa_get_samplerobj(ctx
, unit
);
246 bool using_nearest
= false;
248 /* These don't use samplers at all. */
249 if (texObj
->Target
== GL_TEXTURE_BUFFER
)
252 switch (gl_sampler
->MinFilter
) {
254 sampler
->ss0
.min_filter
= BRW_MAPFILTER_NEAREST
;
255 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_NONE
;
256 using_nearest
= true;
259 sampler
->ss0
.min_filter
= BRW_MAPFILTER_LINEAR
;
260 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_NONE
;
262 case GL_NEAREST_MIPMAP_NEAREST
:
263 sampler
->ss0
.min_filter
= BRW_MAPFILTER_NEAREST
;
264 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_NEAREST
;
266 case GL_LINEAR_MIPMAP_NEAREST
:
267 sampler
->ss0
.min_filter
= BRW_MAPFILTER_LINEAR
;
268 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_NEAREST
;
270 case GL_NEAREST_MIPMAP_LINEAR
:
271 sampler
->ss0
.min_filter
= BRW_MAPFILTER_NEAREST
;
272 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_LINEAR
;
274 case GL_LINEAR_MIPMAP_LINEAR
:
275 sampler
->ss0
.min_filter
= BRW_MAPFILTER_LINEAR
;
276 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_LINEAR
;
284 if (gl_sampler
->MaxAnisotropy
> 1.0) {
285 sampler
->ss0
.min_filter
= BRW_MAPFILTER_ANISOTROPIC
;
286 sampler
->ss0
.mag_filter
= BRW_MAPFILTER_ANISOTROPIC
;
288 if (gl_sampler
->MaxAnisotropy
> 2.0) {
289 sampler
->ss3
.max_aniso
= MIN2((gl_sampler
->MaxAnisotropy
- 2) / 2,
294 switch (gl_sampler
->MagFilter
) {
296 sampler
->ss0
.mag_filter
= BRW_MAPFILTER_NEAREST
;
297 using_nearest
= true;
300 sampler
->ss0
.mag_filter
= BRW_MAPFILTER_LINEAR
;
307 sampler
->ss1
.r_wrap_mode
= translate_wrap_mode(brw
, gl_sampler
->WrapR
,
309 sampler
->ss1
.s_wrap_mode
= translate_wrap_mode(brw
, gl_sampler
->WrapS
,
311 sampler
->ss1
.t_wrap_mode
= translate_wrap_mode(brw
, gl_sampler
->WrapT
,
315 sampler
->ss0
.min_filter
!= sampler
->ss0
.mag_filter
)
316 sampler
->ss0
.min_mag_neq
= 1;
318 /* Cube-maps on 965 and later must use the same wrap mode for all 3
319 * coordinate dimensions. Futher, only CUBE and CLAMP are valid.
321 if (texObj
->Target
== GL_TEXTURE_CUBE_MAP
||
322 texObj
->Target
== GL_TEXTURE_CUBE_MAP_ARRAY
) {
323 if ((ctx
->Texture
.CubeMapSeamless
|| gl_sampler
->CubeMapSeamless
) &&
324 (gl_sampler
->MinFilter
!= GL_NEAREST
||
325 gl_sampler
->MagFilter
!= GL_NEAREST
)) {
326 sampler
->ss1
.r_wrap_mode
= BRW_TEXCOORDMODE_CUBE
;
327 sampler
->ss1
.s_wrap_mode
= BRW_TEXCOORDMODE_CUBE
;
328 sampler
->ss1
.t_wrap_mode
= BRW_TEXCOORDMODE_CUBE
;
330 sampler
->ss1
.r_wrap_mode
= BRW_TEXCOORDMODE_CLAMP
;
331 sampler
->ss1
.s_wrap_mode
= BRW_TEXCOORDMODE_CLAMP
;
332 sampler
->ss1
.t_wrap_mode
= BRW_TEXCOORDMODE_CLAMP
;
334 } else if (texObj
->Target
== GL_TEXTURE_1D
) {
335 /* There's a bug in 1D texture sampling - it actually pays
336 * attention to the wrap_t value, though it should not.
337 * Override the wrap_t value here to GL_REPEAT to keep
338 * any nonexistent border pixels from floating in.
340 sampler
->ss1
.t_wrap_mode
= BRW_TEXCOORDMODE_WRAP
;
344 /* Set shadow function:
346 if (gl_sampler
->CompareMode
== GL_COMPARE_R_TO_TEXTURE_ARB
) {
347 /* Shadowing is "enabled" by emitting a particular sampler
348 * message (sample_c). So need to recompile WM program when
349 * shadow comparison is enabled on each/any texture unit.
351 sampler
->ss0
.shadow_function
=
352 intel_translate_shadow_compare_func(gl_sampler
->CompareFunc
);
357 sampler
->ss0
.lod_bias
= S_FIXED(CLAMP(texUnit
->LodBias
+
358 gl_sampler
->LodBias
, -16, 15), 6);
360 sampler
->ss0
.lod_preclamp
= 1; /* OpenGL mode */
361 sampler
->ss0
.default_color_mode
= 0; /* OpenGL/DX10 mode */
363 sampler
->ss0
.base_level
= U_FIXED(0, 1);
365 sampler
->ss1
.max_lod
= U_FIXED(CLAMP(gl_sampler
->MaxLod
, 0, 13), 6);
366 sampler
->ss1
.min_lod
= U_FIXED(CLAMP(gl_sampler
->MinLod
, 0, 13), 6);
368 /* On Gen6+, the sampler can handle non-normalized texture
369 * rectangle coordinates natively
371 if (brw
->gen
>= 6 && texObj
->Target
== GL_TEXTURE_RECTANGLE
) {
372 sampler
->ss3
.non_normalized_coord
= 1;
376 upload_default_color(brw
, gl_sampler
, unit
, &sdc_offset
);
379 sampler
->ss2
.default_color_pointer
= sdc_offset
>> 5;
382 sampler
->ss2
.default_color_pointer
=
383 (brw
->batch
.bo
->offset64
+ sdc_offset
) >> 5;
385 drm_intel_bo_emit_reloc(brw
->batch
.bo
,
386 batch_offset_for_sampler_state
+
387 offsetof(struct brw_sampler_state
, ss2
),
388 brw
->batch
.bo
, sdc_offset
,
389 I915_GEM_DOMAIN_SAMPLER
, 0);
392 if (sampler
->ss0
.min_filter
!= BRW_MAPFILTER_NEAREST
)
393 sampler
->ss3
.address_round
|= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN
|
394 BRW_ADDRESS_ROUNDING_ENABLE_V_MIN
|
395 BRW_ADDRESS_ROUNDING_ENABLE_R_MIN
;
396 if (sampler
->ss0
.mag_filter
!= BRW_MAPFILTER_NEAREST
)
397 sampler
->ss3
.address_round
|= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG
|
398 BRW_ADDRESS_ROUNDING_ENABLE_V_MAG
|
399 BRW_ADDRESS_ROUNDING_ENABLE_R_MAG
;
404 brw_upload_sampler_state_table(struct brw_context
*brw
,
405 struct gl_program
*prog
,
406 struct brw_stage_state
*stage_state
)
408 struct gl_context
*ctx
= &brw
->ctx
;
409 uint32_t sampler_count
= stage_state
->sampler_count
;
411 GLbitfield SamplersUsed
= prog
->SamplersUsed
;
413 if (sampler_count
== 0)
416 /* SAMPLER_STATE is 4 DWords on all platforms. */
417 const int dwords
= 4;
418 const int size_in_bytes
= dwords
* sizeof(uint32_t);
420 uint32_t *sampler_state
= brw_state_batch(brw
, AUB_TRACE_SAMPLER_STATE
,
421 sampler_count
* size_in_bytes
,
422 32, &stage_state
->sampler_offset
);
423 memset(sampler_state
, 0, sampler_count
* size_in_bytes
);
425 uint32_t batch_offset_for_sampler_state
= stage_state
->sampler_offset
;
427 for (unsigned s
= 0; s
< sampler_count
; s
++) {
428 if (SamplersUsed
& (1 << s
)) {
429 const unsigned unit
= prog
->SamplerUnits
[s
];
430 if (ctx
->Texture
.Unit
[unit
]._Current
) {
432 gen7_update_sampler_state(brw
, unit
,
433 (struct gen7_sampler_state
*)
436 brw_update_sampler_state(brw
, unit
,
437 (struct brw_sampler_state
*)
439 batch_offset_for_sampler_state
);
444 sampler_state
+= dwords
;
445 batch_offset_for_sampler_state
+= size_in_bytes
;
449 /* Emit a 3DSTATE_SAMPLER_STATE_POINTERS_XS packet. */
450 gen7_emit_sampler_state_pointers_xs(brw
, stage_state
);
452 /* Flag that the sampler state table pointer has changed; later atoms
455 brw
->state
.dirty
.cache
|= CACHE_NEW_SAMPLER
;
460 brw_upload_fs_samplers(struct brw_context
*brw
)
462 /* BRW_NEW_FRAGMENT_PROGRAM */
463 struct gl_program
*fs
= (struct gl_program
*) brw
->fragment_program
;
464 brw_upload_sampler_state_table(brw
, fs
, &brw
->wm
.base
);
467 const struct brw_tracked_state brw_fs_samplers
= {
469 .mesa
= _NEW_TEXTURE
,
470 .brw
= BRW_NEW_BATCH
|
471 BRW_NEW_FRAGMENT_PROGRAM
,
474 .emit
= brw_upload_fs_samplers
,
478 brw_upload_vs_samplers(struct brw_context
*brw
)
480 /* BRW_NEW_VERTEX_PROGRAM */
481 struct gl_program
*vs
= (struct gl_program
*) brw
->vertex_program
;
482 brw_upload_sampler_state_table(brw
, vs
, &brw
->vs
.base
);
486 const struct brw_tracked_state brw_vs_samplers
= {
488 .mesa
= _NEW_TEXTURE
,
489 .brw
= BRW_NEW_BATCH
|
490 BRW_NEW_VERTEX_PROGRAM
,
493 .emit
= brw_upload_vs_samplers
,
498 brw_upload_gs_samplers(struct brw_context
*brw
)
500 /* BRW_NEW_GEOMETRY_PROGRAM */
501 struct gl_program
*gs
= (struct gl_program
*) brw
->geometry_program
;
505 brw_upload_sampler_state_table(brw
, gs
, &brw
->gs
.base
);
509 const struct brw_tracked_state brw_gs_samplers
= {
511 .mesa
= _NEW_TEXTURE
,
512 .brw
= BRW_NEW_BATCH
|
513 BRW_NEW_GEOMETRY_PROGRAM
,
516 .emit
= brw_upload_gs_samplers
,