f830e2562684b32286f35a9db5de1770ab4bb041
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_sampler_state.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) 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 <keith@tungstengraphics.com>
30 */
31
32
33 #include "brw_context.h"
34 #include "brw_state.h"
35 #include "brw_defines.h"
36
37 #include "main/macros.h"
38
39
40
41 /* Samplers aren't strictly wm state from the hardware's perspective,
42 * but that is the only situation in which we use them in this driver.
43 */
44
45
46
47 /* The brw (and related graphics cores) do not support GL_CLAMP. The
48 * Intel drivers for "other operating systems" implement GL_CLAMP as
49 * GL_CLAMP_TO_EDGE, so the same is done here.
50 */
51 static GLuint translate_wrap_mode( GLenum wrap )
52 {
53 switch( wrap ) {
54 case GL_REPEAT:
55 return BRW_TEXCOORDMODE_WRAP;
56 case GL_CLAMP:
57 return BRW_TEXCOORDMODE_CLAMP;
58 case GL_CLAMP_TO_EDGE:
59 return BRW_TEXCOORDMODE_CLAMP; /* conform likes it this way */
60 case GL_CLAMP_TO_BORDER:
61 return BRW_TEXCOORDMODE_CLAMP_BORDER;
62 case GL_MIRRORED_REPEAT:
63 return BRW_TEXCOORDMODE_MIRROR;
64 default:
65 return BRW_TEXCOORDMODE_WRAP;
66 }
67 }
68
69 static drm_intel_bo *upload_default_color( struct brw_context *brw,
70 const GLfloat *color )
71 {
72 struct intel_context *intel = &brw->intel;
73
74 if (intel->gen >= 5) {
75 struct gen5_sampler_default_color sdc;
76
77 memset(&sdc, 0, sizeof(sdc));
78
79 UNCLAMPED_FLOAT_TO_UBYTE(sdc.ub[0], color[0]);
80 UNCLAMPED_FLOAT_TO_UBYTE(sdc.ub[1], color[1]);
81 UNCLAMPED_FLOAT_TO_UBYTE(sdc.ub[2], color[2]);
82 UNCLAMPED_FLOAT_TO_UBYTE(sdc.ub[3], color[3]);
83
84 UNCLAMPED_FLOAT_TO_USHORT(sdc.us[0], color[0]);
85 UNCLAMPED_FLOAT_TO_USHORT(sdc.us[1], color[1]);
86 UNCLAMPED_FLOAT_TO_USHORT(sdc.us[2], color[2]);
87 UNCLAMPED_FLOAT_TO_USHORT(sdc.us[3], color[3]);
88
89 UNCLAMPED_FLOAT_TO_SHORT(sdc.s[0], color[0]);
90 UNCLAMPED_FLOAT_TO_SHORT(sdc.s[1], color[1]);
91 UNCLAMPED_FLOAT_TO_SHORT(sdc.s[2], color[2]);
92 UNCLAMPED_FLOAT_TO_SHORT(sdc.s[3], color[3]);
93
94 /* XXX: Fill in half floats */
95 /* XXX: Fill in signed bytes */
96
97 COPY_4V(sdc.f, color);
98
99 return brw_cache_data(&brw->cache, BRW_SAMPLER_DEFAULT_COLOR,
100 &sdc, sizeof(sdc));
101 } else {
102 struct brw_sampler_default_color sdc;
103
104 COPY_4V(sdc.color, color);
105
106 return brw_cache_data(&brw->cache, BRW_SAMPLER_DEFAULT_COLOR,
107 &sdc, sizeof(sdc));
108 }
109 }
110
111
112 struct wm_sampler_key {
113 int sampler_count;
114
115 struct wm_sampler_entry {
116 GLenum tex_target;
117 GLenum wrap_r, wrap_s, wrap_t;
118 uint32_t base_level;
119 float maxlod, minlod;
120 float lod_bias;
121 float max_aniso;
122 GLenum minfilter, magfilter;
123 GLenum comparemode, comparefunc;
124
125 /** If target is cubemap, take context setting.
126 */
127 GLboolean seamless_cube_map;
128 } sampler[BRW_MAX_TEX_UNIT];
129 };
130
131 /**
132 * Sets the sampler state for a single unit based off of the sampler key
133 * entry.
134 */
135 static void brw_update_sampler_state(struct brw_context *brw,
136 struct wm_sampler_entry *key,
137 drm_intel_bo *sdc_bo,
138 struct brw_sampler_state *sampler)
139 {
140 struct intel_context *intel = &brw->intel;
141
142 memset(sampler, 0, sizeof(*sampler));
143
144 switch (key->minfilter) {
145 case GL_NEAREST:
146 sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
147 sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
148 break;
149 case GL_LINEAR:
150 sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
151 sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
152 break;
153 case GL_NEAREST_MIPMAP_NEAREST:
154 sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
155 sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
156 break;
157 case GL_LINEAR_MIPMAP_NEAREST:
158 sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
159 sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
160 break;
161 case GL_NEAREST_MIPMAP_LINEAR:
162 sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
163 sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
164 break;
165 case GL_LINEAR_MIPMAP_LINEAR:
166 sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
167 sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
168 break;
169 default:
170 break;
171 }
172
173 /* Set Anisotropy:
174 */
175 if (key->max_aniso > 1.0) {
176 sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
177 sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
178
179 if (key->max_aniso > 2.0) {
180 sampler->ss3.max_aniso = MIN2((key->max_aniso - 2) / 2,
181 BRW_ANISORATIO_16);
182 }
183 }
184 else {
185 switch (key->magfilter) {
186 case GL_NEAREST:
187 sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
188 break;
189 case GL_LINEAR:
190 sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
191 break;
192 default:
193 break;
194 }
195 }
196
197 sampler->ss1.r_wrap_mode = translate_wrap_mode(key->wrap_r);
198 sampler->ss1.s_wrap_mode = translate_wrap_mode(key->wrap_s);
199 sampler->ss1.t_wrap_mode = translate_wrap_mode(key->wrap_t);
200
201 if (intel->gen >= 6 &&
202 sampler->ss0.min_filter != sampler->ss0.mag_filter)
203 sampler->ss0.min_mag_neq = 1;
204
205 /* Cube-maps on 965 and later must use the same wrap mode for all 3
206 * coordinate dimensions. Futher, only CUBE and CLAMP are valid.
207 */
208 if (key->tex_target == GL_TEXTURE_CUBE_MAP) {
209 if (key->seamless_cube_map &&
210 (key->minfilter != GL_NEAREST || key->magfilter != GL_NEAREST)) {
211 sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
212 sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
213 sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
214 } else {
215 sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
216 sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
217 sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
218 }
219 } else if (key->tex_target == GL_TEXTURE_1D) {
220 /* There's a bug in 1D texture sampling - it actually pays
221 * attention to the wrap_t value, though it should not.
222 * Override the wrap_t value here to GL_REPEAT to keep
223 * any nonexistent border pixels from floating in.
224 */
225 sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
226 }
227
228
229 /* Set shadow function:
230 */
231 if (key->comparemode == GL_COMPARE_R_TO_TEXTURE_ARB) {
232 /* Shadowing is "enabled" by emitting a particular sampler
233 * message (sample_c). So need to recompile WM program when
234 * shadow comparison is enabled on each/any texture unit.
235 */
236 sampler->ss0.shadow_function =
237 intel_translate_shadow_compare_func(key->comparefunc);
238 }
239
240 /* Set LOD bias:
241 */
242 sampler->ss0.lod_bias = S_FIXED(CLAMP(key->lod_bias, -16, 15), 6);
243
244 sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
245 sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
246
247 sampler->ss0.base_level = U_FIXED(key->base_level, 1);
248
249 sampler->ss1.max_lod = U_FIXED(CLAMP(key->maxlod, 0, 13), 6);
250 sampler->ss1.min_lod = U_FIXED(CLAMP(key->minlod, 0, 13), 6);
251
252 sampler->ss2.default_color_pointer = sdc_bo->offset >> 5; /* reloc */
253 }
254
255
256 /** Sets up the cache key for sampler state for all texture units */
257 static void
258 brw_wm_sampler_populate_key(struct brw_context *brw,
259 struct wm_sampler_key *key)
260 {
261 struct gl_context *ctx = &brw->intel.ctx;
262 int unit;
263 char *last_entry_end = ((char*)&key->sampler_count) +
264 sizeof(key->sampler_count);
265
266 key->sampler_count = 0;
267
268 for (unit = 0; unit < BRW_MAX_TEX_UNIT; unit++) {
269 if (ctx->Texture.Unit[unit]._ReallyEnabled) {
270 struct wm_sampler_entry *entry = &key->sampler[unit];
271 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
272 struct gl_texture_object *texObj = texUnit->_Current;
273 struct gl_texture_image *firstImage =
274 texObj->Image[0][texObj->BaseLevel];
275
276 memset(last_entry_end, 0,
277 (char*)entry - last_entry_end + sizeof(*entry));
278 last_entry_end = ((char*)entry) + sizeof(*entry);
279
280 entry->tex_target = texObj->Target;
281
282 entry->seamless_cube_map = (texObj->Target == GL_TEXTURE_CUBE_MAP)
283 ? ctx->Texture.CubeMapSeamless : GL_FALSE;
284
285 entry->wrap_r = texObj->WrapR;
286 entry->wrap_s = texObj->WrapS;
287 entry->wrap_t = texObj->WrapT;
288
289 entry->base_level = texObj->BaseLevel;
290 entry->maxlod = texObj->MaxLod;
291 entry->minlod = texObj->MinLod;
292 entry->lod_bias = texUnit->LodBias + texObj->LodBias;
293 entry->max_aniso = texObj->MaxAnisotropy;
294 entry->minfilter = texObj->MinFilter;
295 entry->magfilter = texObj->MagFilter;
296 entry->comparemode = texObj->CompareMode;
297 entry->comparefunc = texObj->CompareFunc;
298
299 drm_intel_bo_unreference(brw->wm.sdc_bo[unit]);
300 if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) {
301 float bordercolor[4] = {
302 texObj->BorderColor.f[0],
303 texObj->BorderColor.f[0],
304 texObj->BorderColor.f[0],
305 texObj->BorderColor.f[0]
306 };
307 /* GL specs that border color for depth textures is taken from the
308 * R channel, while the hardware uses A. Spam R into all the
309 * channels for safety.
310 */
311 brw->wm.sdc_bo[unit] = upload_default_color(brw, bordercolor);
312 } else {
313 brw->wm.sdc_bo[unit] = upload_default_color(brw,
314 texObj->BorderColor.f);
315 }
316 key->sampler_count = unit + 1;
317 }
318 }
319 struct wm_sampler_entry *entry = &key->sampler[key->sampler_count];
320 memset(last_entry_end, 0, (char*)entry - last_entry_end);
321 }
322
323 /* All samplers must be uploaded in a single contiguous array, which
324 * complicates various things. However, this is still too confusing -
325 * FIXME: simplify all the different new texture state flags.
326 */
327 static void upload_wm_samplers( struct brw_context *brw )
328 {
329 struct gl_context *ctx = &brw->intel.ctx;
330 struct wm_sampler_key key;
331 int i, sampler_key_size;
332
333 brw_wm_sampler_populate_key(brw, &key);
334
335 if (brw->wm.sampler_count != key.sampler_count) {
336 brw->wm.sampler_count = key.sampler_count;
337 brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
338 }
339
340 drm_intel_bo_unreference(brw->wm.sampler_bo);
341 brw->wm.sampler_bo = NULL;
342 if (brw->wm.sampler_count == 0)
343 return;
344
345 /* Only include the populated portion of the key in the search. */
346 sampler_key_size = offsetof(struct wm_sampler_key,
347 sampler[key.sampler_count]);
348 brw->wm.sampler_bo = brw_search_cache(&brw->cache, BRW_SAMPLER,
349 &key, sampler_key_size,
350 brw->wm.sdc_bo, key.sampler_count,
351 NULL);
352
353 /* If we didnt find it in the cache, compute the state and put it in the
354 * cache.
355 */
356 if (brw->wm.sampler_bo == NULL) {
357 struct brw_sampler_state sampler[BRW_MAX_TEX_UNIT];
358
359 memset(sampler, 0, sizeof(sampler));
360 for (i = 0; i < key.sampler_count; i++) {
361 if (brw->wm.sdc_bo[i] == NULL)
362 continue;
363
364 brw_update_sampler_state(brw, &key.sampler[i], brw->wm.sdc_bo[i],
365 &sampler[i]);
366 }
367
368 brw->wm.sampler_bo = brw_upload_cache(&brw->cache, BRW_SAMPLER,
369 &key, sampler_key_size,
370 brw->wm.sdc_bo, key.sampler_count,
371 &sampler, sizeof(sampler));
372
373 /* Emit SDC relocations */
374 for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
375 if (!ctx->Texture.Unit[i]._ReallyEnabled)
376 continue;
377
378 drm_intel_bo_emit_reloc(brw->wm.sampler_bo,
379 i * sizeof(struct brw_sampler_state) +
380 offsetof(struct brw_sampler_state, ss2),
381 brw->wm.sdc_bo[i], 0,
382 I915_GEM_DOMAIN_SAMPLER, 0);
383 }
384 }
385 }
386
387 const struct brw_tracked_state brw_wm_samplers = {
388 .dirty = {
389 .mesa = _NEW_TEXTURE,
390 .brw = 0,
391 .cache = 0
392 },
393 .prepare = upload_wm_samplers,
394 };
395
396