Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / gallium / drivers / nv10 / nv10_fragtex.c
1 #include "nv10_context.h"
2
3 static 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) \
30 { \
31 TRUE, \
32 PIPE_FORMAT_##m, \
33 NV10TCL_TX_FORMAT_FORMAT_##tf, \
34 }
35
36 struct nv10_texture_format {
37 boolean defined;
38 uint pipe;
39 int format;
40 };
41
42 static struct nv10_texture_format
43 nv10_texture_formats[] = {
44 _(A8R8G8B8_UNORM, A8R8G8B8),
45 _(A1R5G5B5_UNORM, A1R5G5B5),
46 _(A4R4G4B4_UNORM, A4R4G4B4),
47 _(U_L8 , L8 ),
48 _(U_A8 , A8 ),
49 _(U_A8_L8 , A8L8 ),
50 // _(RGB_DXT1 , DXT1, ),
51 // _(RGBA_DXT1 , DXT1, ),
52 // _(RGBA_DXT3 , DXT3, ),
53 // _(RGBA_DXT5 , DXT5, ),
54 {},
55 };
56
57 static struct nv10_texture_format *
58 nv10_fragtex_format(uint pipe_format)
59 {
60 struct nv10_texture_format *tf = nv10_texture_formats;
61
62 while (tf->defined) {
63 if (tf->pipe == pipe_format)
64 return tf;
65 tf++;
66 }
67
68 return NULL;
69 }
70
71
72 static void
73 nv10_fragtex_build(struct nv10_context *nv10, int unit)
74 {
75 struct nv10_sampler_state *ps = nv10->tex_sampler[unit];
76 struct nv10_miptree *nv10mt = nv10->tex_miptree[unit];
77 struct pipe_texture *pt = &nv10mt->base;
78 struct nv10_texture_format *tf;
79 uint32_t txf, txs, txp;
80
81 tf = nv10_fragtex_format(pt->format);
82 if (!tf || !tf->defined) {
83 NOUVEAU_ERR("Unsupported texture format: 0x%x\n", pt->format);
84 return;
85 }
86
87 txf = tf->format << 8;
88 txf |= (pt->last_level + 1) << 16;
89 txf |= log2i(pt->width[0]) << 20;
90 txf |= log2i(pt->height[0]) << 24;
91 txf |= log2i(pt->depth[0]) << 28;
92 txf |= 8;
93
94 switch (pt->target) {
95 case PIPE_TEXTURE_CUBE:
96 txf |= NV10TCL_TX_FORMAT_CUBE_MAP;
97 /* fall-through */
98 case PIPE_TEXTURE_2D:
99 txf |= (2<<4);
100 break;
101 case PIPE_TEXTURE_1D:
102 txf |= (1<<4);
103 break;
104 default:
105 NOUVEAU_ERR("Unknown target %d\n", pt->target);
106 return;
107 }
108
109 BEGIN_RING(celsius, NV10TCL_TX_OFFSET(unit), 8);
110 OUT_RELOCl(nv10mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD);
111 OUT_RELOCd(nv10mt->buffer,txf,NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/);
112 OUT_RING (ps->wrap);
113 OUT_RING (0x40000000); /* enable */
114 OUT_RING (txs);
115 OUT_RING (ps->filt | 0x2000 /* magic */);
116 OUT_RING ((pt->width[0] << 16) | pt->height[0]);
117 OUT_RING (ps->bcol);
118 }
119
120 void
121 nv10_fragtex_bind(struct nv10_context *nv10)
122 {
123 struct nv10_fragment_program *fp = nv10->fragprog.active;
124 unsigned samplers, unit;
125
126 samplers = nv10->fp_samplers & ~fp->samplers;
127 while (samplers) {
128 unit = ffs(samplers) - 1;
129 samplers &= ~(1 << unit);
130
131 BEGIN_RING(celsius, NV10TCL_TX_ENABLE(unit), 1);
132 OUT_RING (0);
133 }
134
135 samplers = nv10->dirty_samplers & fp->samplers;
136 while (samplers) {
137 unit = ffs(samplers) - 1;
138 samplers &= ~(1 << unit);
139
140 nv10_fragtex_build(nv10, unit);
141 }
142
143 nv10->fp_samplers = fp->samplers;
144 }
145