Sampler state code now compiles and is built. Not tested yet.
[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_cache.h"
43
44
45
46
47
48
49 /* The i915 (and related graphics cores) do not support GL_CLAMP. The
50 * Intel drivers for "other operating systems" implement GL_CLAMP as
51 * GL_CLAMP_TO_EDGE, so the same is done here.
52 */
53 static unsigned
54 translate_wrap_mode(unsigned wrap)
55 {
56 switch (wrap) {
57 case PIPE_TEX_WRAP_REPEAT:
58 return TEXCOORDMODE_WRAP;
59 case PIPE_TEX_WRAP_CLAMP:
60 return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
61 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
62 return TEXCOORDMODE_CLAMP_EDGE;
63 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
64 return TEXCOORDMODE_CLAMP_BORDER;
65 // case PIPE_TEX_WRAP_MIRRORED_REPEAT:
66 // return TEXCOORDMODE_MIRROR;
67 default:
68 return TEXCOORDMODE_WRAP;
69 }
70 }
71
72 static unsigned translate_img_filter( unsigned filter )
73 {
74 switch (filter) {
75 case PIPE_TEX_FILTER_NEAREST:
76 return FILTER_NEAREST;
77 case PIPE_TEX_FILTER_LINEAR:
78 return FILTER_LINEAR;
79 default:
80 assert(0);
81 return FILTER_NEAREST;
82 }
83 }
84
85 static unsigned translate_mip_filter( unsigned filter )
86 {
87 switch (filter) {
88 case PIPE_TEX_MIPFILTER_NONE:
89 return MIPFILTER_NONE;
90 case PIPE_TEX_MIPFILTER_NEAREST:
91 return MIPFILTER_NEAREST;
92 case PIPE_TEX_FILTER_LINEAR:
93 return MIPFILTER_LINEAR;
94 default:
95 assert(0);
96 return MIPFILTER_NONE;
97 }
98 }
99
100 static unsigned translate_compare_func(unsigned func)
101 {
102 switch (func) {
103 case PIPE_FUNC_NEVER:
104 case PIPE_FUNC_LESS:
105 case PIPE_FUNC_EQUAL:
106 case PIPE_FUNC_LEQUAL:
107 case PIPE_FUNC_GREATER:
108 case PIPE_FUNC_NOTEQUAL:
109 case PIPE_FUNC_GEQUAL:
110 case PIPE_FUNC_ALWAYS:
111 return 0;
112 default:
113 assert(0);
114 return 0;
115 }
116 }
117
118
119 static uint
120 bitcount(uint k)
121 {
122 uint count = 0;
123 while (k) {
124 if (k & 1)
125 count++;
126 k = k >> 1;
127 }
128 return count;
129 }
130
131
132 static boolean
133 is_power_of_two_texture(const struct pipe_mipmap_tree *mt)
134 {
135 if (bitcount(mt->width0) == 1 &&
136 bitcount(mt->height0) == 1 &&
137 bitcount(mt->depth0) == 1) {
138 return 1;
139 }
140 else
141 return 0;
142 }
143
144
145 /**
146 * Compute i915 texture sampling state.
147 *
148 * Recalculate all state from scratch. Perhaps not the most
149 * efficient, but this has gotten complex enough that we need
150 * something which is understandable and reliable.
151 * \param state returns the 3 words of compute state
152 */
153 static void update_sampler(struct i915_context *i915,
154 uint unit,
155 const struct pipe_sampler_state *sampler,
156 const struct pipe_mipmap_tree *mt,
157 const struct pipe_surface *surface,
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 (surface->format == PIPE_FORMAT_YCBCR ||
190 surface->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 const struct pipe_surface *surface = i915->framebuffer.cbufs[0];
262 uint unit;
263
264 i915->current.sampler_enable_nr = 0;
265 i915->current.sampler_enable_flags = 0x0;
266
267 for (unit = 0; unit < I915_TEX_UNITS; unit++) {
268 /* determine unit enable/disable by looking for a bound mipmap tree */
269 /* could also examine the fragment program? */
270 if (i915->texture[unit]) {
271 update_sampler( i915,
272 unit,
273 i915->sampler + unit, /* sampler state */
274 i915->texture[unit], /* mipmap tree */
275 surface, /* cbuffer info */
276 i915->current.sampler[unit] /* the result */
277 );
278
279 i915->current.sampler_enable_nr++;
280 i915->current.sampler_enable_flags |= (1 << unit);
281 }
282 }
283
284 i915->hardware_dirty |= I915_HW_SAMPLER;
285 }