Add support for more surface types in sp_surface.c
[mesa.git] / src / mesa / pipe / i915simple / i915_state_sampler.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * 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, sub license, 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 portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 //#include "mtypes.h"
29 //#include "enums.h"
30 //#include "texformat.h"
31 //#include "macros.h"
32 //#include "dri_bufmgr.h"
33
34
35 #include "pipe/p_context.h"
36 #include "pipe/p_state.h"
37 #include "pipe/p_util.h"
38
39 #include "i915_state_inlines.h"
40 #include "i915_context.h"
41 #include "i915_reg.h"
42 #include "i915_state.h"
43 //#include "i915_cache.h"
44
45
46
47
48
49
50 /* The i915 (and related graphics cores) do not support GL_CLAMP. The
51 * Intel drivers for "other operating systems" implement GL_CLAMP as
52 * GL_CLAMP_TO_EDGE, so the same is done here.
53 */
54 static unsigned
55 translate_wrap_mode(unsigned wrap)
56 {
57 switch (wrap) {
58 case PIPE_TEX_WRAP_REPEAT:
59 return TEXCOORDMODE_WRAP;
60 case PIPE_TEX_WRAP_CLAMP:
61 return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
62 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
63 return TEXCOORDMODE_CLAMP_EDGE;
64 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
65 return TEXCOORDMODE_CLAMP_BORDER;
66 // case PIPE_TEX_WRAP_MIRRORED_REPEAT:
67 // return TEXCOORDMODE_MIRROR;
68 default:
69 return TEXCOORDMODE_WRAP;
70 }
71 }
72
73 static unsigned translate_img_filter( unsigned filter )
74 {
75 switch (filter) {
76 case PIPE_TEX_FILTER_NEAREST:
77 return FILTER_NEAREST;
78 case PIPE_TEX_FILTER_LINEAR:
79 return FILTER_LINEAR;
80 default:
81 assert(0);
82 return FILTER_NEAREST;
83 }
84 }
85
86 static unsigned translate_mip_filter( unsigned filter )
87 {
88 switch (filter) {
89 case PIPE_TEX_MIPFILTER_NONE:
90 return MIPFILTER_NONE;
91 case PIPE_TEX_MIPFILTER_NEAREST:
92 return MIPFILTER_NEAREST;
93 case PIPE_TEX_FILTER_LINEAR:
94 return MIPFILTER_LINEAR;
95 default:
96 assert(0);
97 return MIPFILTER_NONE;
98 }
99 }
100
101 static unsigned translate_compare_func(unsigned func)
102 {
103 switch (func) {
104 case PIPE_FUNC_NEVER:
105 case PIPE_FUNC_LESS:
106 case PIPE_FUNC_EQUAL:
107 case PIPE_FUNC_LEQUAL:
108 case PIPE_FUNC_GREATER:
109 case PIPE_FUNC_NOTEQUAL:
110 case PIPE_FUNC_GEQUAL:
111 case PIPE_FUNC_ALWAYS:
112 return 0;
113 default:
114 assert(0);
115 return 0;
116 }
117 }
118
119
120 static uint
121 bitcount(uint k)
122 {
123 uint count = 0;
124 while (k) {
125 if (k & 1)
126 count++;
127 k = k >> 1;
128 }
129 return count;
130 }
131
132
133 static boolean
134 is_power_of_two_texture(const struct pipe_mipmap_tree *mt)
135 {
136 if (bitcount(mt->width0) == 1 &&
137 bitcount(mt->height0) == 1 &&
138 bitcount(mt->depth0) == 1) {
139 return 1;
140 }
141 else
142 return 0;
143 }
144
145
146 /**
147 * Compute i915 texture sampling state.
148 *
149 * Recalculate all state from scratch. Perhaps not the most
150 * efficient, but this has gotten complex enough that we need
151 * something which is understandable and reliable.
152 * \param state returns the 3 words of compute state
153 */
154 static void update_sampler(struct i915_context *i915,
155 uint unit,
156 const struct pipe_sampler_state *sampler,
157 const struct pipe_mipmap_tree *mt,
158 unsigned state[3] )
159 {
160 const unsigned ws = sampler->wrap_s;
161 const unsigned wt = sampler->wrap_t;
162 const unsigned wr = sampler->wrap_r;
163
164 /* Need to do this after updating the maps, which call the
165 * intel_finalize_mipmap_tree and hence can update firstLevel:
166 */
167 unsigned minFilt, magFilt;
168 unsigned mipFilt;
169
170 state[0] = state[1] = state[2] = 0;
171
172 mipFilt = translate_mip_filter( sampler->min_mip_filter );
173
174 if (sampler->max_anisotropy > 1.0) {
175 minFilt = FILTER_ANISOTROPIC;
176 magFilt = FILTER_ANISOTROPIC;
177 }
178 else {
179 minFilt = translate_img_filter( sampler->min_img_filter );
180 magFilt = translate_img_filter( sampler->mag_img_filter );
181 }
182
183 {
184 int b = sampler->lod_bias * 16.0;
185 b = CLAMP(b, -256, 255);
186 state[0] |= ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
187 }
188
189 if (mt->format == PIPE_FORMAT_YCBCR ||
190 mt->format == PIPE_FORMAT_YCBCR_REV)
191 state[0] |= SS2_COLORSPACE_CONVERSION;
192
193
194 /* Shadow:
195 */
196 if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE)
197 {
198 state[0] |= (SS2_SHADOW_ENABLE |
199 translate_compare_func(sampler->compare_func));
200
201 minFilt = FILTER_4X4_FLAT;
202 magFilt = FILTER_4X4_FLAT;
203 }
204
205 state[0] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
206 (mipFilt << SS2_MIP_FILTER_SHIFT) |
207 (magFilt << SS2_MAG_FILTER_SHIFT));
208
209
210 /* 3D textures don't seem to respect the border color.
211 * Fallback if there's ever a danger that they might refer to
212 * it.
213 *
214 * Effectively this means fallback on 3D clamp or
215 * clamp_to_border.
216 *
217 * XXX: Check if this is true on i945.
218 * XXX: Check if this bug got fixed in release silicon.
219 */
220 if (mt->target == PIPE_TEXTURE_3D &&
221 (sampler->min_img_filter != PIPE_TEX_FILTER_NEAREST ||
222 sampler->mag_img_filter != PIPE_TEX_FILTER_NEAREST) &&
223 (ws == PIPE_TEX_WRAP_CLAMP ||
224 wt == PIPE_TEX_WRAP_CLAMP ||
225 wr == PIPE_TEX_WRAP_CLAMP ||
226 ws == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||
227 wt == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||
228 wr == PIPE_TEX_WRAP_CLAMP_TO_BORDER)) {
229 #if 0
230 if (i915->strict_conformance) {
231 assert(0);
232 /* sampler->fallback = true; */
233 /* TODO */
234 }
235 #endif
236 }
237
238 state[1] =
239 ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) |
240 (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
241 (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT) |
242 (unit << SS3_TEXTUREMAP_INDEX_SHIFT));
243
244 if (is_power_of_two_texture(mt)) {
245 state[1] |= SS3_NORMALIZED_COORDS;
246 }
247
248 {
249 ubyte r = float_to_ubyte(sampler->border_color[0]);
250 ubyte g = float_to_ubyte(sampler->border_color[1]);
251 ubyte b = float_to_ubyte(sampler->border_color[2]);
252 ubyte a = float_to_ubyte(sampler->border_color[3]);
253 state[2] = I915PACKCOLOR8888(r, g, b, a);
254 }
255 }
256
257
258
259 void i915_update_samplers( struct i915_context *i915 )
260 {
261 uint unit;
262
263 i915->current.sampler_enable_nr = 0;
264 i915->current.sampler_enable_flags = 0x0;
265
266 for (unit = 0; unit < I915_TEX_UNITS; unit++) {
267 /* determine unit enable/disable by looking for a bound mipmap tree */
268 /* could also examine the fragment program? */
269 if (i915->texture[unit]) {
270 update_sampler( i915,
271 unit,
272 i915->sampler + unit, /* sampler state */
273 i915->texture[unit], /* mipmap tree */
274 i915->current.sampler[unit] /* the result */
275 );
276
277 i915->current.sampler_enable_nr++;
278 i915->current.sampler_enable_flags |= (1 << unit);
279 }
280 }
281
282 i915->hardware_dirty |= I915_HW_SAMPLER;
283 }
284
285
286
287
288 static uint
289 translate_texture_format(uint pipeFormat)
290 {
291 switch (pipeFormat) {
292 case PIPE_FORMAT_U_L8:
293 return MAPSURF_8BIT | MT_8BIT_L8;
294 case PIPE_FORMAT_U_I8:
295 return MAPSURF_8BIT | MT_8BIT_I8;
296 case PIPE_FORMAT_U_A8:
297 return MAPSURF_8BIT | MT_8BIT_A8;
298 case PIPE_FORMAT_U_A8_L8:
299 return MAPSURF_16BIT | MT_16BIT_AY88;
300 case PIPE_FORMAT_U_R5_G6_B5:
301 return MAPSURF_16BIT | MT_16BIT_RGB565;
302 case PIPE_FORMAT_U_A1_R5_G5_B5:
303 return MAPSURF_16BIT | MT_16BIT_ARGB1555;
304 case PIPE_FORMAT_U_A4_R4_G4_B4:
305 return MAPSURF_16BIT | MT_16BIT_ARGB4444;
306 case PIPE_FORMAT_U_A8_R8_G8_B8:
307 return MAPSURF_32BIT | MT_32BIT_ARGB8888;
308 case PIPE_FORMAT_YCBCR_REV:
309 return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
310 case PIPE_FORMAT_YCBCR:
311 return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
312 #if 0
313 case PIPE_FORMAT_RGB_FXT1:
314 case PIPE_FORMAT_RGBA_FXT1:
315 return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
316 #endif
317 case PIPE_FORMAT_U_Z16:
318 return (MAPSURF_16BIT | MT_16BIT_L16);
319 #if 0
320 case PIPE_FORMAT_RGBA_DXT1:
321 case PIPE_FORMAT_RGB_DXT1:
322 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
323 case PIPE_FORMAT_RGBA_DXT3:
324 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
325 case PIPE_FORMAT_RGBA_DXT5:
326 return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
327 #endif
328 case PIPE_FORMAT_S8_Z24:
329 return (MAPSURF_32BIT | MT_32BIT_xL824);
330 default:
331 fprintf(stderr, "i915: translate_texture_format() bad image format %x\n",
332 pipeFormat);
333 assert(0);
334 return 0;
335 }
336 }
337
338
339 #define I915_TEXREG_MS3 1
340 #define I915_TEXREG_MS4 2
341
342
343 static void
344 i915_update_texture(struct i915_context *i915, uint unit,
345 uint state[6])
346 {
347 const struct pipe_mipmap_tree *mt = i915->texture[unit];
348 uint format, pitch;
349 const uint width = mt->width0, height = mt->height0, depth = mt->depth0;
350 const uint num_levels = mt->last_level - mt->first_level;
351
352 assert(mt);
353 assert(width);
354 assert(height);
355 assert(depth);
356
357 #if 0
358 if (i915->state.tex_buffer[unit] != NULL) {
359 driBOUnReference(i915->state.tex_buffer[unit]);
360 i915->state.tex_buffer[unit] = NULL;
361 }
362 #endif
363
364
365 {
366 struct pipe_buffer_handle *p = driBOReference(mt->region->buffer);
367 }
368
369 #if 0
370 i915->state.tex_buffer[unit] = driBOReference(intelObj->mt->region->
371 buffer);
372 i915->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt,
373 0, intelObj->
374 firstLevel);
375 #endif
376
377 format = translate_texture_format(mt->format);
378 pitch = mt->pitch * mt->cpp;
379
380 assert(format);
381 assert(pitch);
382
383 printf("texture format = 0x%x\n", format);
384
385 /* MS3 state */
386 state[0] =
387 (((height - 1) << MS3_HEIGHT_SHIFT)
388 | ((width - 1) << MS3_WIDTH_SHIFT)
389 | format
390 | MS3_USE_FENCE_REGS);
391
392 /* MS4 state */
393 state[1] =
394 ((((pitch / 4) - 1) << MS4_PITCH_SHIFT)
395 | MS4_CUBE_FACE_ENA_MASK
396 | ((num_levels * 4) << MS4_MAX_LOD_SHIFT)
397 | ((depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
398 }
399
400
401
402 void
403 i915_update_textures(struct i915_context *i915)
404 {
405 uint unit;
406
407 for (unit = 0; unit < I915_TEX_UNITS; unit++) {
408 /* determine unit enable/disable by looking for a bound mipmap tree */
409 /* could also examine the fragment program? */
410 if (i915->texture[unit]) {
411 i915_update_texture(i915, unit, i915->current.texbuffer[unit]);
412 }
413 }
414
415 i915->hardware_dirty |= I915_HW_MAP;
416 }