nv50: nicer texture format switch
[mesa.git] / src / gallium / drivers / nv50 / nv50_tex.c
1 /*
2 * Copyright 2008 Ben Skeggs
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include "nv50_context.h"
24 #include "nv50_texture.h"
25
26 #include "nouveau/nouveau_stateobj.h"
27
28 #define _(pf, tt, r, g, b, a, tf) \
29 { \
30 PIPE_FORMAT_##pf, \
31 NV50TIC_0_0_MAPR_##r | NV50TIC_0_0_TYPER_##tt | \
32 NV50TIC_0_0_MAPG_##g | NV50TIC_0_0_TYPEG_##tt | \
33 NV50TIC_0_0_MAPB_##b | NV50TIC_0_0_TYPEB_##tt | \
34 NV50TIC_0_0_MAPA_##a | NV50TIC_0_0_TYPEA_##tt | \
35 NV50TIC_0_0_FMT_##tf \
36 }
37
38 struct nv50_texture_format {
39 enum pipe_format pf;
40 uint32_t hw;
41 };
42
43 #define NV50_TEX_FORMAT_LIST_SIZE \
44 (sizeof(nv50_tex_format_list) / sizeof(struct nv50_texture_format))
45
46 static const struct nv50_texture_format nv50_tex_format_list[] =
47 {
48 _(A8R8G8B8_UNORM, UNORM, C2, C1, C0, C3, 8_8_8_8),
49 _(X8R8G8B8_UNORM, UNORM, C2, C1, C0, ONE, 8_8_8_8),
50 _(A1R5G5B5_UNORM, UNORM, C2, C1, C0, C3, 1_5_5_5),
51 _(A4R4G4B4_UNORM, UNORM, C2, C1, C0, C3, 4_4_4_4),
52
53 _(R5G6B5_UNORM, UNORM, C2, C1, C0, ONE, 5_6_5),
54
55 _(L8_UNORM, UNORM, C0, C0, C0, ONE, 8),
56 _(A8_UNORM, UNORM, ZERO, ZERO, ZERO, C0, 8),
57 _(I8_UNORM, UNORM, C0, C0, C0, C0, 8),
58
59 _(A8L8_UNORM, UNORM, C0, C0, C0, C1, 8_8),
60
61 _(DXT1_RGB, UNORM, C0, C1, C2, ONE, DXT1),
62 _(DXT1_RGBA, UNORM, C0, C1, C2, C3, DXT1),
63 _(DXT3_RGBA, UNORM, C0, C1, C2, C3, DXT3),
64 _(DXT5_RGBA, UNORM, C0, C1, C2, C3, DXT5)
65 };
66
67 #undef _
68
69 static int
70 nv50_tex_construct(struct nv50_context *nv50, struct nouveau_stateobj *so,
71 struct nv50_miptree *mt, int unit)
72 {
73 unsigned i;
74
75 for (i = 0; i < NV50_TEX_FORMAT_LIST_SIZE; i++)
76 if (nv50_tex_format_list[i].pf == mt->base.base.format)
77 break;
78 if (i == NV50_TEX_FORMAT_LIST_SIZE)
79 return 1;
80
81 so_data (so, nv50_tex_format_list[i].hw);
82 so_reloc(so, mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW |
83 NOUVEAU_BO_RD, 0, 0);
84 if (nv50->sampler[unit]->normalized)
85 so_data (so, 0xd0005000 | mt->base.bo->tile_mode << 22);
86 else
87 so_data (so, 0x5001d000 | mt->base.bo->tile_mode << 22);
88 so_data (so, 0x00300000);
89 so_data (so, mt->base.base.width[0]);
90 so_data (so, (mt->base.base.last_level << 28) |
91 (mt->base.base.depth[0] << 16) | mt->base.base.height[0]);
92 so_data (so, 0x03000000);
93 so_data (so, mt->base.base.last_level << 4);
94
95 return 0;
96 }
97
98 void
99 nv50_tex_validate(struct nv50_context *nv50)
100 {
101 struct nouveau_grobj *tesla = nv50->screen->tesla;
102 struct nouveau_stateobj *so;
103 int unit, push;
104
105 push = nv50->miptree_nr * 11;
106 push += MAX2(nv50->miptree_nr, nv50->state.miptree_nr) * 2;
107
108 so = so_new(push, nv50->miptree_nr * 2);
109 for (unit = 0; unit < nv50->miptree_nr; unit++) {
110 struct nv50_miptree *mt = nv50->miptree[unit];
111
112 if (!mt)
113 continue;
114
115 so_method(so, tesla, NV50TCL_CB_ADDR, 1);
116 so_data (so, ((unit * 8) << NV50TCL_CB_ADDR_ID_SHIFT) |
117 NV50_CB_TIC);
118 so_method(so, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 8);
119 if (nv50_tex_construct(nv50, so, mt, unit)) {
120 NOUVEAU_ERR("failed tex validate\n");
121 so_ref(NULL, &so);
122 return;
123 }
124
125 so_method(so, tesla, NV50TCL_SET_SAMPLER_TEX, 1);
126 so_data (so, (unit << NV50TCL_SET_SAMPLER_TEX_TIC_SHIFT) |
127 (unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) |
128 NV50TCL_SET_SAMPLER_TEX_VALID);
129 }
130
131 for (; unit < nv50->state.miptree_nr; unit++) {
132 so_method(so, tesla, NV50TCL_SET_SAMPLER_TEX, 1);
133 so_data (so,
134 (unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) | 0);
135 }
136
137 so_ref(so, &nv50->state.tic_upload);
138 so_ref(NULL, &so);
139 nv50->state.miptree_nr = nv50->miptree_nr;
140 }
141