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