nvc0: generate shader header for geometry programs
[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
198 static void
199 nvc0_validate_blend(struct nvc0_context *nvc0)
200 {
201 struct nouveau_channel *chan = nvc0->screen->base.channel;
202
203 WAIT_RING(chan, nvc0->blend->size);
204 OUT_RINGp(chan, nvc0->blend->state, nvc0->blend->size);
205 }
206
207 static void
208 nvc0_validate_zsa(struct nvc0_context *nvc0)
209 {
210 struct nouveau_channel *chan = nvc0->screen->base.channel;
211
212 WAIT_RING(chan, nvc0->zsa->size);
213 OUT_RINGp(chan, nvc0->zsa->state, nvc0->zsa->size);
214 }
215
216 static void
217 nvc0_validate_rasterizer(struct nvc0_context *nvc0)
218 {
219 struct nouveau_channel *chan = nvc0->screen->base.channel;
220
221 WAIT_RING(chan, nvc0->rast->size);
222 OUT_RINGp(chan, nvc0->rast->state, nvc0->rast->size);
223 }
224
225 static void
226 nvc0_constbufs_validate(struct nvc0_context *nvc0)
227 {
228 struct nouveau_channel *chan = nvc0->screen->base.channel;
229 struct nouveau_bo *bo;
230 unsigned s;
231
232 for (s = 0; s < 5; ++s) {
233 struct nvc0_resource *res;
234 int i;
235
236 while (nvc0->constbuf_dirty[s]) {
237 unsigned base = 0;
238 unsigned offset = 0, words = 0;
239 boolean rebind = TRUE;
240
241 i = ffs(nvc0->constbuf_dirty[s]) - 1;
242 nvc0->constbuf_dirty[s] &= ~(1 << i);
243
244 res = nvc0_resource(nvc0->constbuf[s][i]);
245 if (!res) {
246 BEGIN_RING(chan, RING_3D(CB_BIND(s)), 1);
247 OUT_RING (chan, (i << 4) | 0);
248 if (i == 0)
249 nvc0->state.uniform_buffer_bound &= ~(1 << s);
250 continue;
251 }
252
253 if (!nvc0_resource_mapped_by_gpu(&res->base)) {
254 if (i == 0) {
255 base = s << 16;
256 bo = nvc0->screen->uniforms;
257
258 if (nvc0->state.uniform_buffer_bound & (1 << s))
259 rebind = FALSE;
260 else
261 nvc0->state.uniform_buffer_bound |= (1 << s);
262 } else {
263 bo = res->bo;
264 }
265 #if 1
266 nvc0_m2mf_push_linear(nvc0, bo, NOUVEAU_BO_VRAM,
267 base, res->base.width0, res->data);
268 BEGIN_RING(chan, RING_3D_(0x021c), 1);
269 OUT_RING (chan, 0x1111);
270 #else
271 words = res->base.width0 / 4;
272 #endif
273 } else {
274 bo = res->bo;
275 if (i == 0)
276 nvc0->state.uniform_buffer_bound &= ~(1 << s);
277 }
278
279 if (bo != nvc0->screen->uniforms)
280 nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_CONSTANT, res,
281 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
282
283 if (rebind) {
284 BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
285 OUT_RING (chan, align(res->base.width0, 0x100));
286 OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
287 OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
288 BEGIN_RING(chan, RING_3D(CB_BIND(s)), 1);
289 OUT_RING (chan, (i << 4) | 1);
290 }
291
292 while (words) {
293 unsigned nr = AVAIL_RING(chan);
294
295 if (nr < 16) {
296 FIRE_RING(chan);
297 continue;
298 }
299 nr = MIN2(MIN2(nr - 6, words), NV04_PFIFO_MAX_PACKET_LEN - 1);
300
301 BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
302 OUT_RING (chan, align(res->base.width0, 0x100));
303 OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
304 OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
305 BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1);
306 OUT_RING (chan, offset);
307 OUT_RINGp (chan, &res->data[offset], nr);
308
309 offset += nr * 4;
310 words -= nr;
311 }
312 }
313 }
314 }
315
316 static struct state_validate {
317 void (*func)(struct nvc0_context *);
318 uint32_t states;
319 } validate_list[] = {
320 { nvc0_validate_fb, NVC0_NEW_FRAMEBUFFER },
321 { nvc0_validate_blend, NVC0_NEW_BLEND },
322 { nvc0_validate_zsa, NVC0_NEW_ZSA },
323 { nvc0_validate_rasterizer, NVC0_NEW_RASTERIZER },
324 { nvc0_validate_blend_colour, NVC0_NEW_BLEND_COLOUR },
325 { nvc0_validate_stencil_ref, NVC0_NEW_STENCIL_REF },
326 { nvc0_validate_stipple, NVC0_NEW_STIPPLE },
327 { nvc0_validate_scissor, NVC0_NEW_SCISSOR | NVC0_NEW_FRAMEBUFFER |
328 NVC0_NEW_RASTERIZER },
329 { nvc0_validate_viewport, NVC0_NEW_VIEWPORT },
330 { nvc0_validate_clip, NVC0_NEW_CLIP },
331 { nvc0_vertprog_validate, NVC0_NEW_VERTPROG },
332 { nvc0_tctlprog_validate, NVC0_NEW_TCTLPROG },
333 { nvc0_tevlprog_validate, NVC0_NEW_TEVLPROG },
334 { nvc0_gmtyprog_validate, NVC0_NEW_GMTYPROG },
335 { nvc0_fragprog_validate, NVC0_NEW_FRAGPROG },
336 { nvc0_constbufs_validate, NVC0_NEW_CONSTBUF },
337 { nvc0_validate_textures, NVC0_NEW_TEXTURES },
338 { nvc0_validate_samplers, NVC0_NEW_SAMPLERS },
339 { nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS }
340 };
341 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
342
343 boolean
344 nvc0_state_validate(struct nvc0_context *nvc0)
345 {
346 unsigned i;
347 #if 0
348 if (nvc0->screen->cur_ctx != nvc0) /* FIXME: not everything is valid */
349 nvc0->dirty = 0xffffffff;
350 #endif
351 nvc0->screen->cur_ctx = nvc0;
352
353 if (nvc0->dirty) {
354 for (i = 0; i < validate_list_len; ++i) {
355 struct state_validate *validate = &validate_list[i];
356
357 if (nvc0->dirty & validate->states)
358 validate->func(nvc0);
359 }
360 nvc0->dirty = 0;
361 }
362
363 nvc0_bufctx_emit_relocs(nvc0);
364
365 return TRUE;
366 }