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