2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) 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 <keith@tungstengraphics.com>
33 #include "brw_context.h"
34 #include "brw_state.h"
35 #include "brw_defines.h"
37 #include "main/macros.h"
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.
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.
51 static GLuint
translate_wrap_mode( GLenum wrap
)
55 return BRW_TEXCOORDMODE_WRAP
;
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
;
65 return BRW_TEXCOORDMODE_WRAP
;
69 static drm_intel_bo
*upload_default_color( struct brw_context
*brw
,
70 const GLfloat
*color
)
72 struct intel_context
*intel
= &brw
->intel
;
74 if (intel
->gen
>= 5) {
75 struct gen5_sampler_default_color sdc
;
77 memset(&sdc
, 0, sizeof(sdc
));
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]);
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]);
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]);
94 /* XXX: Fill in half floats */
95 /* XXX: Fill in signed bytes */
97 COPY_4V(sdc
.f
, color
);
99 return brw_cache_data(&brw
->cache
, BRW_SAMPLER_DEFAULT_COLOR
,
102 struct brw_sampler_default_color sdc
;
104 COPY_4V(sdc
.color
, color
);
106 return brw_cache_data(&brw
->cache
, BRW_SAMPLER_DEFAULT_COLOR
,
112 struct wm_sampler_key
{
115 struct wm_sampler_entry
{
117 GLenum wrap_r
, wrap_s
, wrap_t
;
119 float maxlod
, minlod
;
122 GLenum minfilter
, magfilter
;
123 GLenum comparemode
, comparefunc
;
125 /** If target is cubemap, take context setting.
127 GLboolean seamless_cube_map
;
128 } sampler
[BRW_MAX_TEX_UNIT
];
132 * Sets the sampler state for a single unit based off of the sampler key
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
)
140 struct intel_context
*intel
= &brw
->intel
;
142 memset(sampler
, 0, sizeof(*sampler
));
144 switch (key
->minfilter
) {
146 sampler
->ss0
.min_filter
= BRW_MAPFILTER_NEAREST
;
147 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_NONE
;
150 sampler
->ss0
.min_filter
= BRW_MAPFILTER_LINEAR
;
151 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_NONE
;
153 case GL_NEAREST_MIPMAP_NEAREST
:
154 sampler
->ss0
.min_filter
= BRW_MAPFILTER_NEAREST
;
155 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_NEAREST
;
157 case GL_LINEAR_MIPMAP_NEAREST
:
158 sampler
->ss0
.min_filter
= BRW_MAPFILTER_LINEAR
;
159 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_NEAREST
;
161 case GL_NEAREST_MIPMAP_LINEAR
:
162 sampler
->ss0
.min_filter
= BRW_MAPFILTER_NEAREST
;
163 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_LINEAR
;
165 case GL_LINEAR_MIPMAP_LINEAR
:
166 sampler
->ss0
.min_filter
= BRW_MAPFILTER_LINEAR
;
167 sampler
->ss0
.mip_filter
= BRW_MIPFILTER_LINEAR
;
175 if (key
->max_aniso
> 1.0) {
176 sampler
->ss0
.min_filter
= BRW_MAPFILTER_ANISOTROPIC
;
177 sampler
->ss0
.mag_filter
= BRW_MAPFILTER_ANISOTROPIC
;
179 if (key
->max_aniso
> 2.0) {
180 sampler
->ss3
.max_aniso
= MIN2((key
->max_aniso
- 2) / 2,
185 switch (key
->magfilter
) {
187 sampler
->ss0
.mag_filter
= BRW_MAPFILTER_NEAREST
;
190 sampler
->ss0
.mag_filter
= BRW_MAPFILTER_LINEAR
;
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
);
201 if (intel
->gen
>= 6 &&
202 sampler
->ss0
.min_filter
!= sampler
->ss0
.mag_filter
)
203 sampler
->ss0
.min_mag_neq
= 1;
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.
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
;
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
;
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.
225 sampler
->ss1
.t_wrap_mode
= BRW_TEXCOORDMODE_WRAP
;
229 /* Set shadow function:
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.
236 sampler
->ss0
.shadow_function
=
237 intel_translate_shadow_compare_func(key
->comparefunc
);
242 sampler
->ss0
.lod_bias
= S_FIXED(CLAMP(key
->lod_bias
, -16, 15), 6);
244 sampler
->ss0
.lod_preclamp
= 1; /* OpenGL mode */
245 sampler
->ss0
.default_color_mode
= 0; /* OpenGL/DX10 mode */
247 sampler
->ss0
.base_level
= U_FIXED(key
->base_level
, 1);
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);
252 sampler
->ss2
.default_color_pointer
= sdc_bo
->offset
>> 5; /* reloc */
256 /** Sets up the cache key for sampler state for all texture units */
258 brw_wm_sampler_populate_key(struct brw_context
*brw
,
259 struct wm_sampler_key
*key
)
261 struct gl_context
*ctx
= &brw
->intel
.ctx
;
263 char *last_entry_end
= ((char*)&key
->sampler_count
) +
264 sizeof(key
->sampler_count
);
266 key
->sampler_count
= 0;
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
];
276 memset(last_entry_end
, 0,
277 (char*)entry
- last_entry_end
+ sizeof(*entry
));
278 last_entry_end
= ((char*)entry
) + sizeof(*entry
);
280 entry
->tex_target
= texObj
->Target
;
282 entry
->seamless_cube_map
= (texObj
->Target
== GL_TEXTURE_CUBE_MAP
)
283 ? ctx
->Texture
.CubeMapSeamless
: GL_FALSE
;
285 entry
->wrap_r
= texObj
->WrapR
;
286 entry
->wrap_s
= texObj
->WrapS
;
287 entry
->wrap_t
= texObj
->WrapT
;
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
;
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]
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.
311 brw
->wm
.sdc_bo
[unit
] = upload_default_color(brw
, bordercolor
);
313 brw
->wm
.sdc_bo
[unit
] = upload_default_color(brw
,
314 texObj
->BorderColor
.f
);
316 key
->sampler_count
= unit
+ 1;
319 struct wm_sampler_entry
*entry
= &key
->sampler
[key
->sampler_count
];
320 memset(last_entry_end
, 0, (char*)entry
- last_entry_end
);
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.
327 static void upload_wm_samplers( struct brw_context
*brw
)
329 struct gl_context
*ctx
= &brw
->intel
.ctx
;
330 struct wm_sampler_key key
;
331 int i
, sampler_key_size
;
333 brw_wm_sampler_populate_key(brw
, &key
);
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
;
340 drm_intel_bo_unreference(brw
->wm
.sampler_bo
);
341 brw
->wm
.sampler_bo
= NULL
;
342 if (brw
->wm
.sampler_count
== 0)
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
,
353 /* If we didnt find it in the cache, compute the state and put it in the
356 if (brw
->wm
.sampler_bo
== NULL
) {
357 struct brw_sampler_state sampler
[BRW_MAX_TEX_UNIT
];
359 memset(sampler
, 0, sizeof(sampler
));
360 for (i
= 0; i
< key
.sampler_count
; i
++) {
361 if (brw
->wm
.sdc_bo
[i
] == NULL
)
364 brw_update_sampler_state(brw
, &key
.sampler
[i
], brw
->wm
.sdc_bo
[i
],
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
));
373 /* Emit SDC relocations */
374 for (i
= 0; i
< BRW_MAX_TEX_UNIT
; i
++) {
375 if (!ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
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);
387 const struct brw_tracked_state brw_wm_samplers
= {
389 .mesa
= _NEW_TEXTURE
,
393 .prepare
= upload_wm_samplers
,