Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / drivers / nvfx / nv40_fragtex.c
1 #include "util/u_format.h"
2 #include "nvfx_context.h"
3 #include "nvfx_tex.h"
4 #include "nvfx_resource.h"
5
6 void
7 nv40_sampler_state_init(struct pipe_context *pipe,
8 struct nvfx_sampler_state *ps,
9 const struct pipe_sampler_state *cso)
10 {
11 if (cso->max_anisotropy >= 2) {
12 /* no idea, binary driver sets it, works without it.. meh.. */
13 ps->wrap |= (1 << 5);
14
15 if (cso->max_anisotropy >= 16) {
16 ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X;
17 } else
18 if (cso->max_anisotropy >= 12) {
19 ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X;
20 } else
21 if (cso->max_anisotropy >= 10) {
22 ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X;
23 } else
24 if (cso->max_anisotropy >= 8) {
25 ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X;
26 } else
27 if (cso->max_anisotropy >= 6) {
28 ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X;
29 } else
30 if (cso->max_anisotropy >= 4) {
31 ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X;
32 } else {
33 ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X;
34 }
35 }
36
37 {
38 float limit;
39
40 limit = CLAMP(cso->lod_bias, -16.0, 15.0);
41 ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
42
43 limit = CLAMP(cso->max_lod, 0.0, 15.0);
44 ps->en |= (int)(limit * 256.0) << 7;
45
46 limit = CLAMP(cso->min_lod, 0.0, 15.0);
47 ps->en |= (int)(limit * 256.0) << 19;
48 }
49 }
50
51 #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw) \
52 { \
53 TRUE, \
54 PIPE_FORMAT_##m, \
55 NV40TCL_TEX_FORMAT_FORMAT_##tf, \
56 (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \
57 NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \
58 NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \
59 NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w), \
60 ((NV34TCL_TX_FILTER_SIGNED_RED*sx) | (NV34TCL_TX_FILTER_SIGNED_GREEN*sy) | \
61 (NV34TCL_TX_FILTER_SIGNED_BLUE*sz) | (NV34TCL_TX_FILTER_SIGNED_ALPHA*sw)) \
62 }
63
64 struct nv40_texture_format {
65 boolean defined;
66 uint pipe;
67 int format;
68 int swizzle;
69 int sign;
70 };
71
72 static struct nv40_texture_format
73 nv40_texture_formats[] = {
74 _(B8G8R8X8_UNORM, A8R8G8B8, S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
75 _(B8G8R8A8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
76 _(B5G5R5A1_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
77 _(B4G4R4A4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
78 _(B5G6R5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
79 _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
80 _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X, 0, 0, 0, 0),
81 _(R16_SNORM , A16 , ZERO, ZERO, S1, ONE, X, X, X, Y, 1, 1, 1, 1),
82 _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X, 0, 0, 0, 0),
83 _(L8A8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y, 0, 0, 0, 0),
84 _(Z16_UNORM , Z16 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
85 _(S8_USCALED_Z24_UNORM , Z24 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0),
86 _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0),
87 _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
88 _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
89 _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0),
90 {},
91 };
92
93 static struct nv40_texture_format *
94 nv40_fragtex_format(uint pipe_format)
95 {
96 struct nv40_texture_format *tf = nv40_texture_formats;
97
98 while (tf->defined) {
99 if (tf->pipe == pipe_format)
100 return tf;
101 tf++;
102 }
103
104 NOUVEAU_ERR("unknown texture format %s\n", util_format_name(pipe_format));
105 return NULL;
106 }
107
108
109 void
110 nv40_fragtex_set(struct nvfx_context *nvfx, int unit)
111 {
112 struct nouveau_channel* chan = nvfx->screen->base.channel;
113 struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
114 struct nvfx_miptree *nv40mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture;
115 struct nouveau_bo *bo = nv40mt->base.bo;
116 struct pipe_resource *pt = &nv40mt->base.base;
117 struct nv40_texture_format *tf;
118
119 uint32_t txf, txs, txp;
120 unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
121
122 tf = nv40_fragtex_format(pt->format);
123 if (!tf)
124 assert(0);
125
126 txf = ps->fmt;
127 txf |= tf->format | 0x8000;
128 txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
129
130 if (1) /* XXX */
131 txf |= NV34TCL_TX_FORMAT_NO_BORDER;
132
133 switch (pt->target) {
134 case PIPE_TEXTURE_CUBE:
135 txf |= NV34TCL_TX_FORMAT_CUBIC;
136 /* fall-through */
137 case PIPE_TEXTURE_2D:
138 txf |= NV34TCL_TX_FORMAT_DIMS_2D;
139 break;
140 case PIPE_TEXTURE_3D:
141 txf |= NV34TCL_TX_FORMAT_DIMS_3D;
142 break;
143 case PIPE_TEXTURE_1D:
144 txf |= NV34TCL_TX_FORMAT_DIMS_1D;
145 break;
146 default:
147 NOUVEAU_ERR("Unknown target %d\n", pt->target);
148 return;
149 }
150
151 if (!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR)) {
152 txp = 0;
153 } else {
154 txp = nv40mt->level[0].pitch;
155 txf |= NV40TCL_TEX_FORMAT_LINEAR;
156 }
157
158 txs = tf->swizzle;
159
160 MARK_RING(chan, 11 + 2 * !unit, 2);
161 OUT_RING(chan, RING_3D(NV34TCL_TX_OFFSET(unit), 8));
162 OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
163 OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR,
164 NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
165 OUT_RING(chan, ps->wrap);
166 OUT_RING(chan, NV40TCL_TEX_ENABLE_ENABLE | ps->en);
167 OUT_RING(chan, txs);
168 OUT_RING(chan, ps->filt | tf->sign | 0x2000 /*voodoo*/);
169 OUT_RING(chan, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | pt->height0);
170 OUT_RING(chan, ps->bcol);
171 OUT_RING(chan, RING_3D(NV40TCL_TEX_SIZE1(unit), 1));
172 OUT_RING(chan, (pt->depth0 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp);
173
174 nvfx->hw_txf[unit] = txf;
175 nvfx->hw_samplers |= (1 << unit);
176 }