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