nv50,nvc0: share sampler state creation
[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_resource.h"
25 #include "nv50_texture.xml.h"
26 #include "nv50_defs.xml.h"
27
28 #include "util/u_format.h"
29
30 #define NV50_TIC_0_SWIZZLE__MASK \
31 (NV50_TIC_0_MAPA__MASK | NV50_TIC_0_MAPB__MASK | \
32 NV50_TIC_0_MAPG__MASK | NV50_TIC_0_MAPR__MASK)
33
34 static INLINE uint32_t
35 nv50_tic_swizzle(uint32_t tc, unsigned swz, boolean tex_int)
36 {
37 switch (swz) {
38 case PIPE_SWIZZLE_RED:
39 return (tc & NV50_TIC_0_MAPR__MASK) >> NV50_TIC_0_MAPR__SHIFT;
40 case PIPE_SWIZZLE_GREEN:
41 return (tc & NV50_TIC_0_MAPG__MASK) >> NV50_TIC_0_MAPG__SHIFT;
42 case PIPE_SWIZZLE_BLUE:
43 return (tc & NV50_TIC_0_MAPB__MASK) >> NV50_TIC_0_MAPB__SHIFT;
44 case PIPE_SWIZZLE_ALPHA:
45 return (tc & NV50_TIC_0_MAPA__MASK) >> NV50_TIC_0_MAPA__SHIFT;
46 case PIPE_SWIZZLE_ONE:
47 return tex_int ? NV50_TIC_MAP_ONE_INT : NV50_TIC_MAP_ONE_FLOAT;
48 case PIPE_SWIZZLE_ZERO:
49 default:
50 return NV50_TIC_MAP_ZERO;
51 }
52 }
53
54 struct pipe_sampler_view *
55 nv50_create_sampler_view(struct pipe_context *pipe,
56 struct pipe_resource *texture,
57 const struct pipe_sampler_view *templ)
58 {
59 const struct util_format_description *desc;
60 uint32_t *tic;
61 uint32_t swz[4];
62 uint32_t depth;
63 struct nv50_tic_entry *view;
64 struct nv50_miptree *mt = nv50_miptree(texture);
65 boolean tex_int;
66
67 view = MALLOC_STRUCT(nv50_tic_entry);
68 if (!view)
69 return NULL;
70
71 view->pipe = *templ;
72 view->pipe.reference.count = 1;
73 view->pipe.texture = NULL;
74 view->pipe.context = pipe;
75
76 view->id = -1;
77
78 pipe_resource_reference(&view->pipe.texture, texture);
79
80 tic = &view->tic[0];
81
82 desc = util_format_description(mt->base.base.format);
83
84 /* TIC[0] */
85
86 tic[0] = nv50_format_table[view->pipe.format].tic;
87
88 tex_int = FALSE; /* XXX: integer textures */
89
90 swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r, tex_int);
91 swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g, tex_int);
92 swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b, tex_int);
93 swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a, tex_int);
94 tic[0] = (tic[0] & ~NV50_TIC_0_SWIZZLE__MASK) |
95 (swz[0] << NV50_TIC_0_MAPR__SHIFT) |
96 (swz[1] << NV50_TIC_0_MAPG__SHIFT) |
97 (swz[2] << NV50_TIC_0_MAPB__SHIFT) |
98 (swz[3] << NV50_TIC_0_MAPA__SHIFT);
99
100 tic[1] = /* mt->base.bo->offset; */ 0;
101 tic[2] = /* mt->base.bo->offset >> 32 */ 0;
102
103 tic[2] |= 0x10001000 | NV50_TIC_2_NO_BORDER;
104
105 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
106 tic[2] |= NV50_TIC_2_COLORSPACE_SRGB;
107
108 if (mt->base.base.target != PIPE_TEXTURE_RECT)
109 tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;
110
111 tic[2] |=
112 ((mt->base.bo->tile_mode & 0x0f) << (22 - 0)) |
113 ((mt->base.bo->tile_mode & 0xf0) << (25 - 4));
114
115 depth = MAX2(mt->base.base.array_size, mt->base.base.depth0);
116
117 if (mt->base.base.target == PIPE_TEXTURE_1D_ARRAY ||
118 mt->base.base.target == PIPE_TEXTURE_2D_ARRAY) {
119 tic[1] = view->pipe.u.tex.first_layer * mt->layer_stride;
120 depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1;
121 }
122
123 switch (mt->base.base.target) {
124 case PIPE_TEXTURE_1D:
125 tic[2] |= NV50_TIC_2_TARGET_1D;
126 break;
127 case PIPE_TEXTURE_2D:
128 tic[2] |= NV50_TIC_2_TARGET_2D;
129 break;
130 case PIPE_TEXTURE_RECT:
131 tic[2] |= NV50_TIC_2_TARGET_RECT;
132 break;
133 case PIPE_TEXTURE_3D:
134 tic[2] |= NV50_TIC_2_TARGET_3D;
135 break;
136 case PIPE_TEXTURE_CUBE:
137 depth /= 6;
138 if (depth > 1)
139 tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
140 else
141 tic[2] |= NV50_TIC_2_TARGET_CUBE;
142 break;
143 case PIPE_TEXTURE_1D_ARRAY:
144 tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
145 break;
146 case PIPE_TEXTURE_2D_ARRAY:
147 tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
148 break;
149 case PIPE_BUFFER:
150 tic[2] |= NV50_TIC_2_TARGET_BUFFER | NV50_TIC_2_LINEAR;
151 break;
152 default:
153 NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target);
154 return FALSE;
155 }
156
157 if (mt->base.base.target == PIPE_BUFFER)
158 tic[3] = mt->base.base.width0;
159 else
160 tic[3] = 0x00300000;
161
162 tic[4] = (1 << 31) | mt->base.base.width0;
163
164 tic[5] = mt->base.base.height0 & 0xffff;
165 tic[5] |= depth << 16;
166 tic[5] |= mt->base.base.last_level << 28;
167
168 tic[6] = 0x03000000;
169
170 tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
171
172 return &view->pipe;
173 }
174
175 static boolean
176 nv50_validate_tic(struct nv50_context *nv50, int s)
177 {
178 struct nouveau_channel *chan = nv50->screen->base.channel;
179 struct nouveau_bo *txc = nv50->screen->txc;
180 unsigned i;
181 boolean need_flush = FALSE;
182
183 for (i = 0; i < nv50->num_textures[s]; ++i) {
184 struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]);
185 struct nv04_resource *res;
186
187 if (!tic) {
188 BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1);
189 OUT_RING (chan, (i << 1) | 0);
190 continue;
191 }
192 res = &nv50_miptree(tic->pipe.texture)->base;
193
194 if (tic->id < 0) {
195 uint32_t offset = tic->tic[1];
196
197 tic->id = nv50_screen_tic_alloc(nv50->screen, tic);
198
199 MARK_RING (chan, 24 + 8, 4);
200 BEGIN_RING(chan, RING_2D(DST_FORMAT), 2);
201 OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM);
202 OUT_RING (chan, 1);
203 BEGIN_RING(chan, RING_2D(DST_PITCH), 5);
204 OUT_RING (chan, 262144);
205 OUT_RING (chan, 65536);
206 OUT_RING (chan, 1);
207 OUT_RELOCh(chan, txc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
208 OUT_RELOCl(chan, txc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
209 BEGIN_RING(chan, RING_2D(SIFC_BITMAP_ENABLE), 2);
210 OUT_RING (chan, 0);
211 OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM);
212 BEGIN_RING(chan, RING_2D(SIFC_WIDTH), 10);
213 OUT_RING (chan, 32);
214 OUT_RING (chan, 1);
215 OUT_RING (chan, 0);
216 OUT_RING (chan, 1);
217 OUT_RING (chan, 0);
218 OUT_RING (chan, 1);
219 OUT_RING (chan, 0);
220 OUT_RING (chan, tic->id * 32);
221 OUT_RING (chan, 0);
222 OUT_RING (chan, 0);
223 BEGIN_RING_NI(chan, RING_2D(SIFC_DATA), 8);
224 OUT_RING (chan, tic->tic[0]);
225 OUT_RELOCl(chan, res->bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
226 OUT_RELOC (chan, res->bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
227 NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, tic->tic[2], tic->tic[2]);
228 OUT_RINGp (chan, &tic->tic[3], 5);
229
230 need_flush = TRUE;
231 } else
232 if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
233 BEGIN_RING(chan, RING_3D(TEX_CACHE_CTL), 1);
234 OUT_RING (chan, 0x20); //(tic->id << 4) | 1);
235 }
236
237 nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
238
239 res->status &= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
240 res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
241
242 nv50_bufctx_add_resident(nv50, NV50_BUFCTX_TEXTURES, res,
243 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
244
245 BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1);
246 OUT_RING (chan, (tic->id << 9) | (i << 1) | 1);
247 }
248 for (; i < nv50->state.num_textures[s]; ++i) {
249 BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1);
250 OUT_RING (chan, (i << 1) | 0);
251 }
252 nv50->state.num_textures[s] = nv50->num_textures[s];
253
254 return need_flush;
255 }
256
257 void nv50_validate_textures(struct nv50_context *nv50)
258 {
259 boolean need_flush;
260
261 need_flush = nv50_validate_tic(nv50, 0);
262 need_flush |= nv50_validate_tic(nv50, 2);
263
264 if (need_flush) {
265 BEGIN_RING(nv50->screen->base.channel, RING_3D(TIC_FLUSH), 1);
266 OUT_RING (nv50->screen->base.channel, 0);
267 }
268 }
269
270 static boolean
271 nv50_validate_tsc(struct nv50_context *nv50, int s)
272 {
273 struct nouveau_channel *chan = nv50->screen->base.channel;
274 unsigned i;
275 boolean need_flush = FALSE;
276
277 for (i = 0; i < nv50->num_samplers[s]; ++i) {
278 struct nv50_tsc_entry *tsc = nv50_tsc_entry(nv50->samplers[s][i]);
279
280 if (!tsc) {
281 BEGIN_RING(chan, RING_3D(BIND_TSC(s)), 1);
282 OUT_RING (chan, (i << 4) | 0);
283 continue;
284 }
285 if (tsc->id < 0) {
286 tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc);
287
288 nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc,
289 65536 + tsc->id * 32,
290 NOUVEAU_BO_VRAM, 32, tsc->tsc);
291 need_flush = TRUE;
292 }
293 nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32);
294
295 BEGIN_RING(chan, RING_3D(BIND_TSC(s)), 1);
296 OUT_RING (chan, (tsc->id << 12) | (i << 4) | 1);
297 }
298 for (; i < nv50->state.num_samplers[s]; ++i) {
299 BEGIN_RING(chan, RING_3D(BIND_TSC(s)), 1);
300 OUT_RING (chan, (i << 4) | 0);
301 }
302 nv50->state.num_samplers[s] = nv50->num_samplers[s];
303
304 return need_flush;
305 }
306
307 void nv50_validate_samplers(struct nv50_context *nv50)
308 {
309 boolean need_flush;
310
311 need_flush = nv50_validate_tsc(nv50, 0);
312 need_flush |= nv50_validate_tsc(nv50, 2);
313
314 if (need_flush) {
315 BEGIN_RING(nv50->screen->base.channel, RING_3D(TSC_FLUSH), 1);
316 OUT_RING (nv50->screen->base.channel, 0);
317 }
318 }