nv30_fragtex.c revision 5acbd0b0961089f9553adbe9b3d1341997ccb220
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	pf_sprint_name(fs, pipe_format);
79	NOUVEAU_ERR("unknown texture format %s\n", fs);
80	return NULL;
81}
82
83
84static struct nouveau_stateobj *
85nv30_fragtex_build(struct nv30_context *nv30, int unit)
86{
87	struct nv30_sampler_state *ps = nv30->tex_sampler[unit];
88	struct nv30_miptree *nv30mt = nv30->tex_miptree[unit];
89	struct pipe_texture *pt = &nv30mt->base;
90	struct nv30_texture_format *tf;
91	struct nouveau_stateobj *so;
92	uint32_t txf, txs /*, txp*/;
93	/*int swizzled = 0;*/ /*XXX: implement in region code? */
94	unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
95
96	tf = nv30_fragtex_format(pt->format);
97	if (!tf)
98		assert(0);
99
100	txf  = tf->format << 8;
101	txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0);
102	txf |= log2i(pt->width[0]) << 20;
103	txf |= log2i(pt->height[0]) << 24;
104	txf |= log2i(pt->depth[0]) << 28;
105	txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000;
106
107	switch (pt->target) {
108	case PIPE_TEXTURE_CUBE:
109		txf |= NV34TCL_TX_FORMAT_CUBIC;
110		/* fall-through */
111	case PIPE_TEXTURE_2D:
112		txf |= NV34TCL_TX_FORMAT_DIMS_2D;
113		break;
114	case PIPE_TEXTURE_3D:
115		txf |= NV34TCL_TX_FORMAT_DIMS_3D;
116		break;
117	case PIPE_TEXTURE_1D:
118		txf |= NV34TCL_TX_FORMAT_DIMS_1D;
119		break;
120	default:
121		NOUVEAU_ERR("Unknown target %d\n", pt->target);
122		return NULL;
123	}
124
125	txs = tf->swizzle;
126
127	so = so_new(16, 2);
128	so_method(so, nv30->screen->rankine, NV34TCL_TX_OFFSET(unit), 8);
129	so_reloc (so, nv30mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
130	so_reloc (so, nv30mt->buffer, txf, tex_flags | NOUVEAU_BO_OR,
131		  NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
132	so_data  (so, ps->wrap);
133	so_data  (so, NV34TCL_TX_ENABLE_ENABLE | ps->en);
134	so_data  (so, txs);
135	so_data  (so, ps->filt | 0x2000 /*voodoo*/);
136	so_data  (so, (pt->width[0] << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
137		       pt->height[0]);
138	so_data  (so, ps->bcol);
139
140	return so;
141}
142
143static boolean
144nv30_fragtex_validate(struct nv30_context *nv30)
145{
146	struct nv30_fragment_program *fp = nv30->fragprog.current;
147	struct nv30_state *state = &nv30->state;
148	struct nouveau_stateobj *so;
149	unsigned samplers, unit;
150
151	samplers = state->fp_samplers & ~fp->samplers;
152	while (samplers) {
153		unit = ffs(samplers) - 1;
154		samplers &= ~(1 << unit);
155
156		so = so_new(2, 0);
157		so_method(so, nv30->screen->rankine, NV34TCL_TX_ENABLE(unit), 1);
158		so_data  (so, 0);
159		so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]);
160		state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit));
161	}
162
163	samplers = nv30->dirty_samplers & fp->samplers;
164	while (samplers) {
165		unit = ffs(samplers) - 1;
166		samplers &= ~(1 << unit);
167
168		so = nv30_fragtex_build(nv30, unit);
169		so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]);
170		state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit));
171	}
172
173	nv30->state.fp_samplers = fp->samplers;
174	return FALSE;
175}
176
177struct nv30_state_entry nv30_state_fragtex = {
178	.validate = nv30_fragtex_validate,
179	.dirty = {
180		.pipe = NV30_NEW_SAMPLER | NV30_NEW_FRAGPROG,
181		.hw = 0
182	}
183};
184