nv30_fragtex.c revision 6432d03c3d7ae21312e983fe41f4df7d66f7a3bf
1#include "nv30_context.h"
2
3static INLINE int log2i(int i)
4{
5	int r = 0;
6
7	if (i & 0xffff0000) {
8		i >>= 16;
9		r += 16;
10	}
11	if (i & 0x0000ff00) {
12		i >>= 8;
13		r += 8;
14	}
15	if (i & 0x000000f0) {
16		i >>= 4;
17		r += 4;
18	}
19	if (i & 0x0000000c) {
20		i >>= 2;
21		r += 2;
22	}
23	if (i & 0x00000002) {
24		r += 1;
25	}
26	return r;
27}
28
29#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w)                        \
30{                                                                              \
31  TRUE,                                                                        \
32  PIPE_FORMAT_##m,                                                             \
33  NV34TCL_TX_FORMAT_FORMAT_##tf,                                               \
34  (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y |           \
35   NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w |           \
36   NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y |           \
37   NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w)            \
38}
39
40struct nv30_texture_format {
41	boolean defined;
42	uint	pipe;
43	int     format;
44	int     swizzle;
45};
46
47static struct nv30_texture_format
48nv30_texture_formats[] = {
49	_(A8R8G8B8_UNORM, A8R8G8B8,   S1,   S1,   S1,   S1, X, Y, Z, W),
50	_(A1R5G5B5_UNORM, A1R5G5B5,   S1,   S1,   S1,   S1, X, Y, Z, W),
51	_(A4R4G4B4_UNORM, A4R4G4B4,   S1,   S1,   S1,   S1, X, Y, Z, W),
52	_(R5G6B5_UNORM  , R5G6B5  ,   S1,   S1,   S1,  ONE, X, Y, Z, W),
53	_(L8_UNORM      , L8      ,   S1,   S1,   S1,  ONE, X, X, X, X),
54	_(A8_UNORM      , L8      , ZERO, ZERO, ZERO,   S1, X, X, X, X),
55	_(I8_UNORM      , L8      ,   S1,   S1,   S1,   S1, X, X, X, X),
56	_(A8L8_UNORM    , A8L8    ,   S1,   S1,   S1,   S1, X, X, X, Y),
57//	_(Z16_UNORM     , Z16     ,   S1,   S1,   S1,  ONE, X, X, X, X),
58//	_(Z24S8_UNORM   , Z24     ,   S1,   S1,   S1,  ONE, X, X, X, X),
59	_(DXT1_RGB      , DXT1    ,   S1,   S1,   S1,  ONE, X, Y, Z, W),
60	_(DXT1_RGBA     , DXT1    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
61	_(DXT3_RGBA     , DXT3    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
62	_(DXT5_RGBA     , DXT5    ,   S1,   S1,   S1,   S1, X, Y, Z, W),
63	{},
64};
65
66static struct nv30_texture_format *
67nv30_fragtex_format(uint pipe_format)
68{
69	struct nv30_texture_format *tf = nv30_texture_formats;
70	char fs[128];
71
72	while (tf->defined) {
73		if (tf->pipe == pipe_format)
74			return tf;
75		tf++;
76	}
77
78	NOUVEAU_ERR("unknown texture format %s\n", pf_name(pipe_format));
79	return NULL;
80}
81
82
83static struct nouveau_stateobj *
84nv30_fragtex_build(struct nv30_context *nv30, int unit)
85{
86	struct nv30_sampler_state *ps = nv30->tex_sampler[unit];
87	struct nv30_miptree *nv30mt = nv30->tex_miptree[unit];
88	struct pipe_texture *pt = &nv30mt->base;
89	struct nv30_texture_format *tf;
90	struct nouveau_stateobj *so;
91	uint32_t txf, txs , txp;
92	unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
93
94	tf = nv30_fragtex_format(pt->format);
95	if (!tf)
96		assert(0);
97
98	txf  = tf->format;
99	txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0);
100	txf |= log2i(pt->width[0]) << 20;
101	txf |= log2i(pt->height[0]) << 24;
102	txf |= log2i(pt->depth[0]) << 28;
103	txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000;
104
105	switch (pt->target) {
106	case PIPE_TEXTURE_CUBE:
107		txf |= NV34TCL_TX_FORMAT_CUBIC;
108		/* fall-through */
109	case PIPE_TEXTURE_2D:
110		txf |= NV34TCL_TX_FORMAT_DIMS_2D;
111		break;
112	case PIPE_TEXTURE_3D:
113		txf |= NV34TCL_TX_FORMAT_DIMS_3D;
114		break;
115	case PIPE_TEXTURE_1D:
116		txf |= NV34TCL_TX_FORMAT_DIMS_1D;
117		break;
118	default:
119		NOUVEAU_ERR("Unknown target %d\n", pt->target);
120		return NULL;
121	}
122
123	if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
124		txp = 0;
125	} else {
126		txp  = nv30mt->level[0].pitch;
127		txf |= (1<<13) /*FIXME: NV34TCL_TX_FORMAT_LINEAR ? */;
128	}
129
130	txs = tf->swizzle;
131
132	so = so_new(16, 2);
133	so_method(so, nv30->screen->rankine, NV34TCL_TX_OFFSET(unit), 8);
134	so_reloc (so, nv30mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
135	so_reloc (so, nv30mt->buffer, txf, tex_flags | NOUVEAU_BO_OR,
136		  NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
137	so_data  (so, ps->wrap);
138	so_data  (so, NV34TCL_TX_ENABLE_ENABLE | ps->en);
139	so_data  (so, txs);
140	so_data  (so, ps->filt | 0x2000 /*voodoo*/);
141	so_data  (so, (pt->width[0] << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
142		       pt->height[0]);
143	so_data  (so, ps->bcol);
144
145	return so;
146}
147
148static boolean
149nv30_fragtex_validate(struct nv30_context *nv30)
150{
151	struct nv30_fragment_program *fp = nv30->fragprog;
152	struct nv30_state *state = &nv30->state;
153	struct nouveau_stateobj *so;
154	unsigned samplers, unit;
155
156	samplers = state->fp_samplers & ~fp->samplers;
157	while (samplers) {
158		unit = ffs(samplers) - 1;
159		samplers &= ~(1 << unit);
160
161		so = so_new(2, 0);
162		so_method(so, nv30->screen->rankine, NV34TCL_TX_ENABLE(unit), 1);
163		so_data  (so, 0);
164		so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]);
165		state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit));
166	}
167
168	samplers = nv30->dirty_samplers & fp->samplers;
169	while (samplers) {
170		unit = ffs(samplers) - 1;
171		samplers &= ~(1 << unit);
172
173		so = nv30_fragtex_build(nv30, unit);
174		so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]);
175		state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit));
176	}
177
178	nv30->state.fp_samplers = fp->samplers;
179	return FALSE;
180}
181
182struct nv30_state_entry nv30_state_fragtex = {
183	.validate = nv30_fragtex_validate,
184	.dirty = {
185		.pipe = NV30_NEW_SAMPLER | NV30_NEW_FRAGPROG,
186		.hw = 0
187	}
188};
189