nvc0: implement point coord replacement
[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_validate_sprite_coords(struct nvc0_context *nvc0)
290 {
291 struct nouveau_channel *chan = nvc0->screen->base.channel;
292 uint32_t reg;
293
294 if (nvc0->rast->pipe.sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT)
295 reg = NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT;
296 else
297 reg = NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT;
298
299 if (nvc0->rast->pipe.point_quad_rasterization) {
300 uint32_t en = nvc0->rast->pipe.sprite_coord_enable;
301 int i;
302 struct nvc0_program *prog = nvc0->fragprog;
303
304 while (en) {
305 i = ffs(en) - 1;
306 en &= ~(1 << i);
307 if (prog->fp.in_pos[i] >= 0xc0 && prog->fp.in_pos[i] < 0xe0)
308 reg |= 8 << ((prog->fp.in_pos[i] - 0xc0) / 4);
309 }
310 }
311
312 BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE), 1);
313 OUT_RING (chan, reg);
314 }
315
316 static void
317 nvc0_constbufs_validate(struct nvc0_context *nvc0)
318 {
319 struct nouveau_channel *chan = nvc0->screen->base.channel;
320 struct nouveau_bo *bo;
321 unsigned s;
322
323 for (s = 0; s < 5; ++s) {
324 struct nvc0_resource *res;
325 int i;
326
327 while (nvc0->constbuf_dirty[s]) {
328 unsigned base = 0;
329 unsigned offset = 0, words = 0;
330 boolean rebind = TRUE;
331
332 i = ffs(nvc0->constbuf_dirty[s]) - 1;
333 nvc0->constbuf_dirty[s] &= ~(1 << i);
334
335 res = nvc0_resource(nvc0->constbuf[s][i]);
336 if (!res) {
337 BEGIN_RING(chan, RING_3D(CB_BIND(s)), 1);
338 OUT_RING (chan, (i << 4) | 0);
339 if (i == 0)
340 nvc0->state.uniform_buffer_bound[s] = 0;
341 continue;
342 }
343
344 if (!nvc0_resource_mapped_by_gpu(&res->base)) {
345 if (i == 0) {
346 base = s << 16;
347 bo = nvc0->screen->uniforms;
348
349 if (nvc0->state.uniform_buffer_bound[s] >= res->base.width0)
350 rebind = FALSE;
351 else
352 nvc0->state.uniform_buffer_bound[s] =
353 align(res->base.width0, 0x100);
354 } else {
355 bo = res->bo;
356 }
357 #if 0
358 nvc0_m2mf_push_linear(nvc0, bo, NOUVEAU_BO_VRAM,
359 base, res->base.width0, res->data);
360 BEGIN_RING(chan, RING_3D_(0x021c), 1);
361 OUT_RING (chan, 0x1111);
362 #else
363 words = res->base.width0 / 4;
364 #endif
365 } else {
366 bo = res->bo;
367 if (i == 0)
368 nvc0->state.uniform_buffer_bound[s] = 0;
369 }
370
371 if (bo != nvc0->screen->uniforms)
372 nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_CONSTANT, res,
373 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
374
375 if (rebind) {
376 MARK_RING (chan, 4, 2);
377 BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
378 OUT_RING (chan, align(res->base.width0, 0x100));
379 OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
380 OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
381 BEGIN_RING(chan, RING_3D(CB_BIND(s)), 1);
382 OUT_RING (chan, (i << 4) | 1);
383 }
384
385 while (words) {
386 unsigned nr = AVAIL_RING(chan);
387
388 if (nr < 16) {
389 FIRE_RING(chan);
390 continue;
391 }
392 nr = MIN2(MIN2(nr - 6, words), NV04_PFIFO_MAX_PACKET_LEN - 1);
393
394 MARK_RING (chan, nr + 5, 2);
395 BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
396 OUT_RING (chan, align(res->base.width0, 0x100));
397 OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
398 OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
399 BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1);
400 OUT_RING (chan, offset);
401 OUT_RINGp (chan, &res->data[offset], nr);
402
403 offset += nr * 4;
404 words -= nr;
405 }
406 }
407 }
408 }
409
410 static struct state_validate {
411 void (*func)(struct nvc0_context *);
412 uint32_t states;
413 } validate_list[] = {
414 { nvc0_validate_fb, NVC0_NEW_FRAMEBUFFER },
415 { nvc0_validate_blend, NVC0_NEW_BLEND },
416 { nvc0_validate_zsa, NVC0_NEW_ZSA },
417 { nvc0_validate_rasterizer, NVC0_NEW_RASTERIZER },
418 { nvc0_validate_blend_colour, NVC0_NEW_BLEND_COLOUR },
419 { nvc0_validate_stencil_ref, NVC0_NEW_STENCIL_REF },
420 { nvc0_validate_stipple, NVC0_NEW_STIPPLE },
421 #ifdef NVC0_SCISSORS_CLIPPING
422 { nvc0_validate_scissor, NVC0_NEW_SCISSOR | NVC0_NEW_VIEWPORT |
423 NVC0_NEW_RASTERIZER |
424 NVC0_NEW_FRAMEBUFFER },
425 #else
426 { nvc0_validate_scissor, NVC0_NEW_SCISSOR },
427 #endif
428 { nvc0_validate_viewport, NVC0_NEW_VIEWPORT },
429 { nvc0_validate_clip, NVC0_NEW_CLIP },
430 { nvc0_vertprog_validate, NVC0_NEW_VERTPROG },
431 { nvc0_tctlprog_validate, NVC0_NEW_TCTLPROG },
432 { nvc0_tevlprog_validate, NVC0_NEW_TEVLPROG },
433 { nvc0_gmtyprog_validate, NVC0_NEW_GMTYPROG },
434 { nvc0_fragprog_validate, NVC0_NEW_FRAGPROG },
435 { nvc0_validate_sprite_coords, NVC0_NEW_RASTERIZER | NVC0_NEW_FRAGPROG },
436 { nvc0_constbufs_validate, NVC0_NEW_CONSTBUF },
437 { nvc0_validate_textures, NVC0_NEW_TEXTURES },
438 { nvc0_validate_samplers, NVC0_NEW_SAMPLERS },
439 { nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS }
440 };
441 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
442
443 boolean
444 nvc0_state_validate(struct nvc0_context *nvc0)
445 {
446 unsigned i;
447 #if 0
448 if (nvc0->screen->cur_ctx != nvc0) /* FIXME: not everything is valid */
449 nvc0->dirty = 0xffffffff;
450 #endif
451 nvc0->screen->cur_ctx = nvc0;
452
453 if (nvc0->dirty) {
454 for (i = 0; i < validate_list_len; ++i) {
455 struct state_validate *validate = &validate_list[i];
456
457 if (nvc0->dirty & validate->states)
458 validate->func(nvc0);
459 }
460 nvc0->dirty = 0;
461 }
462
463 nvc0_bufctx_emit_relocs(nvc0);
464
465 return TRUE;
466 }