3ef9fcce347e8507b9fcbfbf51b24f492a2586e7
[mesa.git] / src / gallium / drivers / nvfx / nvfx_fragtex.c
1 #include "nvfx_context.h"
2 #include "nvfx_resource.h"
3 #include "nvfx_tex.h"
4
5 static void *
6 nvfx_sampler_state_create(struct pipe_context *pipe,
7 const struct pipe_sampler_state *cso)
8 {
9 struct nvfx_context *nvfx = nvfx_context(pipe);
10 struct nvfx_sampler_state *ps;
11
12 ps = MALLOC(sizeof(struct nvfx_sampler_state));
13
14 /* on nv30, we use this as an internal flag */
15 ps->fmt = cso->normalized_coords ? 0 : NV40_3D_TEX_FORMAT_RECT;
16 ps->en = 0;
17 ps->filt = nvfx_tex_filter(cso) | 0x2000; /*voodoo*/
18 ps->wrap = (nvfx_tex_wrap_mode(cso->wrap_s) << NV30_3D_TEX_WRAP_S__SHIFT) |
19 (nvfx_tex_wrap_mode(cso->wrap_t) << NV30_3D_TEX_WRAP_T__SHIFT) |
20 (nvfx_tex_wrap_mode(cso->wrap_r) << NV30_3D_TEX_WRAP_R__SHIFT);
21 ps->compare = FALSE;
22
23 if(cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE)
24 {
25 ps->wrap |= nvfx_tex_wrap_compare_mode(cso->compare_func);
26 ps->compare = TRUE;
27 }
28 ps->bcol = nvfx_tex_border_color(cso->border_color.f);
29
30 if(nvfx->is_nv4x)
31 nv40_sampler_state_init(pipe, ps, cso);
32 else
33 nv30_sampler_state_init(pipe, ps, cso);
34
35 return (void *)ps;
36 }
37
38 static void
39 nvfx_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
40 {
41 FREE(hwcso);
42 }
43
44 static void
45 nvfx_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
46 {
47 struct nvfx_context *nvfx = nvfx_context(pipe);
48 unsigned unit;
49
50 for (unit = 0; unit < nr; unit++) {
51 nvfx->tex_sampler[unit] = sampler[unit];
52 nvfx->dirty_samplers |= (1 << unit);
53 }
54
55 for (unit = nr; unit < nvfx->nr_samplers; unit++) {
56 nvfx->tex_sampler[unit] = NULL;
57 nvfx->dirty_samplers |= (1 << unit);
58 }
59
60 nvfx->nr_samplers = nr;
61 nvfx->dirty |= NVFX_NEW_SAMPLER;
62 }
63
64 static struct pipe_sampler_view *
65 nvfx_create_sampler_view(struct pipe_context *pipe,
66 struct pipe_resource *pt,
67 const struct pipe_sampler_view *templ)
68 {
69 struct nvfx_context *nvfx = nvfx_context(pipe);
70 struct nvfx_sampler_view *sv = CALLOC_STRUCT(nvfx_sampler_view);
71 struct nvfx_texture_format *tf = &nvfx_texture_formats[templ->format];
72 unsigned txf;
73
74 if (!sv)
75 return NULL;
76
77 sv->base = *templ;
78 sv->base.reference.count = 1;
79 sv->base.texture = NULL;
80 pipe_resource_reference(&sv->base.texture, pt);
81 sv->base.context = pipe;
82
83 txf = NV30_3D_TEX_FORMAT_NO_BORDER;
84
85 switch (pt->target) {
86 case PIPE_TEXTURE_CUBE:
87 txf |= NV30_3D_TEX_FORMAT_CUBIC;
88 /* fall-through */
89 case PIPE_TEXTURE_2D:
90 case PIPE_TEXTURE_RECT:
91 txf |= NV30_3D_TEX_FORMAT_DIMS_2D;
92 break;
93 case PIPE_TEXTURE_3D:
94 txf |= NV30_3D_TEX_FORMAT_DIMS_3D;
95 break;
96 case PIPE_TEXTURE_1D:
97 txf |= NV30_3D_TEX_FORMAT_DIMS_1D;
98 break;
99 default:
100 assert(0);
101 }
102 sv->u.init_fmt = txf;
103
104 sv->swizzle = 0
105 | (tf->src[sv->base.swizzle_r] << NV30_3D_TEX_SWIZZLE_S0_Z__SHIFT)
106 | (tf->src[sv->base.swizzle_g] << NV30_3D_TEX_SWIZZLE_S0_Y__SHIFT)
107 | (tf->src[sv->base.swizzle_b] << NV30_3D_TEX_SWIZZLE_S0_X__SHIFT)
108 | (tf->src[sv->base.swizzle_a] << NV30_3D_TEX_SWIZZLE_S0_W__SHIFT)
109 | (tf->comp[sv->base.swizzle_r] << NV30_3D_TEX_SWIZZLE_S1_Z__SHIFT)
110 | (tf->comp[sv->base.swizzle_g] << NV30_3D_TEX_SWIZZLE_S1_Y__SHIFT)
111 | (tf->comp[sv->base.swizzle_b] << NV30_3D_TEX_SWIZZLE_S1_X__SHIFT)
112 | (tf->comp[sv->base.swizzle_a] << NV30_3D_TEX_SWIZZLE_S1_W__SHIFT);
113
114 sv->filt = tf->sign;
115 sv->wrap = tf->wrap;
116 sv->wrap_mask = ~0;
117
118 if (pt->target == PIPE_TEXTURE_CUBE)
119 {
120 sv->offset = 0;
121 sv->npot_size = (pt->width0 << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | pt->height0;
122 }
123 else
124 {
125 sv->offset = nvfx_subresource_offset(pt, 0, sv->base.u.tex.first_level, 0);
126 sv->npot_size = (u_minify(pt->width0, sv->base.u.tex.first_level) << NV30_3D_TEX_NPOT_SIZE_W__SHIFT) | u_minify(pt->height0, sv->base.u.tex.first_level);
127
128 /* apparently, we need to ignore the t coordinate for 1D textures to fix piglit tex1d-2dborder */
129 if(pt->target == PIPE_TEXTURE_1D)
130 {
131 sv->wrap_mask &=~ NV30_3D_TEX_WRAP_T__MASK;
132 sv->wrap |= NV30_3D_TEX_WRAP_T_REPEAT;
133 }
134 }
135
136 if(nvfx->is_nv4x)
137 nv40_sampler_view_init(pipe, sv);
138 else
139 nv30_sampler_view_init(pipe, sv);
140
141 return &sv->base;
142 }
143
144 static void
145 nvfx_sampler_view_destroy(struct pipe_context *pipe,
146 struct pipe_sampler_view *view)
147 {
148 pipe_resource_reference(&view->texture, NULL);
149 FREE(view);
150 }
151
152 static void
153 nvfx_set_fragment_sampler_views(struct pipe_context *pipe,
154 unsigned nr,
155 struct pipe_sampler_view **views)
156 {
157 struct nvfx_context *nvfx = nvfx_context(pipe);
158 unsigned unit;
159
160 for (unit = 0; unit < nr; unit++) {
161 pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit],
162 views[unit]);
163 nvfx->dirty_samplers |= (1 << unit);
164 }
165
166 for (unit = nr; unit < nvfx->nr_textures; unit++) {
167 pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit],
168 NULL);
169 nvfx->dirty_samplers |= (1 << unit);
170 }
171
172 nvfx->nr_textures = nr;
173 nvfx->dirty |= NVFX_NEW_SAMPLER;
174 }
175
176 void
177 nvfx_fragtex_validate(struct nvfx_context *nvfx)
178 {
179 struct nouveau_channel* chan = nvfx->screen->base.channel;
180 struct nouveau_grobj *eng3d = nvfx->screen->eng3d;
181 unsigned samplers, unit;
182
183 samplers = nvfx->dirty_samplers;
184 if(!samplers)
185 return;
186
187 while (samplers) {
188 unit = ffs(samplers) - 1;
189 samplers &= ~(1 << unit);
190
191 if(nvfx->fragment_sampler_views[unit] && nvfx->tex_sampler[unit]) {
192 util_dirty_surfaces_use_for_sampling(&nvfx->pipe,
193 &((struct nvfx_miptree*)nvfx->fragment_sampler_views[unit]->texture)->dirty_surfaces,
194 nvfx_surface_flush);
195
196 if(!nvfx->is_nv4x)
197 nv30_fragtex_set(nvfx, unit);
198 else
199 nv40_fragtex_set(nvfx, unit);
200 } else {
201 /* this is OK for nv40 too */
202 BEGIN_RING(chan, eng3d, NV30_3D_TEX_ENABLE(unit), 1);
203 OUT_RING(chan, 0);
204 nvfx->hw_samplers &= ~(1 << unit);
205 }
206 }
207 nvfx->dirty_samplers = 0;
208 nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGTEX;
209 }
210
211 void
212 nvfx_fragtex_relocate(struct nvfx_context *nvfx)
213 {
214 struct nouveau_channel* chan = nvfx->screen->base.channel;
215 unsigned samplers, unit;
216 unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
217
218 samplers = nvfx->hw_samplers;
219 while (samplers) {
220 struct nvfx_miptree* mt;
221 struct nouveau_bo *bo;
222
223 unit = ffs(samplers) - 1;
224 samplers &= ~(1 << unit);
225
226 mt = (struct nvfx_miptree*)nvfx->fragment_sampler_views[unit]->texture;
227 bo = mt->base.bo;
228
229 MARK_RING(chan, 3, 3);
230 OUT_RELOC(chan, bo, RING_3D(NV30_3D_TEX_OFFSET(unit), 2), tex_flags | NOUVEAU_BO_DUMMY, 0, 0);
231 OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_DUMMY, 0, 0);
232 OUT_RELOC(chan, bo, nvfx->hw_txf[unit], tex_flags | NOUVEAU_BO_OR | NOUVEAU_BO_DUMMY,
233 NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
234 }
235 nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGTEX;
236 }
237
238 void
239 nvfx_init_sampling_functions(struct nvfx_context *nvfx)
240 {
241 nvfx->pipe.create_sampler_state = nvfx_sampler_state_create;
242 nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind;
243 nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete;
244 nvfx->pipe.set_fragment_sampler_views = nvfx_set_fragment_sampler_views;
245 nvfx->pipe.create_sampler_view = nvfx_create_sampler_view;
246 nvfx->pipe.sampler_view_destroy = nvfx_sampler_view_destroy;
247 }
248
249 #define NV30_3D_TEX_FORMAT_FORMAT_DXT1_RECT NV30_3D_TEX_FORMAT_FORMAT_DXT1
250 #define NV30_3D_TEX_FORMAT_FORMAT_DXT3_RECT NV30_3D_TEX_FORMAT_FORMAT_DXT3
251 #define NV30_3D_TEX_FORMAT_FORMAT_DXT5_RECT NV30_3D_TEX_FORMAT_FORMAT_DXT5
252
253 #define NV40_3D_TEX_FORMAT_FORMAT_HILO16 NV40_3D_TEX_FORMAT_FORMAT_A16L16
254
255 #define NV30_3D_TEX_FORMAT_FORMAT_RGBA16F 0x00004a00
256 #define NV30_3D_TEX_FORMAT_FORMAT_RGBA16F_RECT NV30_3D_TEX_FORMAT_FORMAT_RGBA16F
257 #define NV30_3D_TEX_FORMAT_FORMAT_RGBA32F 0x00004b00
258 #define NV30_3D_TEX_FORMAT_FORMAT_RGBA32F_RECT NV30_3D_TEX_FORMAT_FORMAT_RGBA32F
259 #define NV30_3D_TEX_FORMAT_FORMAT_R32F 0x00004c00
260 #define NV30_3D_TEX_FORMAT_FORMAT_R32F_RECT NV30_3D_TEX_FORMAT_FORMAT_R32F
261
262 // TODO: guess!
263 #define NV40_3D_TEX_FORMAT_FORMAT_R32F 0x00001c00
264
265 #define SRGB 0x00700000
266
267 #define __(m,tf,tfc,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign,wrap) \
268 [PIPE_FORMAT_##m] = { \
269 {NV30_3D_TEX_FORMAT_FORMAT_##tf, \
270 NV30_3D_TEX_FORMAT_FORMAT_##tfc, \
271 NV30_3D_TEX_FORMAT_FORMAT_##tf##_RECT, \
272 NV30_3D_TEX_FORMAT_FORMAT_##tfc##_RECT, \
273 NV40_3D_TEX_FORMAT_FORMAT_##tf, \
274 NV40_3D_TEX_FORMAT_FORMAT_##tfc}, \
275 sign, wrap, \
276 {ts0z, ts0y, ts0x, ts0w, 0, 1}, {ts1z, ts1y, ts1x, ts1w, 0, 0} \
277 }
278
279 #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign, wrap) \
280 __(m,tf,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign, wrap)
281
282 /* Depth formats works by reading the depth value most significant 8/16 bits.
283 * We are losing precision, but nVidia loses even more by using A8R8G8B8 instead of HILO16
284 * There is no 32-bit integer texture support, so other things are infeasible.
285 *
286 * TODO: is it possible to read 16 bits for Z16? A16 doesn't seem to work, either due to normalization or endianness issues
287 */
288
289 #define T 2
290
291 #define X 3
292 #define Y 2
293 #define Z 1
294 #define W 0
295
296 #define SNORM ((NV30_3D_TEX_FILTER_SIGNED_RED) | (NV30_3D_TEX_FILTER_SIGNED_GREEN) | (NV30_3D_TEX_FILTER_SIGNED_BLUE) | (NV30_3D_TEX_FILTER_SIGNED_ALPHA))
297 #define UNORM 0
298
299 struct nvfx_texture_format
300 nvfx_texture_formats[PIPE_FORMAT_COUNT] = {
301 [0 ... PIPE_FORMAT_COUNT - 1] = {{-1, -1, -1, -1, -1, -1}},
302 _(B8G8R8X8_UNORM, A8R8G8B8, T, T, T, 1, X, Y, Z, W, UNORM, 0),
303 _(B8G8R8X8_SRGB, A8R8G8B8, T, T, T, 1, X, Y, Z, W, UNORM, SRGB),
304 _(B8G8R8A8_UNORM, A8R8G8B8, T, T, T, T, X, Y, Z, W, UNORM, 0),
305 _(B8G8R8A8_SRGB, A8R8G8B8, T, T, T, T, X, Y, Z, W, UNORM, SRGB),
306
307 _(R8G8B8A8_UNORM, A8R8G8B8, T, T, T, T, Z, Y, X, W, UNORM, 0),
308 _(R8G8B8A8_SRGB, A8R8G8B8, T, T, T, T, Z, Y, X, W, UNORM, SRGB),
309 _(R8G8B8X8_UNORM, A8R8G8B8, T, T, T, 1, Z, Y, X, W, UNORM, 0),
310
311 _(A8R8G8B8_UNORM, A8R8G8B8, T, T, T, T, W, Z, Y, X, UNORM, 0),
312 _(A8R8G8B8_SRGB, A8R8G8B8, T, T, T, T, W, Z, Y, X, UNORM, SRGB),
313 _(A8B8G8R8_UNORM, A8R8G8B8, T, T, T, T, W, X, Y, Z, UNORM, 0),
314 _(A8B8G8R8_SRGB, A8R8G8B8, T, T, T, T, W, X, Y, Z, UNORM, SRGB),
315 _(X8R8G8B8_UNORM, A8R8G8B8, T, T, T, 1, W, Z, Y, X, UNORM, 0),
316 _(X8R8G8B8_SRGB, A8R8G8B8, T, T, T, 1, W, Z, Y, X, UNORM, SRGB),
317
318 _(B5G5R5A1_UNORM, A1R5G5B5, T, T, T, T, X, Y, Z, W, UNORM, 0),
319 _(B5G5R5X1_UNORM, A1R5G5B5, T, T, T, 1, X, Y, Z, W, UNORM, 0),
320
321 _(B4G4R4A4_UNORM, A4R4G4B4, T, T, T, T, X, Y, Z, W, UNORM, 0),
322 _(B4G4R4X4_UNORM, A4R4G4B4, T, T, T, 1, X, Y, Z, W, UNORM, 0),
323
324 _(B5G6R5_UNORM, R5G6B5, T, T, T, 1, X, Y, Z, W, UNORM, 0),
325
326 _(R8_UNORM, L8, T, 0, 0, 1, X, X, X, X, UNORM, 0),
327 _(R8_SNORM, L8, T, 0, 0, 1, X, X, X, X, SNORM, 0),
328 _(L8_UNORM, L8, T, T, T, 1, X, X, X, X, UNORM, 0),
329 _(L8_SRGB, L8, T, T, T, 1, X, X, X, X, UNORM, SRGB),
330 _(A8_UNORM, L8, 0, 0, 0, T, X, X, X, X, UNORM, 0),
331 _(I8_UNORM, L8, T, T, T, T, X, X, X, X, UNORM, 0),
332
333 _(R8G8_UNORM, A8L8, T, T, T, T, X, X, X, W, UNORM, 0),
334 _(R8G8_SNORM, A8L8, T, T, T, T, X, X, X, W, SNORM, 0),
335 _(L8A8_UNORM, A8L8, T, T, T, T, X, X, X, W, UNORM, 0),
336 _(L8A8_SRGB, A8L8, T, T, T, T, X, X, X, W, UNORM, SRGB),
337
338 _(DXT1_RGB, DXT1, T, T, T, 1, X, Y, Z, W, UNORM, 0),
339 _(DXT1_SRGB, DXT1, T, T, T, 1, X, Y, Z, W, UNORM, SRGB),
340 _(DXT1_RGBA, DXT1, T, T, T, T, X, Y, Z, W, UNORM, 0),
341 _(DXT1_SRGBA, DXT1, T, T, T, T, X, Y, Z, W, UNORM, SRGB),
342 _(DXT3_RGBA, DXT3, T, T, T, T, X, Y, Z, W, UNORM, 0),
343 _(DXT3_SRGBA, DXT3, T, T, T, T, X, Y, Z, W, UNORM, SRGB),
344 _(DXT5_RGBA, DXT5, T, T, T, T, X, Y, Z, W, UNORM, 0),
345 _(DXT5_SRGBA, DXT5, T, T, T, T, X, Y, Z, W, UNORM, SRGB),
346
347 __(Z16_UNORM, A8L8, Z16, T, T, T, 1, W, W, W, W, UNORM, 0),
348 __(S8_USCALED_Z24_UNORM,HILO16,Z24, T, T, T, 1, W, W, W, W, UNORM, 0),
349 __(X8Z24_UNORM, HILO16,Z24, T, T, T, 1, W, W, W, W, UNORM, 0),
350
351 _(R16_UNORM, A16, T, 0, 0, 1, X, X, X, X, UNORM, 0),
352 _(R16_SNORM, A16, T, 0, 0, 1, X, X, X, X, SNORM, 0),
353 _(R16G16_UNORM, HILO16, T, T, 0, 1, X, Y, X, X, UNORM, 0),
354 _(R16G16_SNORM, HILO16, T, T, 0, 1, X, Y, X, X, SNORM, 0),
355
356 _(R16G16B16A16_FLOAT, RGBA16F, T, T, T, T, X, Y, Z, W, UNORM, 0),
357 _(R32G32B32A32_FLOAT, RGBA32F, T, T, T, T, X, Y, Z, W, UNORM, 0),
358 _(R32_FLOAT, R32F, T, 0, 0, 1, X, X, X, X, UNORM, 0)
359 };