95592533bb3f3068630bf15ac38c51612513e6c6
[mesa.git] / src / gallium / drivers / nouveau / nv50 / nv50_state_validate.c
1
2 #include "nv50/nv50_context.h"
3 #include "nv50/nv50_defs.xml.h"
4
5 static INLINE void
6 nv50_fb_set_null_rt(struct nouveau_pushbuf *push, unsigned i)
7 {
8 BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(i)), 4);
9 PUSH_DATA (push, 0);
10 PUSH_DATA (push, 0);
11 PUSH_DATA (push, NV50_SURFACE_FORMAT_NONE);
12 PUSH_DATA (push, 0);
13 BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);
14 PUSH_DATA (push, 64);
15 PUSH_DATA (push, 0);
16 }
17
18 static void
19 nv50_validate_fb(struct nv50_context *nv50)
20 {
21 struct nouveau_pushbuf *push = nv50->base.pushbuf;
22 struct pipe_framebuffer_state *fb = &nv50->framebuffer;
23 unsigned i;
24 unsigned ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1;
25 uint32_t array_size = 0xffff, array_mode = 0;
26
27 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
28
29 BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);
30 PUSH_DATA (push, (076543210 << 4) | fb->nr_cbufs);
31 BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);
32 PUSH_DATA (push, fb->width << 16);
33 PUSH_DATA (push, fb->height << 16);
34
35 for (i = 0; i < fb->nr_cbufs; ++i) {
36 struct nv50_miptree *mt;
37 struct nv50_surface *sf;
38 struct nouveau_bo *bo;
39
40 if (!fb->cbufs[i]) {
41 nv50_fb_set_null_rt(push, i);
42 continue;
43 }
44
45 mt = nv50_miptree(fb->cbufs[i]->texture);
46 sf = nv50_surface(fb->cbufs[i]);
47 bo = mt->base.bo;
48
49 array_size = MIN2(array_size, sf->depth);
50 if (mt->layout_3d)
51 array_mode = NV50_3D_RT_ARRAY_MODE_MODE_3D; /* 1 << 16 */
52
53 /* can't mix 3D with ARRAY or have RTs of different depth/array_size */
54 assert(mt->layout_3d || !array_mode || array_size == 1);
55
56 BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(i)), 5);
57 PUSH_DATAh(push, bo->offset + sf->offset);
58 PUSH_DATA (push, bo->offset + sf->offset);
59 PUSH_DATA (push, nv50_format_table[sf->base.format].rt);
60 if (likely(nouveau_bo_memtype(bo))) {
61 PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
62 PUSH_DATA (push, mt->layer_stride >> 2);
63 BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);
64 PUSH_DATA (push, sf->width);
65 PUSH_DATA (push, sf->height);
66 BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);
67 PUSH_DATA (push, array_mode | array_size);
68 } else {
69 PUSH_DATA (push, 0);
70 PUSH_DATA (push, 0);
71 BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);
72 PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | mt->level[0].pitch);
73 PUSH_DATA (push, sf->height);
74 BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);
75 PUSH_DATA (push, 0);
76
77 assert(!fb->zsbuf);
78 assert(!mt->ms_mode);
79 }
80
81 ms_mode = mt->ms_mode;
82
83 if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
84 nv50->state.rt_serialize = TRUE;
85 mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
86 mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
87
88 /* only register for writing, otherwise we'd always serialize here */
89 BCTX_REFN(nv50->bufctx_3d, FB, &mt->base, WR);
90 }
91
92 if (fb->zsbuf) {
93 struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
94 struct nv50_surface *sf = nv50_surface(fb->zsbuf);
95 struct nouveau_bo *bo = mt->base.bo;
96 int unk = mt->base.base.target == PIPE_TEXTURE_3D || sf->depth == 1;
97
98 BEGIN_NV04(push, NV50_3D(ZETA_ADDRESS_HIGH), 5);
99 PUSH_DATAh(push, bo->offset + sf->offset);
100 PUSH_DATA (push, bo->offset + sf->offset);
101 PUSH_DATA (push, nv50_format_table[fb->zsbuf->format].rt);
102 PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
103 PUSH_DATA (push, mt->layer_stride >> 2);
104 BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
105 PUSH_DATA (push, 1);
106 BEGIN_NV04(push, NV50_3D(ZETA_HORIZ), 3);
107 PUSH_DATA (push, sf->width);
108 PUSH_DATA (push, sf->height);
109 PUSH_DATA (push, (unk << 16) | sf->depth);
110
111 ms_mode = mt->ms_mode;
112
113 if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
114 nv50->state.rt_serialize = TRUE;
115 mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
116 mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
117
118 BCTX_REFN(nv50->bufctx_3d, FB, &mt->base, WR);
119 } else {
120 BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
121 PUSH_DATA (push, 0);
122 }
123
124 BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);
125 PUSH_DATA (push, ms_mode);
126
127 BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
128 PUSH_DATA (push, fb->width << 16);
129 PUSH_DATA (push, fb->height << 16);
130 }
131
132 static void
133 nv50_validate_blend_colour(struct nv50_context *nv50)
134 {
135 struct nouveau_pushbuf *push = nv50->base.pushbuf;
136
137 BEGIN_NV04(push, NV50_3D(BLEND_COLOR(0)), 4);
138 PUSH_DATAf(push, nv50->blend_colour.color[0]);
139 PUSH_DATAf(push, nv50->blend_colour.color[1]);
140 PUSH_DATAf(push, nv50->blend_colour.color[2]);
141 PUSH_DATAf(push, nv50->blend_colour.color[3]);
142 }
143
144 static void
145 nv50_validate_stencil_ref(struct nv50_context *nv50)
146 {
147 struct nouveau_pushbuf *push = nv50->base.pushbuf;
148
149 BEGIN_NV04(push, NV50_3D(STENCIL_FRONT_FUNC_REF), 1);
150 PUSH_DATA (push, nv50->stencil_ref.ref_value[0]);
151 BEGIN_NV04(push, NV50_3D(STENCIL_BACK_FUNC_REF), 1);
152 PUSH_DATA (push, nv50->stencil_ref.ref_value[1]);
153 }
154
155 static void
156 nv50_validate_stipple(struct nv50_context *nv50)
157 {
158 struct nouveau_pushbuf *push = nv50->base.pushbuf;
159 unsigned i;
160
161 BEGIN_NV04(push, NV50_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
162 for (i = 0; i < 32; ++i)
163 PUSH_DATA(push, util_bswap32(nv50->stipple.stipple[i]));
164 }
165
166 static void
167 nv50_validate_scissor(struct nv50_context *nv50)
168 {
169 struct nouveau_pushbuf *push = nv50->base.pushbuf;
170 struct pipe_scissor_state *s = &nv50->scissor;
171 #ifdef NV50_SCISSORS_CLIPPING
172 struct pipe_viewport_state *vp = &nv50->viewport;
173 int minx, maxx, miny, maxy;
174
175 if (!(nv50->dirty &
176 (NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | NV50_NEW_FRAMEBUFFER)) &&
177 nv50->state.scissor == nv50->rast->pipe.scissor)
178 return;
179 nv50->state.scissor = nv50->rast->pipe.scissor;
180
181 if (nv50->state.scissor) {
182 minx = s->minx;
183 maxx = s->maxx;
184 miny = s->miny;
185 maxy = s->maxy;
186 } else {
187 minx = 0;
188 maxx = nv50->framebuffer.width;
189 miny = 0;
190 maxy = nv50->framebuffer.height;
191 }
192
193 minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
194 maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
195 miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
196 maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
197
198 BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
199 PUSH_DATA (push, (maxx << 16) | minx);
200 PUSH_DATA (push, (maxy << 16) | miny);
201 #else
202 BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
203 PUSH_DATA (push, (s->maxx << 16) | s->minx);
204 PUSH_DATA (push, (s->maxy << 16) | s->miny);
205 #endif
206 }
207
208 static void
209 nv50_validate_viewport(struct nv50_context *nv50)
210 {
211 struct nouveau_pushbuf *push = nv50->base.pushbuf;
212 float zmin, zmax;
213
214 BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSLATE_X(0)), 3);
215 PUSH_DATAf(push, nv50->viewport.translate[0]);
216 PUSH_DATAf(push, nv50->viewport.translate[1]);
217 PUSH_DATAf(push, nv50->viewport.translate[2]);
218 BEGIN_NV04(push, NV50_3D(VIEWPORT_SCALE_X(0)), 3);
219 PUSH_DATAf(push, nv50->viewport.scale[0]);
220 PUSH_DATAf(push, nv50->viewport.scale[1]);
221 PUSH_DATAf(push, nv50->viewport.scale[2]);
222
223 zmin = nv50->viewport.translate[2] - fabsf(nv50->viewport.scale[2]);
224 zmax = nv50->viewport.translate[2] + fabsf(nv50->viewport.scale[2]);
225
226 #ifdef NV50_SCISSORS_CLIPPING
227 BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(0)), 2);
228 PUSH_DATAf(push, zmin);
229 PUSH_DATAf(push, zmax);
230 #endif
231 }
232
233 static INLINE void
234 nv50_check_program_ucps(struct nv50_context *nv50,
235 struct nv50_program *vp, uint8_t mask)
236 {
237 const unsigned n = util_logbase2(mask) + 1;
238
239 if (vp->vp.clpd_nr >= n)
240 return;
241 nv50_program_destroy(nv50, vp);
242
243 vp->vp.clpd_nr = n;
244 if (likely(vp == nv50->vertprog)) {
245 nv50->dirty |= NV50_NEW_VERTPROG;
246 nv50_vertprog_validate(nv50);
247 } else {
248 nv50->dirty |= NV50_NEW_GMTYPROG;
249 nv50_gmtyprog_validate(nv50);
250 }
251 nv50_fp_linkage_validate(nv50);
252 }
253
254 static void
255 nv50_validate_clip(struct nv50_context *nv50)
256 {
257 struct nouveau_pushbuf *push = nv50->base.pushbuf;
258 struct nv50_program *vp;
259 uint8_t clip_enable;
260
261 if (nv50->dirty & NV50_NEW_CLIP) {
262 BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
263 PUSH_DATA (push, (NV50_CB_AUX_UCP_OFFSET << 8) | NV50_CB_AUX);
264 BEGIN_NI04(push, NV50_3D(CB_DATA(0)), PIPE_MAX_CLIP_PLANES * 4);
265 PUSH_DATAp(push, &nv50->clip.ucp[0][0], PIPE_MAX_CLIP_PLANES * 4);
266 }
267
268 vp = nv50->gmtyprog;
269 if (likely(!vp))
270 vp = nv50->vertprog;
271
272 clip_enable = nv50->rast->pipe.clip_plane_enable;
273
274 BEGIN_NV04(push, NV50_3D(CLIP_DISTANCE_ENABLE), 1);
275 PUSH_DATA (push, clip_enable);
276
277 if (clip_enable)
278 nv50_check_program_ucps(nv50, vp, clip_enable);
279 }
280
281 static void
282 nv50_validate_blend(struct nv50_context *nv50)
283 {
284 struct nouveau_pushbuf *push = nv50->base.pushbuf;
285
286 PUSH_SPACE(push, nv50->blend->size);
287 PUSH_DATAp(push, nv50->blend->state, nv50->blend->size);
288 }
289
290 static void
291 nv50_validate_zsa(struct nv50_context *nv50)
292 {
293 struct nouveau_pushbuf *push = nv50->base.pushbuf;
294
295 PUSH_SPACE(push, nv50->zsa->size);
296 PUSH_DATAp(push, nv50->zsa->state, nv50->zsa->size);
297 }
298
299 static void
300 nv50_validate_rasterizer(struct nv50_context *nv50)
301 {
302 struct nouveau_pushbuf *push = nv50->base.pushbuf;
303
304 PUSH_SPACE(push, nv50->rast->size);
305 PUSH_DATAp(push, nv50->rast->state, nv50->rast->size);
306 }
307
308 static void
309 nv50_validate_sample_mask(struct nv50_context *nv50)
310 {
311 struct nouveau_pushbuf *push = nv50->base.pushbuf;
312
313 unsigned mask[4] =
314 {
315 nv50->sample_mask & 0xffff,
316 nv50->sample_mask & 0xffff,
317 nv50->sample_mask & 0xffff,
318 nv50->sample_mask & 0xffff
319 };
320
321 BEGIN_NV04(push, NV50_3D(MSAA_MASK(0)), 4);
322 PUSH_DATA (push, mask[0]);
323 PUSH_DATA (push, mask[1]);
324 PUSH_DATA (push, mask[2]);
325 PUSH_DATA (push, mask[3]);
326 }
327
328 static void
329 nv50_switch_pipe_context(struct nv50_context *ctx_to)
330 {
331 struct nv50_context *ctx_from = ctx_to->screen->cur_ctx;
332
333 if (ctx_from)
334 ctx_to->state = ctx_from->state;
335
336 ctx_to->dirty = ~0;
337
338 if (!ctx_to->vertex)
339 ctx_to->dirty &= ~(NV50_NEW_VERTEX | NV50_NEW_ARRAYS);
340
341 if (!ctx_to->vertprog)
342 ctx_to->dirty &= ~NV50_NEW_VERTPROG;
343 if (!ctx_to->fragprog)
344 ctx_to->dirty &= ~NV50_NEW_FRAGPROG;
345
346 if (!ctx_to->blend)
347 ctx_to->dirty &= ~NV50_NEW_BLEND;
348 if (!ctx_to->rast)
349 #ifdef NV50_SCISSORS_CLIPPING
350 ctx_to->dirty &= ~(NV50_NEW_RASTERIZER | NV50_NEW_SCISSOR);
351 #else
352 ctx_to->dirty &= ~NV50_NEW_RASTERIZER;
353 #endif
354 if (!ctx_to->zsa)
355 ctx_to->dirty &= ~NV50_NEW_ZSA;
356
357 ctx_to->screen->cur_ctx = ctx_to;
358 }
359
360 static struct state_validate {
361 void (*func)(struct nv50_context *);
362 uint32_t states;
363 } validate_list[] = {
364 { nv50_validate_fb, NV50_NEW_FRAMEBUFFER },
365 { nv50_validate_blend, NV50_NEW_BLEND },
366 { nv50_validate_zsa, NV50_NEW_ZSA },
367 { nv50_validate_sample_mask, NV50_NEW_SAMPLE_MASK },
368 { nv50_validate_rasterizer, NV50_NEW_RASTERIZER },
369 { nv50_validate_blend_colour, NV50_NEW_BLEND_COLOUR },
370 { nv50_validate_stencil_ref, NV50_NEW_STENCIL_REF },
371 { nv50_validate_stipple, NV50_NEW_STIPPLE },
372 #ifdef NV50_SCISSORS_CLIPPING
373 { nv50_validate_scissor, NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT |
374 NV50_NEW_RASTERIZER |
375 NV50_NEW_FRAMEBUFFER },
376 #else
377 { nv50_validate_scissor, NV50_NEW_SCISSOR },
378 #endif
379 { nv50_validate_viewport, NV50_NEW_VIEWPORT },
380 { nv50_vertprog_validate, NV50_NEW_VERTPROG },
381 { nv50_gmtyprog_validate, NV50_NEW_GMTYPROG },
382 { nv50_fragprog_validate, NV50_NEW_FRAGPROG },
383 { nv50_fp_linkage_validate, NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
384 NV50_NEW_GMTYPROG | NV50_NEW_RASTERIZER },
385 { nv50_gp_linkage_validate, NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG },
386 { nv50_validate_derived_rs, NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER |
387 NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
388 { nv50_validate_clip, NV50_NEW_CLIP | NV50_NEW_RASTERIZER |
389 NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
390 { nv50_constbufs_validate, NV50_NEW_CONSTBUF },
391 { nv50_validate_textures, NV50_NEW_TEXTURES },
392 { nv50_validate_samplers, NV50_NEW_SAMPLERS },
393 { nv50_stream_output_validate, NV50_NEW_STRMOUT |
394 NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
395 { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS }
396 };
397 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
398
399 boolean
400 nv50_state_validate(struct nv50_context *nv50, uint32_t mask, unsigned words)
401 {
402 uint32_t state_mask;
403 int ret;
404 unsigned i;
405
406 if (nv50->screen->cur_ctx != nv50)
407 nv50_switch_pipe_context(nv50);
408
409 state_mask = nv50->dirty & mask;
410
411 if (state_mask) {
412 for (i = 0; i < validate_list_len; ++i) {
413 struct state_validate *validate = &validate_list[i];
414
415 if (state_mask & validate->states)
416 validate->func(nv50);
417 }
418 nv50->dirty &= ~state_mask;
419
420 if (nv50->state.rt_serialize) {
421 nv50->state.rt_serialize = FALSE;
422 BEGIN_NV04(nv50->base.pushbuf, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);
423 PUSH_DATA (nv50->base.pushbuf, 0);
424 }
425
426 nv50_bufctx_fence(nv50->bufctx_3d, FALSE);
427 }
428 nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx_3d);
429 ret = nouveau_pushbuf_validate(nv50->base.pushbuf);
430
431 if (unlikely(nv50->state.flushed)) {
432 nv50->state.flushed = FALSE;
433 nv50_bufctx_fence(nv50->bufctx_3d, TRUE);
434 }
435 return !ret;
436 }