nv30, nv40: partially non-trivially unify nv[34]0_fragtex.c
[mesa.git] / src / gallium / drivers / nv30 / nv30_fragtex.c
1 #include "util/u_format.h"
2
3 #include "nvfx_context.h"
4 #include "nouveau/nouveau_util.h"
5
6 #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w) \
7 { \
8 TRUE, \
9 PIPE_FORMAT_##m, \
10 NV34TCL_TX_FORMAT_FORMAT_##tf, \
11 (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \
12 NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \
13 NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \
14 NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w) \
15 }
16
17 struct nv30_texture_format {
18 boolean defined;
19 uint pipe;
20 int format;
21 int swizzle;
22 };
23
24 static struct nv30_texture_format
25 nv30_texture_formats[] = {
26 _(B8G8R8X8_UNORM, A8R8G8B8, S1, S1, S1, ONE, X, Y, Z, W),
27 _(B8G8R8A8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W),
28 _(B5G5R5A1_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W),
29 _(B4G4R4A4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W),
30 _(B5G6R5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W),
31 _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X),
32 _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X),
33 _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X),
34 _(L8A8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y),
35 _(Z16_UNORM , R5G6B5 , S1, S1, S1, ONE, X, X, X, X),
36 _(S8Z24_UNORM , A8R8G8B8, S1, S1, S1, ONE, X, X, X, X),
37 _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W),
38 _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W),
39 _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W),
40 _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W),
41 {},
42 };
43
44 static struct nv30_texture_format *
45 nv30_fragtex_format(uint pipe_format)
46 {
47 struct nv30_texture_format *tf = nv30_texture_formats;
48
49 while (tf->defined) {
50 if (tf->pipe == pipe_format)
51 return tf;
52 tf++;
53 }
54
55 NOUVEAU_ERR("unknown texture format %s\n", util_format_name(pipe_format));
56 return NULL;
57 }
58
59
60 struct nouveau_stateobj *
61 nv30_fragtex_build(struct nvfx_context *nvfx, int unit)
62 {
63 struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
64 struct nvfx_miptree *nv30mt = nvfx->tex_miptree[unit];
65 struct pipe_texture *pt = &nv30mt->base;
66 struct nouveau_bo *bo = nouveau_bo(nv30mt->buffer);
67 struct nv30_texture_format *tf;
68 struct nouveau_stateobj *so;
69 uint32_t txf, txs;
70 unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
71
72 tf = nv30_fragtex_format(pt->format);
73 if (!tf)
74 return NULL;
75
76 txf = tf->format;
77 txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0);
78 txf |= log2i(pt->width0) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT;
79 txf |= log2i(pt->height0) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT;
80 txf |= log2i(pt->depth0) << NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT;
81 txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000;
82
83 switch (pt->target) {
84 case PIPE_TEXTURE_CUBE:
85 txf |= NV34TCL_TX_FORMAT_CUBIC;
86 /* fall-through */
87 case PIPE_TEXTURE_2D:
88 txf |= NV34TCL_TX_FORMAT_DIMS_2D;
89 break;
90 case PIPE_TEXTURE_3D:
91 txf |= NV34TCL_TX_FORMAT_DIMS_3D;
92 break;
93 case PIPE_TEXTURE_1D:
94 txf |= NV34TCL_TX_FORMAT_DIMS_1D;
95 break;
96 default:
97 NOUVEAU_ERR("Unknown target %d\n", pt->target);
98 return NULL;
99 }
100
101 txs = tf->swizzle;
102
103 so = so_new(1, 8, 2);
104 so_method(so, nvfx->screen->eng3d, NV34TCL_TX_OFFSET(unit), 8);
105 so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
106 so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR,
107 NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
108 so_data (so, ps->wrap);
109 so_data (so, NV34TCL_TX_ENABLE_ENABLE | ps->en);
110 so_data (so, txs);
111 so_data (so, ps->filt | 0x2000 /*voodoo*/);
112 so_data (so, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
113 pt->height0);
114 so_data (so, ps->bcol);
115
116 return so;
117 }
118