4c26f3cb123f5f5c2fe31336c0323a69b1f973e8
[mesa.git] / src / gallium / drivers / nv40 / nv40_fragtex.c
1 #include "util/u_format.h"
2
3 #include "nv40_context.h"
4
5 #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw) \
6 { \
7 TRUE, \
8 PIPE_FORMAT_##m, \
9 NV40TCL_TEX_FORMAT_FORMAT_##tf, \
10 (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \
11 NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \
12 NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \
13 NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w), \
14 ((NV34TCL_TX_FILTER_SIGNED_RED*sx) | (NV34TCL_TX_FILTER_SIGNED_GREEN*sy) | \
15 (NV34TCL_TX_FILTER_SIGNED_BLUE*sz) | (NV34TCL_TX_FILTER_SIGNED_ALPHA*sw)) \
16 }
17
18 struct nv40_texture_format {
19 boolean defined;
20 uint pipe;
21 int format;
22 int swizzle;
23 int sign;
24 };
25
26 static struct nv40_texture_format
27 nv40_texture_formats[] = {
28 _(B8G8R8X8_UNORM, A8R8G8B8, S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
29 _(B8G8R8A8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
30 _(B5G5R5A1_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
31 _(B4G4R4A4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
32 _(B5G6R5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
33 _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
34 _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X, 0, 0, 0, 0),
35 _(R16_SNORM , A16 , ZERO, ZERO, S1, ONE, X, X, X, Y, 1, 1, 1, 1),
36 _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X, 0, 0, 0, 0),
37 _(L8A8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y, 0, 0, 0, 0),
38 _(Z16_UNORM , Z16 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
39 _(S8Z24_UNORM , Z24 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
40 _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
41 _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
42 _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
43 _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
44 {},
45 };
46
47 static struct nv40_texture_format *
48 nv40_fragtex_format(uint pipe_format)
49 {
50 struct nv40_texture_format *tf = nv40_texture_formats;
51
52 while (tf->defined) {
53 if (tf->pipe == pipe_format)
54 return tf;
55 tf++;
56 }
57
58 NOUVEAU_ERR("unknown texture format %s\n", util_format_name(pipe_format));
59 return NULL;
60 }
61
62
63 static struct nouveau_stateobj *
64 nv40_fragtex_build(struct nv40_context *nv40, int unit)
65 {
66 struct nv40_sampler_state *ps = nv40->tex_sampler[unit];
67 struct nv40_miptree *nv40mt = nv40->tex_miptree[unit];
68 struct nouveau_bo *bo = nouveau_bo(nv40mt->buffer);
69 struct pipe_texture *pt = &nv40mt->base;
70 struct nv40_texture_format *tf;
71 struct nouveau_stateobj *so;
72 uint32_t txf, txs, txp;
73 unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
74
75 tf = nv40_fragtex_format(pt->format);
76 if (!tf)
77 assert(0);
78
79 txf = ps->fmt;
80 txf |= tf->format | 0x8000;
81 txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
82
83 if (1) /* XXX */
84 txf |= NV34TCL_TX_FORMAT_NO_BORDER;
85
86 switch (pt->target) {
87 case PIPE_TEXTURE_CUBE:
88 txf |= NV34TCL_TX_FORMAT_CUBIC;
89 /* fall-through */
90 case PIPE_TEXTURE_2D:
91 txf |= NV34TCL_TX_FORMAT_DIMS_2D;
92 break;
93 case PIPE_TEXTURE_3D:
94 txf |= NV34TCL_TX_FORMAT_DIMS_3D;
95 break;
96 case PIPE_TEXTURE_1D:
97 txf |= NV34TCL_TX_FORMAT_DIMS_1D;
98 break;
99 default:
100 NOUVEAU_ERR("Unknown target %d\n", pt->target);
101 return NULL;
102 }
103
104 if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
105 txp = 0;
106 } else {
107 txp = nv40mt->level[0].pitch;
108 txf |= NV40TCL_TEX_FORMAT_LINEAR;
109 }
110
111 txs = tf->swizzle;
112
113 so = so_new(2, 9, 2);
114 so_method(so, nv40->screen->eng3d, NV34TCL_TX_OFFSET(unit), 8);
115 so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
116 so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR,
117 NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
118 so_data (so, ps->wrap);
119 so_data (so, NV40TCL_TEX_ENABLE_ENABLE | ps->en);
120 so_data (so, txs);
121 so_data (so, ps->filt | tf->sign | 0x2000 /*voodoo*/);
122 so_data (so, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
123 pt->height0);
124 so_data (so, ps->bcol);
125 so_method(so, nv40->screen->eng3d, NV40TCL_TEX_SIZE1(unit), 1);
126 so_data (so, (pt->depth0 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp);
127
128 return so;
129 }
130
131 static boolean
132 nv40_fragtex_validate(struct nv40_context *nv40)
133 {
134 struct nv40_fragment_program *fp = nv40->fragprog;
135 struct nv40_state *state = &nv40->state;
136 struct nouveau_stateobj *so;
137 unsigned samplers, unit;
138
139 samplers = state->fp_samplers & ~fp->samplers;
140 while (samplers) {
141 unit = ffs(samplers) - 1;
142 samplers &= ~(1 << unit);
143
144 so = so_new(1, 1, 0);
145 so_method(so, nv40->screen->eng3d, NV34TCL_TX_ENABLE(unit), 1);
146 so_data (so, 0);
147 so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
148 state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
149 }
150
151 samplers = nv40->dirty_samplers & fp->samplers;
152 while (samplers) {
153 unit = ffs(samplers) - 1;
154 samplers &= ~(1 << unit);
155
156 so = nv40_fragtex_build(nv40, unit);
157 so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
158 so_ref(NULL, &so);
159 state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
160 }
161
162 nv40->state.fp_samplers = fp->samplers;
163 return FALSE;
164 }
165
166 struct nv40_state_entry nv40_state_fragtex = {
167 .validate = nv40_fragtex_validate,
168 .dirty = {
169 .pipe = NV40_NEW_SAMPLER | NV40_NEW_FRAGPROG,
170 .hw = 0
171 }
172 };
173