nvc0: switch to the proper constants upload path
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_state_validate.c
1
2 #include "nvc0_context.h"
3 #include "os/os_time.h"
4
5 static void
6 nvc0_validate_zcull(struct nvc0_context *nvc0)
7 {
8 struct nouveau_channel *chan = nvc0->screen->base.channel;
9 struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
10 struct nvc0_miptree *mt = nvc0_miptree(fb->zsbuf->texture);
11 struct nouveau_bo *bo = mt->base.bo;
12 uint32_t size;
13 uint32_t offset = align(mt->total_size, 1 << 17);
14 unsigned width, height;
15
16 size = mt->total_size * 2;
17
18 height = align(fb->height, 32);
19 width = fb->width % 224;
20 if (width)
21 width = fb->width + (224 - width);
22 else
23 width = fb->width;
24
25 BEGIN_RING(chan, RING_3D_(0x1590), 1); /* ZCULL_REGION_INDEX (bits 0x3f) */
26 OUT_RING (chan, 0);
27 BEGIN_RING(chan, RING_3D_(0x07e8), 2); /* ZCULL_ADDRESS_A_HIGH */
28 OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
29 OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
30 offset += 1 << 17;
31 BEGIN_RING(chan, RING_3D_(0x07f0), 2); /* ZCULL_ADDRESS_B_HIGH */
32 OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
33 OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
34 BEGIN_RING(chan, RING_3D_(0x07e0), 2);
35 OUT_RING (chan, size);
36 OUT_RING (chan, size >> 16);
37 BEGIN_RING(chan, RING_3D_(0x15c8), 1); /* bits 0x3 */
38 OUT_RING (chan, 2);
39 BEGIN_RING(chan, RING_3D_(0x07c0), 4); /* ZCULL dimensions */
40 OUT_RING (chan, width);
41 OUT_RING (chan, height);
42 OUT_RING (chan, 1);
43 OUT_RING (chan, 0);
44 BEGIN_RING(chan, RING_3D_(0x15fc), 2);
45 OUT_RING (chan, 0); /* bits 0xffff */
46 OUT_RING (chan, 0); /* bits 0xffff */
47 BEGIN_RING(chan, RING_3D_(0x1958), 1);
48 OUT_RING (chan, 0); /* bits ~0 */
49 }
50
51 static void
52 nvc0_validate_fb(struct nvc0_context *nvc0)
53 {
54 struct nouveau_channel *chan = nvc0->screen->base.channel;
55 struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
56 unsigned i;
57
58 nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_FRAME);
59
60 BEGIN_RING(chan, RING_3D(RT_CONTROL), 1);
61 OUT_RING (chan, (076543210 << 4) | fb->nr_cbufs);
62 BEGIN_RING(chan, RING_3D(SCREEN_SCISSOR_HORIZ), 2);
63 OUT_RING (chan, fb->width << 16);
64 OUT_RING (chan, fb->height << 16);
65
66 for (i = 0; i < fb->nr_cbufs; ++i) {
67 struct nvc0_miptree *mt = nvc0_miptree(fb->cbufs[i]->texture);
68 struct nouveau_bo *bo = mt->base.bo;
69 unsigned offset = fb->cbufs[i]->offset;
70
71 BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(i)), 8);
72 OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
73 OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
74 OUT_RING (chan, fb->cbufs[i]->width);
75 OUT_RING (chan, fb->cbufs[i]->height);
76 OUT_RING (chan, nvc0_format_table[fb->cbufs[i]->format].rt);
77 OUT_RING (chan, mt->level[fb->cbufs[i]->level].tile_mode);
78 OUT_RING (chan, 1);
79 OUT_RING (chan, 0);
80
81 nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base,
82 NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
83 }
84
85 if (fb->zsbuf) {
86 struct nvc0_miptree *mt = nvc0_miptree(fb->zsbuf->texture);
87 struct nouveau_bo *bo = mt->base.bo;
88 unsigned offset = fb->zsbuf->offset;
89
90 BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
91 OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
92 OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
93 OUT_RING (chan, nvc0_format_table[fb->zsbuf->format].rt);
94 OUT_RING (chan, mt->level[fb->zsbuf->level].tile_mode);
95 OUT_RING (chan, 0);
96 BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
97 OUT_RING (chan, 1);
98 BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);
99 OUT_RING (chan, fb->zsbuf->width);
100 OUT_RING (chan, fb->zsbuf->height);
101 OUT_RING (chan, (1 << 16) | 1);
102
103 nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base,
104 NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
105 } else {
106 BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
107 OUT_RING (chan, 0);
108 }
109
110 BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
111 OUT_RING (chan, fb->width << 16);
112 OUT_RING (chan, fb->height << 16);
113 }
114
115 static void
116 nvc0_validate_blend_colour(struct nvc0_context *nvc0)
117 {
118 struct nouveau_channel *chan = nvc0->screen->base.channel;
119
120 BEGIN_RING(chan, RING_3D(BLEND_COLOR(0)), 4);
121 OUT_RINGf (chan, nvc0->blend_colour.color[0]);
122 OUT_RINGf (chan, nvc0->blend_colour.color[1]);
123 OUT_RINGf (chan, nvc0->blend_colour.color[2]);
124 OUT_RINGf (chan, nvc0->blend_colour.color[3]);
125 }
126
127 static void
128 nvc0_validate_stencil_ref(struct nvc0_context *nvc0)
129 {
130 struct nouveau_channel *chan = nvc0->screen->base.channel;
131
132 BEGIN_RING(chan, RING_3D(STENCIL_FRONT_FUNC_REF), 1);
133 OUT_RING (chan, nvc0->stencil_ref.ref_value[0]);
134 BEGIN_RING(chan, RING_3D(STENCIL_BACK_FUNC_REF), 1);
135 OUT_RING (chan, nvc0->stencil_ref.ref_value[1]);
136 }
137
138 static void
139 nvc0_validate_stipple(struct nvc0_context *nvc0)
140 {
141 struct nouveau_channel *chan = nvc0->screen->base.channel;
142 unsigned i;
143
144 BEGIN_RING(chan, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
145 for (i = 0; i < 32; ++i)
146 OUT_RING(chan, util_bswap32(nvc0->stipple.stipple[i]));
147 }
148
149 static void
150 nvc0_validate_scissor(struct nvc0_context *nvc0)
151 {
152 struct nouveau_channel *chan = nvc0->screen->base.channel;
153 struct pipe_scissor_state *s = &nvc0->scissor;
154
155 if (!(nvc0->dirty & NVC0_NEW_SCISSOR) &&
156 nvc0->state.scissor == nvc0->rast->pipe.scissor)
157 return;
158 nvc0->state.scissor = nvc0->rast->pipe.scissor;
159
160 if (nvc0->state.scissor) {
161 BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
162 OUT_RING (chan, (s->maxx << 16) | s->minx);
163 OUT_RING (chan, (s->maxy << 16) | s->miny);
164 } else {
165 BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
166 OUT_RING (chan, nvc0->framebuffer.width << 16);
167 OUT_RING (chan, nvc0->framebuffer.height << 16);
168 }
169 }
170
171 static void
172 nvc0_validate_viewport(struct nvc0_context *nvc0)
173 {
174 struct nouveau_channel *chan = nvc0->screen->base.channel;
175
176 BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
177 OUT_RINGf (chan, nvc0->viewport.translate[0]);
178 OUT_RINGf (chan, nvc0->viewport.translate[1]);
179 OUT_RINGf (chan, nvc0->viewport.translate[2]);
180 BEGIN_RING(chan, RING_3D(VIEWPORT_SCALE_X(0)), 3);
181 OUT_RINGf (chan, nvc0->viewport.scale[0]);
182 OUT_RINGf (chan, nvc0->viewport.scale[1]);
183 OUT_RINGf (chan, nvc0->viewport.scale[2]);
184 }
185
186 static void
187 nvc0_validate_clip(struct nvc0_context *nvc0)
188 {
189 struct nouveau_channel *chan = nvc0->screen->base.channel;
190 uint32_t clip;
191
192 clip = nvc0->clip.depth_clamp ? 0x201a : 0x0002;
193
194 BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1);
195 OUT_RING (chan, clip);
196
197 if (nvc0->clip.nr) {
198 struct nouveau_bo *bo = nvc0->screen->uniforms;
199
200 BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
201 OUT_RING (chan, 256);
202 OUT_RELOCh(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
203 OUT_RELOCl(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
204 BEGIN_RING_1I(chan, RING_3D(CB_POS), nvc0->clip.nr * 4 + 1);
205 OUT_RING (chan, 0);
206 OUT_RINGp (chan, &nvc0->clip.ucp[0][0], nvc0->clip.nr * 4);
207
208 BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1);
209 OUT_RING (chan, (1 << nvc0->clip.nr) - 1);
210 } else {
211 INLIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 0);
212 }
213 }
214
215 static void
216 nvc0_validate_blend(struct nvc0_context *nvc0)
217 {
218 struct nouveau_channel *chan = nvc0->screen->base.channel;
219
220 WAIT_RING(chan, nvc0->blend->size);
221 OUT_RINGp(chan, nvc0->blend->state, nvc0->blend->size);
222 }
223
224 static void
225 nvc0_validate_zsa(struct nvc0_context *nvc0)
226 {
227 struct nouveau_channel *chan = nvc0->screen->base.channel;
228
229 WAIT_RING(chan, nvc0->zsa->size);
230 OUT_RINGp(chan, nvc0->zsa->state, nvc0->zsa->size);
231 }
232
233 static void
234 nvc0_validate_rasterizer(struct nvc0_context *nvc0)
235 {
236 struct nouveau_channel *chan = nvc0->screen->base.channel;
237
238 WAIT_RING(chan, nvc0->rast->size);
239 OUT_RINGp(chan, nvc0->rast->state, nvc0->rast->size);
240 }
241
242 static void
243 nvc0_constbufs_validate(struct nvc0_context *nvc0)
244 {
245 struct nouveau_channel *chan = nvc0->screen->base.channel;
246 struct nouveau_bo *bo;
247 unsigned s;
248
249 for (s = 0; s < 5; ++s) {
250 struct nvc0_resource *res;
251 int i;
252
253 while (nvc0->constbuf_dirty[s]) {
254 unsigned base = 0;
255 unsigned offset = 0, words = 0;
256 boolean rebind = TRUE;
257
258 i = ffs(nvc0->constbuf_dirty[s]) - 1;
259 nvc0->constbuf_dirty[s] &= ~(1 << i);
260
261 res = nvc0_resource(nvc0->constbuf[s][i]);
262 if (!res) {
263 BEGIN_RING(chan, RING_3D(CB_BIND(s)), 1);
264 OUT_RING (chan, (i << 4) | 0);
265 if (i == 0)
266 nvc0->state.uniform_buffer_bound[s] = 0;
267 continue;
268 }
269
270 if (!nvc0_resource_mapped_by_gpu(&res->base)) {
271 if (i == 0) {
272 base = s << 16;
273 bo = nvc0->screen->uniforms;
274
275 if (nvc0->state.uniform_buffer_bound[s] >= res->base.width0)
276 rebind = FALSE;
277 else
278 nvc0->state.uniform_buffer_bound[s] =
279 align(res->base.width0, 0x100);
280 } else {
281 bo = res->bo;
282 }
283 #if 0
284 nvc0_m2mf_push_linear(nvc0, bo, NOUVEAU_BO_VRAM,
285 base, res->base.width0, res->data);
286 BEGIN_RING(chan, RING_3D_(0x021c), 1);
287 OUT_RING (chan, 0x1111);
288 #else
289 words = res->base.width0 / 4;
290 #endif
291 } else {
292 bo = res->bo;
293 if (i == 0)
294 nvc0->state.uniform_buffer_bound[s] = 0;
295 }
296
297 if (bo != nvc0->screen->uniforms)
298 nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_CONSTANT, res,
299 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
300
301 if (rebind) {
302 BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
303 OUT_RING (chan, align(res->base.width0, 0x100));
304 OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
305 OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
306 BEGIN_RING(chan, RING_3D(CB_BIND(s)), 1);
307 OUT_RING (chan, (i << 4) | 1);
308 }
309
310 while (words) {
311 unsigned nr = AVAIL_RING(chan);
312
313 if (nr < 16) {
314 FIRE_RING(chan);
315 continue;
316 }
317 nr = MIN2(MIN2(nr - 6, words), NV04_PFIFO_MAX_PACKET_LEN - 1);
318
319 BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
320 OUT_RING (chan, align(res->base.width0, 0x100));
321 OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
322 OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
323 BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1);
324 OUT_RING (chan, offset);
325 OUT_RINGp (chan, &res->data[offset], nr);
326
327 offset += nr * 4;
328 words -= nr;
329 }
330 }
331 }
332 }
333
334 static struct state_validate {
335 void (*func)(struct nvc0_context *);
336 uint32_t states;
337 } validate_list[] = {
338 { nvc0_validate_fb, NVC0_NEW_FRAMEBUFFER },
339 { nvc0_validate_blend, NVC0_NEW_BLEND },
340 { nvc0_validate_zsa, NVC0_NEW_ZSA },
341 { nvc0_validate_rasterizer, NVC0_NEW_RASTERIZER },
342 { nvc0_validate_blend_colour, NVC0_NEW_BLEND_COLOUR },
343 { nvc0_validate_stencil_ref, NVC0_NEW_STENCIL_REF },
344 { nvc0_validate_stipple, NVC0_NEW_STIPPLE },
345 { nvc0_validate_scissor, NVC0_NEW_SCISSOR | NVC0_NEW_FRAMEBUFFER |
346 NVC0_NEW_RASTERIZER },
347 { nvc0_validate_viewport, NVC0_NEW_VIEWPORT },
348 { nvc0_validate_clip, NVC0_NEW_CLIP },
349 { nvc0_vertprog_validate, NVC0_NEW_VERTPROG },
350 { nvc0_tctlprog_validate, NVC0_NEW_TCTLPROG },
351 { nvc0_tevlprog_validate, NVC0_NEW_TEVLPROG },
352 { nvc0_gmtyprog_validate, NVC0_NEW_GMTYPROG },
353 { nvc0_fragprog_validate, NVC0_NEW_FRAGPROG },
354 { nvc0_constbufs_validate, NVC0_NEW_CONSTBUF },
355 { nvc0_validate_textures, NVC0_NEW_TEXTURES },
356 { nvc0_validate_samplers, NVC0_NEW_SAMPLERS },
357 { nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS }
358 };
359 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
360
361 boolean
362 nvc0_state_validate(struct nvc0_context *nvc0)
363 {
364 unsigned i;
365 #if 0
366 if (nvc0->screen->cur_ctx != nvc0) /* FIXME: not everything is valid */
367 nvc0->dirty = 0xffffffff;
368 #endif
369 nvc0->screen->cur_ctx = nvc0;
370
371 if (nvc0->dirty) {
372 for (i = 0; i < validate_list_len; ++i) {
373 struct state_validate *validate = &validate_list[i];
374
375 if (nvc0->dirty & validate->states)
376 validate->func(nvc0);
377 }
378 nvc0->dirty = 0;
379 }
380
381 nvc0_bufctx_emit_relocs(nvc0);
382
383 return TRUE;
384 }