i965: Drop the degenerate brw_sampler_default_color structure.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_sampler_state.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics to
4 develop this 3D driver.
5
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:
13
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.
17
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.
25
26 **********************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keithw@vmware.com>
30 */
31
32 /**
33 * @file brw_sampler_state.c
34 *
35 * This file contains code for emitting SAMPLER_STATE structures, which
36 * specifies filter modes, wrap modes, border color, and so on.
37 */
38
39 #include "brw_context.h"
40 #include "brw_state.h"
41 #include "brw_defines.h"
42 #include "intel_mipmap_tree.h"
43
44 #include "main/macros.h"
45 #include "main/samplerobj.h"
46
47 uint32_t
48 translate_wrap_mode(struct brw_context *brw, GLenum wrap, bool using_nearest)
49 {
50 switch( wrap ) {
51 case GL_REPEAT:
52 return BRW_TEXCOORDMODE_WRAP;
53 case GL_CLAMP:
54 /* GL_CLAMP is the weird mode where coordinates are clamped to
55 * [0.0, 1.0], so linear filtering of coordinates outside of
56 * [0.0, 1.0] give you half edge texel value and half border
57 * color.
58 *
59 * Gen8+ supports this natively.
60 */
61 if (brw->gen >= 8)
62 return GEN8_TEXCOORDMODE_HALF_BORDER;
63
64 /* On Gen4-7.5, we clamp the coordinates in the fragment shader
65 * and set clamp_border here, which gets the result desired.
66 * We just use clamp(_to_edge) for nearest, because for nearest
67 * clamping to 1.0 gives border color instead of the desired
68 * edge texels.
69 */
70 if (using_nearest)
71 return BRW_TEXCOORDMODE_CLAMP;
72 else
73 return BRW_TEXCOORDMODE_CLAMP_BORDER;
74 case GL_CLAMP_TO_EDGE:
75 return BRW_TEXCOORDMODE_CLAMP;
76 case GL_CLAMP_TO_BORDER:
77 return BRW_TEXCOORDMODE_CLAMP_BORDER;
78 case GL_MIRRORED_REPEAT:
79 return BRW_TEXCOORDMODE_MIRROR;
80 case GL_MIRROR_CLAMP_TO_EDGE:
81 return BRW_TEXCOORDMODE_MIRROR_ONCE;
82 default:
83 return BRW_TEXCOORDMODE_WRAP;
84 }
85 }
86
87 /**
88 * Upload SAMPLER_BORDER_COLOR_STATE.
89 */
90 void
91 upload_default_color(struct brw_context *brw,
92 struct gl_sampler_object *sampler,
93 int unit,
94 uint32_t *sdc_offset)
95 {
96 struct gl_context *ctx = &brw->ctx;
97 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
98 struct gl_texture_object *texObj = texUnit->_Current;
99 struct gl_texture_image *firstImage = texObj->Image[0][texObj->BaseLevel];
100 float color[4];
101
102 switch (firstImage->_BaseFormat) {
103 case GL_DEPTH_COMPONENT:
104 /* GL specs that border color for depth textures is taken from the
105 * R channel, while the hardware uses A. Spam R into all the
106 * channels for safety.
107 */
108 color[0] = sampler->BorderColor.f[0];
109 color[1] = sampler->BorderColor.f[0];
110 color[2] = sampler->BorderColor.f[0];
111 color[3] = sampler->BorderColor.f[0];
112 break;
113 case GL_ALPHA:
114 color[0] = 0.0;
115 color[1] = 0.0;
116 color[2] = 0.0;
117 color[3] = sampler->BorderColor.f[3];
118 break;
119 case GL_INTENSITY:
120 color[0] = sampler->BorderColor.f[0];
121 color[1] = sampler->BorderColor.f[0];
122 color[2] = sampler->BorderColor.f[0];
123 color[3] = sampler->BorderColor.f[0];
124 break;
125 case GL_LUMINANCE:
126 color[0] = sampler->BorderColor.f[0];
127 color[1] = sampler->BorderColor.f[0];
128 color[2] = sampler->BorderColor.f[0];
129 color[3] = 1.0;
130 break;
131 case GL_LUMINANCE_ALPHA:
132 color[0] = sampler->BorderColor.f[0];
133 color[1] = sampler->BorderColor.f[0];
134 color[2] = sampler->BorderColor.f[0];
135 color[3] = sampler->BorderColor.f[3];
136 break;
137 default:
138 color[0] = sampler->BorderColor.f[0];
139 color[1] = sampler->BorderColor.f[1];
140 color[2] = sampler->BorderColor.f[2];
141 color[3] = sampler->BorderColor.f[3];
142 break;
143 }
144
145 /* In some cases we use an RGBA surface format for GL RGB textures,
146 * where we've initialized the A channel to 1.0. We also have to set
147 * the border color alpha to 1.0 in that case.
148 */
149 if (firstImage->_BaseFormat == GL_RGB)
150 color[3] = 1.0;
151
152 if (brw->gen >= 8) {
153 /* On Broadwell, the border color is represented as four 32-bit floats,
154 * integers, or unsigned values, interpreted according to the surface
155 * format. This matches the sampler->BorderColor union exactly. Since
156 * we use floats both here and in the above reswizzling code, we preserve
157 * the original bit pattern. So we actually handle all three formats.
158 */
159 float *sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR,
160 4 * 4, 64, sdc_offset);
161 COPY_4FV(sdc, color);
162 } else if (brw->gen == 5 || brw->gen == 6) {
163 struct gen5_sampler_default_color *sdc;
164
165 sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR,
166 sizeof(*sdc), 32, sdc_offset);
167
168 memset(sdc, 0, sizeof(*sdc));
169
170 UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[0], color[0]);
171 UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[1], color[1]);
172 UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[2], color[2]);
173 UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[3], color[3]);
174
175 UNCLAMPED_FLOAT_TO_USHORT(sdc->us[0], color[0]);
176 UNCLAMPED_FLOAT_TO_USHORT(sdc->us[1], color[1]);
177 UNCLAMPED_FLOAT_TO_USHORT(sdc->us[2], color[2]);
178 UNCLAMPED_FLOAT_TO_USHORT(sdc->us[3], color[3]);
179
180 UNCLAMPED_FLOAT_TO_SHORT(sdc->s[0], color[0]);
181 UNCLAMPED_FLOAT_TO_SHORT(sdc->s[1], color[1]);
182 UNCLAMPED_FLOAT_TO_SHORT(sdc->s[2], color[2]);
183 UNCLAMPED_FLOAT_TO_SHORT(sdc->s[3], color[3]);
184
185 sdc->hf[0] = _mesa_float_to_half(color[0]);
186 sdc->hf[1] = _mesa_float_to_half(color[1]);
187 sdc->hf[2] = _mesa_float_to_half(color[2]);
188 sdc->hf[3] = _mesa_float_to_half(color[3]);
189
190 sdc->b[0] = sdc->s[0] >> 8;
191 sdc->b[1] = sdc->s[1] >> 8;
192 sdc->b[2] = sdc->s[2] >> 8;
193 sdc->b[3] = sdc->s[3] >> 8;
194
195 sdc->f[0] = color[0];
196 sdc->f[1] = color[1];
197 sdc->f[2] = color[2];
198 sdc->f[3] = color[3];
199 } else {
200 float *sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR,
201 4 * 4, 32, sdc_offset);
202 memcpy(sdc, color, 4 * 4);
203 }
204 }
205
206 /**
207 * Sets the sampler state for a single unit based off of the sampler key
208 * entry.
209 */
210 static void brw_update_sampler_state(struct brw_context *brw,
211 int unit,
212 int ss_index,
213 struct brw_sampler_state *sampler,
214 uint32_t sampler_state_table_offset,
215 uint32_t *sdc_offset)
216 {
217 struct gl_context *ctx = &brw->ctx;
218 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
219 struct gl_texture_object *texObj = texUnit->_Current;
220 struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit);
221 bool using_nearest = false;
222
223 /* These don't use samplers at all. */
224 if (texObj->Target == GL_TEXTURE_BUFFER)
225 return;
226
227 switch (gl_sampler->MinFilter) {
228 case GL_NEAREST:
229 sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
230 sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
231 using_nearest = true;
232 break;
233 case GL_LINEAR:
234 sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
235 sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
236 break;
237 case GL_NEAREST_MIPMAP_NEAREST:
238 sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
239 sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
240 break;
241 case GL_LINEAR_MIPMAP_NEAREST:
242 sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
243 sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
244 break;
245 case GL_NEAREST_MIPMAP_LINEAR:
246 sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
247 sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
248 break;
249 case GL_LINEAR_MIPMAP_LINEAR:
250 sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
251 sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
252 break;
253 default:
254 break;
255 }
256
257 /* Set Anisotropy:
258 */
259 if (gl_sampler->MaxAnisotropy > 1.0) {
260 sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
261 sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
262
263 if (gl_sampler->MaxAnisotropy > 2.0) {
264 sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2,
265 BRW_ANISORATIO_16);
266 }
267 }
268 else {
269 switch (gl_sampler->MagFilter) {
270 case GL_NEAREST:
271 sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
272 using_nearest = true;
273 break;
274 case GL_LINEAR:
275 sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
276 break;
277 default:
278 break;
279 }
280 }
281
282 sampler->ss1.r_wrap_mode = translate_wrap_mode(brw, gl_sampler->WrapR,
283 using_nearest);
284 sampler->ss1.s_wrap_mode = translate_wrap_mode(brw, gl_sampler->WrapS,
285 using_nearest);
286 sampler->ss1.t_wrap_mode = translate_wrap_mode(brw, gl_sampler->WrapT,
287 using_nearest);
288
289 if (brw->gen >= 6 &&
290 sampler->ss0.min_filter != sampler->ss0.mag_filter)
291 sampler->ss0.min_mag_neq = 1;
292
293 /* Cube-maps on 965 and later must use the same wrap mode for all 3
294 * coordinate dimensions. Futher, only CUBE and CLAMP are valid.
295 */
296 if (texObj->Target == GL_TEXTURE_CUBE_MAP ||
297 texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) {
298 if ((ctx->Texture.CubeMapSeamless || gl_sampler->CubeMapSeamless) &&
299 (gl_sampler->MinFilter != GL_NEAREST ||
300 gl_sampler->MagFilter != GL_NEAREST)) {
301 sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
302 sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
303 sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
304 } else {
305 sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
306 sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
307 sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
308 }
309 } else if (texObj->Target == GL_TEXTURE_1D) {
310 /* There's a bug in 1D texture sampling - it actually pays
311 * attention to the wrap_t value, though it should not.
312 * Override the wrap_t value here to GL_REPEAT to keep
313 * any nonexistent border pixels from floating in.
314 */
315 sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
316 }
317
318
319 /* Set shadow function:
320 */
321 if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
322 /* Shadowing is "enabled" by emitting a particular sampler
323 * message (sample_c). So need to recompile WM program when
324 * shadow comparison is enabled on each/any texture unit.
325 */
326 sampler->ss0.shadow_function =
327 intel_translate_shadow_compare_func(gl_sampler->CompareFunc);
328 }
329
330 /* Set LOD bias:
331 */
332 sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias +
333 gl_sampler->LodBias, -16, 15), 6);
334
335 sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
336 sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
337
338 sampler->ss0.base_level = U_FIXED(0, 1);
339
340 sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 6);
341 sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 6);
342
343 /* On Gen6+, the sampler can handle non-normalized texture
344 * rectangle coordinates natively
345 */
346 if (brw->gen >= 6 && texObj->Target == GL_TEXTURE_RECTANGLE) {
347 sampler->ss3.non_normalized_coord = 1;
348 }
349
350 upload_default_color(brw, gl_sampler, unit, sdc_offset);
351
352 if (brw->gen >= 6) {
353 sampler->ss2.default_color_pointer = *sdc_offset >> 5;
354 } else {
355 /* reloc */
356 sampler->ss2.default_color_pointer = (brw->batch.bo->offset64 +
357 *sdc_offset) >> 5;
358
359 drm_intel_bo_emit_reloc(brw->batch.bo,
360 sampler_state_table_offset +
361 ss_index * sizeof(struct brw_sampler_state) +
362 offsetof(struct brw_sampler_state, ss2),
363 brw->batch.bo, *sdc_offset,
364 I915_GEM_DOMAIN_SAMPLER, 0);
365 }
366
367 if (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST)
368 sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN |
369 BRW_ADDRESS_ROUNDING_ENABLE_V_MIN |
370 BRW_ADDRESS_ROUNDING_ENABLE_R_MIN;
371 if (sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST)
372 sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG |
373 BRW_ADDRESS_ROUNDING_ENABLE_V_MAG |
374 BRW_ADDRESS_ROUNDING_ENABLE_R_MAG;
375 }
376
377
378 static void
379 brw_upload_sampler_state_table(struct brw_context *brw,
380 struct gl_program *prog,
381 struct brw_stage_state *stage_state)
382 {
383 struct gl_context *ctx = &brw->ctx;
384 struct brw_sampler_state *samplers;
385 uint32_t sampler_count = stage_state->sampler_count;
386
387 GLbitfield SamplersUsed = prog->SamplersUsed;
388
389 if (sampler_count == 0)
390 return;
391
392 samplers = brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE,
393 sampler_count * sizeof(*samplers),
394 32, &stage_state->sampler_offset);
395 memset(samplers, 0, sampler_count * sizeof(*samplers));
396
397 for (unsigned s = 0; s < sampler_count; s++) {
398 if (SamplersUsed & (1 << s)) {
399 const unsigned unit = prog->SamplerUnits[s];
400 if (ctx->Texture.Unit[unit]._Current)
401 brw_update_sampler_state(brw, unit, s, &samplers[s],
402 stage_state->sampler_offset,
403 &stage_state->sdc_offset[s]);
404 }
405 }
406
407 brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
408 }
409
410 static void
411 brw_upload_fs_samplers(struct brw_context *brw)
412 {
413 /* BRW_NEW_FRAGMENT_PROGRAM */
414 struct gl_program *fs = (struct gl_program *) brw->fragment_program;
415 brw->vtbl.upload_sampler_state_table(brw, fs, &brw->wm.base);
416 }
417
418 const struct brw_tracked_state brw_fs_samplers = {
419 .dirty = {
420 .mesa = _NEW_TEXTURE,
421 .brw = BRW_NEW_BATCH |
422 BRW_NEW_FRAGMENT_PROGRAM,
423 .cache = 0
424 },
425 .emit = brw_upload_fs_samplers,
426 };
427
428 static void
429 brw_upload_vs_samplers(struct brw_context *brw)
430 {
431 /* BRW_NEW_VERTEX_PROGRAM */
432 struct gl_program *vs = (struct gl_program *) brw->vertex_program;
433 brw->vtbl.upload_sampler_state_table(brw, vs, &brw->vs.base);
434 }
435
436
437 const struct brw_tracked_state brw_vs_samplers = {
438 .dirty = {
439 .mesa = _NEW_TEXTURE,
440 .brw = BRW_NEW_BATCH |
441 BRW_NEW_VERTEX_PROGRAM,
442 .cache = 0
443 },
444 .emit = brw_upload_vs_samplers,
445 };
446
447
448 static void
449 brw_upload_gs_samplers(struct brw_context *brw)
450 {
451 /* BRW_NEW_GEOMETRY_PROGRAM */
452 struct gl_program *gs = (struct gl_program *) brw->geometry_program;
453 if (!gs)
454 return;
455
456 brw->vtbl.upload_sampler_state_table(brw, gs, &brw->gs.base);
457 }
458
459
460 const struct brw_tracked_state brw_gs_samplers = {
461 .dirty = {
462 .mesa = _NEW_TEXTURE,
463 .brw = BRW_NEW_BATCH |
464 BRW_NEW_GEOMETRY_PROGRAM,
465 .cache = 0
466 },
467 .emit = brw_upload_gs_samplers,
468 };
469
470
471 void
472 gen4_init_vtable_sampler_functions(struct brw_context *brw)
473 {
474 brw->vtbl.upload_sampler_state_table = brw_upload_sampler_state_table;
475 }