05f32ea78d2447750a9f93d495ded30b12c9fcb8
[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 void
217 nv50_validate_clip(struct nv50_context *nv50)
218 {
219 struct nouveau_channel *chan = nv50->screen->base.channel;
220 uint32_t clip;
221
222 if (nv50->clip.depth_clamp) {
223 clip =
224 NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR |
225 NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR |
226 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1;
227 } else {
228 clip = 0;
229 }
230
231 #ifndef NV50_SCISSORS_CLIPPING
232 clip |=
233 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK7 |
234 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1;
235 #endif
236
237 BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1);
238 OUT_RING (chan, clip);
239
240 if (nv50->clip.nr) {
241 BEGIN_RING(chan, RING_3D(CB_ADDR), 1);
242 OUT_RING (chan, (0 << 8) | NV50_CB_AUX);
243 BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nv50->clip.nr * 4);
244 OUT_RINGp (chan, &nv50->clip.ucp[0][0], nv50->clip.nr * 4);
245 }
246
247 BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1);
248 OUT_RING (chan, (1 << nv50->clip.nr) - 1);
249
250 if (nv50->vertprog && nv50->clip.nr > nv50->vertprog->vp.clpd_nr)
251 nv50->dirty |= NV50_NEW_VERTPROG;
252 }
253
254 static void
255 nv50_validate_blend(struct nv50_context *nv50)
256 {
257 struct nouveau_channel *chan = nv50->screen->base.channel;
258
259 WAIT_RING(chan, nv50->blend->size);
260 OUT_RINGp(chan, nv50->blend->state, nv50->blend->size);
261 }
262
263 static void
264 nv50_validate_zsa(struct nv50_context *nv50)
265 {
266 struct nouveau_channel *chan = nv50->screen->base.channel;
267
268 WAIT_RING(chan, nv50->zsa->size);
269 OUT_RINGp(chan, nv50->zsa->state, nv50->zsa->size);
270 }
271
272 static void
273 nv50_validate_rasterizer(struct nv50_context *nv50)
274 {
275 struct nouveau_channel *chan = nv50->screen->base.channel;
276
277 WAIT_RING(chan, nv50->rast->size);
278 OUT_RINGp(chan, nv50->rast->state, nv50->rast->size);
279 }
280
281 static void
282 nv50_validate_sample_mask(struct nv50_context *nv50)
283 {
284 struct nouveau_channel *chan = nv50->screen->base.channel;
285
286 unsigned mask[4] =
287 {
288 nv50->sample_mask & 0xffff,
289 nv50->sample_mask & 0xffff,
290 nv50->sample_mask & 0xffff,
291 nv50->sample_mask & 0xffff
292 };
293
294 BEGIN_RING(chan, RING_3D(MSAA_MASK(0)), 4);
295 OUT_RING (chan, mask[0]);
296 OUT_RING (chan, mask[1]);
297 OUT_RING (chan, mask[2]);
298 OUT_RING (chan, mask[3]);
299 }
300
301 static void
302 nv50_switch_pipe_context(struct nv50_context *ctx_to)
303 {
304 struct nv50_context *ctx_from = ctx_to->screen->cur_ctx;
305
306 if (ctx_from)
307 ctx_to->state = ctx_from->state;
308
309 ctx_to->dirty = ~0;
310
311 if (!ctx_to->vertex)
312 ctx_to->dirty &= ~(NV50_NEW_VERTEX | NV50_NEW_ARRAYS);
313
314 if (!ctx_to->vertprog)
315 ctx_to->dirty &= ~NV50_NEW_VERTPROG;
316 if (!ctx_to->fragprog)
317 ctx_to->dirty &= ~NV50_NEW_FRAGPROG;
318
319 if (!ctx_to->blend)
320 ctx_to->dirty &= ~NV50_NEW_BLEND;
321 if (!ctx_to->rast)
322 #ifdef NV50_SCISSORS_CLIPPING
323 ctx_to->dirty &= ~(NV50_NEW_RASTERIZER | NV50_NEW_SCISSOR);
324 #else
325 ctx_to->dirty &= ~NV50_NEW_RASTERIZER;
326 #endif
327 if (!ctx_to->zsa)
328 ctx_to->dirty &= ~NV50_NEW_ZSA;
329
330 ctx_to->screen->cur_ctx = ctx_to;
331 }
332
333 static struct state_validate {
334 void (*func)(struct nv50_context *);
335 uint32_t states;
336 } validate_list[] = {
337 { nv50_validate_fb, NV50_NEW_FRAMEBUFFER },
338 { nv50_validate_blend, NV50_NEW_BLEND },
339 { nv50_validate_zsa, NV50_NEW_ZSA },
340 { nv50_validate_sample_mask, NV50_NEW_SAMPLE_MASK },
341 { nv50_validate_rasterizer, NV50_NEW_RASTERIZER },
342 { nv50_validate_blend_colour, NV50_NEW_BLEND_COLOUR },
343 { nv50_validate_stencil_ref, NV50_NEW_STENCIL_REF },
344 { nv50_validate_stipple, NV50_NEW_STIPPLE },
345 #ifdef NV50_SCISSORS_CLIPPING
346 { nv50_validate_scissor, NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT |
347 NV50_NEW_RASTERIZER |
348 NV50_NEW_FRAMEBUFFER },
349 #else
350 { nv50_validate_scissor, NV50_NEW_SCISSOR },
351 #endif
352 { nv50_validate_viewport, NV50_NEW_VIEWPORT },
353 { nv50_validate_clip, NV50_NEW_CLIP },
354 { nv50_vertprog_validate, NV50_NEW_VERTPROG },
355 { nv50_gmtyprog_validate, NV50_NEW_GMTYPROG },
356 { nv50_fragprog_validate, NV50_NEW_FRAGPROG },
357 { nv50_fp_linkage_validate, NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
358 NV50_NEW_GMTYPROG },
359 { nv50_gp_linkage_validate, NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG },
360 { nv50_validate_derived_rs, NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER |
361 NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
362 { nv50_constbufs_validate, NV50_NEW_CONSTBUF },
363 { nv50_validate_textures, NV50_NEW_TEXTURES },
364 { nv50_validate_samplers, NV50_NEW_SAMPLERS },
365 { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS }
366 };
367 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
368
369 boolean
370 nv50_state_validate(struct nv50_context *nv50, uint32_t mask, unsigned words)
371 {
372 uint32_t state_mask;
373 unsigned i;
374
375 if (nv50->screen->cur_ctx != nv50)
376 nv50_switch_pipe_context(nv50);
377
378 state_mask = nv50->dirty & mask;
379
380 if (state_mask) {
381 for (i = 0; i < validate_list_len; ++i) {
382 struct state_validate *validate = &validate_list[i];
383
384 if (state_mask & validate->states)
385 validate->func(nv50);
386 }
387 nv50->dirty &= ~state_mask;
388 }
389
390 MARK_RING(nv50->screen->base.channel, words, 0);
391
392 nv50_bufctx_emit_relocs(nv50);
393
394 return TRUE;
395 }