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