nvfx: new 2D: optimize fragtex format lookup
[mesa.git] / src / gallium / drivers / nvfx / nv30_fragtex.c
1 #include "util/u_format.h"
2
3 #include "nvfx_context.h"
4 #include "nouveau/nouveau_util.h"
5 #include "nvfx_tex.h"
6 #include "nvfx_resource.h"
7
8 void
9 nv30_sampler_state_init(struct pipe_context *pipe,
10 struct nvfx_sampler_state *ps,
11 const struct pipe_sampler_state *cso)
12 {
13 if (cso->max_anisotropy >= 8) {
14 ps->en |= NV34TCL_TX_ENABLE_ANISO_8X;
15 } else
16 if (cso->max_anisotropy >= 4) {
17 ps->en |= NV34TCL_TX_ENABLE_ANISO_4X;
18 } else
19 if (cso->max_anisotropy >= 2) {
20 ps->en |= NV34TCL_TX_ENABLE_ANISO_2X;
21 }
22
23 {
24 float limit;
25
26 limit = CLAMP(cso->lod_bias, -16.0, 15.0);
27 ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
28
29 limit = CLAMP(cso->max_lod, 0.0, 15.0);
30 ps->en |= (int)(limit) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/;
31
32 limit = CLAMP(cso->min_lod, 0.0, 15.0);
33 ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/;
34 }
35 }
36
37 #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w) \
38 [PIPE_FORMAT_##m] = { \
39 NV34TCL_TX_FORMAT_FORMAT_##tf, \
40 (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \
41 NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \
42 NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \
43 NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w) \
44 }
45
46 struct nv30_texture_format {
47 int format;
48 int swizzle;
49 };
50
51 static struct nv30_texture_format
52 nv30_texture_formats[PIPE_FORMAT_COUNT] = {
53 [0 ... PIPE_FORMAT_COUNT - 1] = {-1, 0},
54 _(B8G8R8X8_UNORM, A8R8G8B8, S1, S1, S1, ONE, X, Y, Z, W),
55 _(B8G8R8A8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W),
56 _(B5G5R5A1_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W),
57 _(B4G4R4A4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W),
58 _(B5G6R5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W),
59 _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X),
60 _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X),
61 _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X),
62 _(L8A8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y),
63 _(Z16_UNORM , R5G6B5 , S1, S1, S1, ONE, X, X, X, X),
64 _(S8_USCALED_Z24_UNORM , A8R8G8B8, S1, S1, S1, ONE, X, X, X, X),
65 _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W),
66 _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W),
67 _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W),
68 _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W),
69 {},
70 };
71
72 void
73 nv30_fragtex_set(struct nvfx_context *nvfx, int unit)
74 {
75 struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
76 struct nvfx_miptree *mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture;
77 struct pipe_resource *pt = &mt->base.base;
78 struct nouveau_bo *bo = mt->base.bo;
79 struct nv30_texture_format *tf;
80 struct nouveau_channel* chan = nvfx->screen->base.channel;
81 uint32_t txf, txs;
82 unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
83
84 tf = &nv30_texture_formats[pt->format];
85 assert(tf->format >= 0);
86
87 txf = tf->format;
88 txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0);
89 txf |= log2i(pt->width0) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT;
90 txf |= log2i(pt->height0) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT;
91 txf |= log2i(pt->depth0) << NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT;
92 txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000;
93
94 switch (pt->target) {
95 case PIPE_TEXTURE_CUBE:
96 txf |= NV34TCL_TX_FORMAT_CUBIC;
97 /* fall-through */
98 case PIPE_TEXTURE_2D:
99 case PIPE_TEXTURE_RECT:
100 txf |= NV34TCL_TX_FORMAT_DIMS_2D;
101 break;
102 case PIPE_TEXTURE_3D:
103 txf |= NV34TCL_TX_FORMAT_DIMS_3D;
104 break;
105 case PIPE_TEXTURE_1D:
106 txf |= NV34TCL_TX_FORMAT_DIMS_1D;
107 break;
108 default:
109 NOUVEAU_ERR("Unknown target %d\n", pt->target);
110 return;
111 }
112
113 txs = tf->swizzle;
114
115 MARK_RING(chan, 9, 2);
116 OUT_RING(chan, RING_3D(NV34TCL_TX_OFFSET(unit), 8));
117 OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
118 OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR,
119 NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
120 OUT_RING(chan, ps->wrap);
121 OUT_RING(chan, NV34TCL_TX_ENABLE_ENABLE | ps->en);
122 OUT_RING(chan, txs);
123 OUT_RING(chan, ps->filt | 0x2000 /*voodoo*/);
124 OUT_RING(chan, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
125 pt->height0);
126 OUT_RING(chan, ps->bcol);
127
128 nvfx->hw_txf[unit] = txf;
129 nvfx->hw_samplers |= (1 << unit);
130 }