Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / drivers / nvc0 / nvc0_state_validate.c
1
2 #include "util/u_math.h"
3
4 #include "nvc0_context.h"
5
6 static void
7 nvc0_validate_zcull(struct nvc0_context *nvc0)
8 {
9     struct nouveau_channel *chan = nvc0->screen->base.channel;
10     struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
11     struct nvc0_surface *sf = nvc0_surface(fb->zsbuf);
12     struct nvc0_miptree *mt = nvc0_miptree(sf->base.texture);
13     struct nouveau_bo *bo = mt->base.bo;
14     uint32_t size;
15     uint32_t offset = align(mt->total_size, 1 << 17);
16     unsigned width, height;
17
18     assert(mt->base.base.depth0 == 1 && mt->base.base.array_size < 2);
19
20     size = mt->total_size * 2;
21
22     height = align(fb->height, 32);
23     width = fb->width % 224;
24     if (width)
25        width = fb->width + (224 - width);
26     else
27        width = fb->width;
28
29     MARK_RING (chan, 23, 4);
30     BEGIN_RING(chan, RING_3D_(0x1590), 1); /* ZCULL_REGION_INDEX (bits 0x3f) */
31     OUT_RING  (chan, 0);
32     BEGIN_RING(chan, RING_3D_(0x07e8), 2); /* ZCULL_ADDRESS_A_HIGH */
33     OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
34     OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
35     offset += 1 << 17;
36     BEGIN_RING(chan, RING_3D_(0x07f0), 2); /* ZCULL_ADDRESS_B_HIGH */
37     OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
38     OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
39     BEGIN_RING(chan, RING_3D_(0x07e0), 2);
40     OUT_RING  (chan, size);
41     OUT_RING  (chan, size >> 16);
42     BEGIN_RING(chan, RING_3D_(0x15c8), 1); /* bits 0x3 */
43     OUT_RING  (chan, 2);
44     BEGIN_RING(chan, RING_3D_(0x07c0), 4); /* ZCULL dimensions */
45     OUT_RING  (chan, width);
46     OUT_RING  (chan, height);
47     OUT_RING  (chan, 1);
48     OUT_RING  (chan, 0);
49     BEGIN_RING(chan, RING_3D_(0x15fc), 2);
50     OUT_RING  (chan, 0); /* bits 0xffff */
51     OUT_RING  (chan, 0); /* bits 0xffff */
52     BEGIN_RING(chan, RING_3D_(0x1958), 1);
53     OUT_RING  (chan, 0); /* bits ~0 */
54 }
55
56 static void
57 nvc0_validate_fb(struct nvc0_context *nvc0)
58 {
59     struct nouveau_channel *chan = nvc0->screen->base.channel;
60     struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
61     unsigned i;
62     boolean serialize = FALSE;
63
64     nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_FRAME);
65
66     BEGIN_RING(chan, RING_3D(RT_CONTROL), 1);
67     OUT_RING  (chan, (076543210 << 4) | fb->nr_cbufs);
68     BEGIN_RING(chan, RING_3D(SCREEN_SCISSOR_HORIZ), 2);
69     OUT_RING  (chan, fb->width << 16);
70     OUT_RING  (chan, fb->height << 16);
71
72     MARK_RING(chan, 9 * fb->nr_cbufs, 2 * fb->nr_cbufs);
73
74     for (i = 0; i < fb->nr_cbufs; ++i) {
75         struct nvc0_miptree *mt = nvc0_miptree(fb->cbufs[i]->texture);
76         struct nvc0_surface *sf = nvc0_surface(fb->cbufs[i]);
77         struct nouveau_bo *bo = mt->base.bo;
78         uint32_t offset = sf->offset;
79
80         BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(i)), 9);
81         OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
82         OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
83         OUT_RING  (chan, sf->width);
84         OUT_RING  (chan, sf->height);
85         OUT_RING  (chan, nvc0_format_table[sf->base.format].rt);
86         OUT_RING  (chan, (mt->layout_3d << 16) |
87                    mt->level[sf->base.u.tex.level].tile_mode);
88         OUT_RING  (chan, sf->base.u.tex.first_layer + sf->depth);
89         OUT_RING  (chan, mt->layer_stride >> 2);
90         OUT_RING  (chan, sf->base.u.tex.first_layer);
91
92         if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
93            serialize = TRUE;
94         mt->base.status |=  NOUVEAU_BUFFER_STATUS_GPU_WRITING;
95         mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
96
97         /* only register for writing, otherwise we'd always serialize here */
98         nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base,
99                                  NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
100     }
101
102     if (fb->zsbuf) {
103         struct nvc0_miptree *mt = nvc0_miptree(fb->zsbuf->texture);
104         struct nvc0_surface *sf = nvc0_surface(fb->zsbuf);
105         struct nouveau_bo *bo = mt->base.bo;
106         int unk = mt->base.base.target == PIPE_TEXTURE_2D;
107         uint32_t offset = sf->offset;
108
109         MARK_RING (chan, 12, 2);
110         BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
111         OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
112         OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
113         OUT_RING  (chan, nvc0_format_table[fb->zsbuf->format].rt);
114         OUT_RING  (chan, mt->level[sf->base.u.tex.level].tile_mode);
115         OUT_RING  (chan, mt->layer_stride >> 2);
116         BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
117         OUT_RING  (chan, 1);
118         BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);
119         OUT_RING  (chan, sf->width);
120         OUT_RING  (chan, sf->height);
121         OUT_RING  (chan, (unk << 16) |
122                    (sf->base.u.tex.first_layer + sf->depth));
123         BEGIN_RING(chan, RING_3D(ZETA_BASE_LAYER), 1);
124         OUT_RING  (chan, sf->base.u.tex.first_layer);
125
126         if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
127            serialize = TRUE;
128         mt->base.status |=  NOUVEAU_BUFFER_STATUS_GPU_WRITING;
129         mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
130
131         nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_FRAME, &mt->base,
132                                  NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
133     } else {
134         BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
135         OUT_RING  (chan, 0);
136     }
137
138     if (serialize) {
139        BEGIN_RING(chan, RING_3D(SERIALIZE), 1);
140        OUT_RING  (chan, 0);
141     }
142 }
143
144 static void
145 nvc0_validate_blend_colour(struct nvc0_context *nvc0)
146 {
147     struct nouveau_channel *chan = nvc0->screen->base.channel;
148
149     BEGIN_RING(chan, RING_3D(BLEND_COLOR(0)), 4);
150     OUT_RINGf (chan, nvc0->blend_colour.color[0]);
151     OUT_RINGf (chan, nvc0->blend_colour.color[1]);
152     OUT_RINGf (chan, nvc0->blend_colour.color[2]);
153     OUT_RINGf (chan, nvc0->blend_colour.color[3]);    
154 }
155
156 static void
157 nvc0_validate_stencil_ref(struct nvc0_context *nvc0)
158 {
159     struct nouveau_channel *chan = nvc0->screen->base.channel;
160     const ubyte *ref = &nvc0->stencil_ref.ref_value[0];
161
162     IMMED_RING(chan, RING_3D(STENCIL_FRONT_FUNC_REF), ref[0]);
163     IMMED_RING(chan, RING_3D(STENCIL_BACK_FUNC_REF), ref[1]);
164 }
165
166 static void
167 nvc0_validate_stipple(struct nvc0_context *nvc0)
168 {
169     struct nouveau_channel *chan = nvc0->screen->base.channel;
170     unsigned i;
171
172     BEGIN_RING(chan, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
173     for (i = 0; i < 32; ++i)
174         OUT_RING(chan, util_bswap32(nvc0->stipple.stipple[i]));
175 }
176
177 static void
178 nvc0_validate_scissor(struct nvc0_context *nvc0)
179 {
180     struct nouveau_channel *chan = nvc0->screen->base.channel;
181     struct pipe_scissor_state *s = &nvc0->scissor;
182
183     if (!(nvc0->dirty & NVC0_NEW_SCISSOR) &&
184         nvc0->rast->pipe.scissor == nvc0->state.scissor)
185        return;
186     nvc0->state.scissor = nvc0->rast->pipe.scissor;
187
188     BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
189     if (nvc0->rast->pipe.scissor) {
190        OUT_RING(chan, (s->maxx << 16) | s->minx);
191        OUT_RING(chan, (s->maxy << 16) | s->miny);
192     } else {
193        OUT_RING(chan, (0xffff << 16) | 0);
194        OUT_RING(chan, (0xffff << 16) | 0);
195     }
196 }
197
198 static void
199 nvc0_validate_viewport(struct nvc0_context *nvc0)
200 {
201     struct nouveau_channel *chan = nvc0->screen->base.channel;
202     struct pipe_viewport_state *vp = &nvc0->viewport;
203     int x, y, w, h;
204     float zmin, zmax;
205
206     BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
207     OUT_RINGf (chan, vp->translate[0]);
208     OUT_RINGf (chan, vp->translate[1]);
209     OUT_RINGf (chan, vp->translate[2]);
210     BEGIN_RING(chan, RING_3D(VIEWPORT_SCALE_X(0)), 3);
211     OUT_RINGf (chan, vp->scale[0]);
212     OUT_RINGf (chan, vp->scale[1]);
213     OUT_RINGf (chan, vp->scale[2]);
214
215     /* now set the viewport rectangle to viewport dimensions for clipping */
216
217     x = util_iround(MAX2(0.0f, vp->translate[0] - fabsf(vp->scale[0])));
218     y = util_iround(MAX2(0.0f, vp->translate[1] - fabsf(vp->scale[1])));
219     w = util_iround(vp->translate[0] + fabsf(vp->scale[0])) - x;
220     h = util_iround(vp->translate[1] + fabsf(vp->scale[1])) - y;
221
222     zmin = vp->translate[2] - fabsf(vp->scale[2]);
223     zmax = vp->translate[2] + fabsf(vp->scale[2]);
224
225     BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
226     OUT_RING  (chan, (w << 16) | x);
227     OUT_RING  (chan, (h << 16) | y);
228     BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
229     OUT_RINGf (chan, zmin);
230     OUT_RINGf (chan, zmax);
231 }
232
233 static void
234 nvc0_validate_clip(struct nvc0_context *nvc0)
235 {
236    struct nouveau_channel *chan = nvc0->screen->base.channel;
237    uint32_t clip;
238
239    if (nvc0->clip.depth_clamp) {
240       clip =
241          NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1 |
242          NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR |
243          NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR |
244          NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2;
245    } else {
246       clip = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1;
247    }
248
249    BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1);
250    OUT_RING  (chan, clip);
251
252    if (nvc0->clip.nr) {
253       struct nouveau_bo *bo = nvc0->screen->uniforms;
254
255       MARK_RING (chan, 6 + nvc0->clip.nr * 4, 2);
256       BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
257       OUT_RING  (chan, 256);
258       OUT_RELOCh(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
259       OUT_RELOCl(chan, bo, 5 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
260       BEGIN_RING_1I(chan, RING_3D(CB_POS), nvc0->clip.nr * 4 + 1);
261       OUT_RING  (chan, 0);
262       OUT_RINGp (chan, &nvc0->clip.ucp[0][0], nvc0->clip.nr * 4);
263
264       BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1);
265       OUT_RING  (chan, (1 << nvc0->clip.nr) - 1);
266    } else {
267       IMMED_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 0);
268    }
269 }
270
271 static void
272 nvc0_validate_blend(struct nvc0_context *nvc0)
273 {
274    struct nouveau_channel *chan = nvc0->screen->base.channel;
275
276    WAIT_RING(chan, nvc0->blend->size);
277    OUT_RINGp(chan, nvc0->blend->state, nvc0->blend->size);
278 }
279
280 static void
281 nvc0_validate_zsa(struct nvc0_context *nvc0)
282 {
283    struct nouveau_channel *chan = nvc0->screen->base.channel;
284
285    WAIT_RING(chan, nvc0->zsa->size);
286    OUT_RINGp(chan, nvc0->zsa->state, nvc0->zsa->size);
287 }
288
289 static void
290 nvc0_validate_rasterizer(struct nvc0_context *nvc0)
291 {
292    struct nouveau_channel *chan = nvc0->screen->base.channel;
293
294    WAIT_RING(chan, nvc0->rast->size);
295    OUT_RINGp(chan, nvc0->rast->state, nvc0->rast->size);
296 }
297
298 static void
299 nvc0_constbufs_validate(struct nvc0_context *nvc0)
300 {
301    struct nouveau_channel *chan = nvc0->screen->base.channel;
302    struct nouveau_bo *bo;
303    unsigned s;
304
305    for (s = 0; s < 5; ++s) {
306       struct nv04_resource *res;
307       int i;
308
309       while (nvc0->constbuf_dirty[s]) {
310          unsigned base = 0;
311          unsigned offset = 0, words = 0;
312          boolean rebind = TRUE;
313
314          i = ffs(nvc0->constbuf_dirty[s]) - 1;
315          nvc0->constbuf_dirty[s] &= ~(1 << i);
316
317          res = nv04_resource(nvc0->constbuf[s][i]);
318          if (!res) {
319             BEGIN_RING(chan, RING_3D(CB_BIND(s)), 1);
320             OUT_RING  (chan, (i << 4) | 0);
321             if (i == 0)
322                nvc0->state.uniform_buffer_bound[s] = 0;
323             continue;
324          }
325
326          if (!nouveau_resource_mapped_by_gpu(&res->base)) {
327             if (i == 0) {
328                base = s << 16;
329                bo = nvc0->screen->uniforms;
330
331                if (nvc0->state.uniform_buffer_bound[s] >= res->base.width0)
332                   rebind = FALSE;
333                else
334                   nvc0->state.uniform_buffer_bound[s] =
335                      align(res->base.width0, 0x100);
336             } else {
337                bo = res->bo;
338             }
339 #if 0
340             nvc0_m2mf_push_linear(nvc0, bo, NOUVEAU_BO_VRAM,
341                                   base, res->base.width0, res->data);
342             BEGIN_RING(chan, RING_3D_(0x021c), 1);
343             OUT_RING  (chan, 0x1111);
344 #else
345             words = res->base.width0 / 4;
346 #endif
347          } else {
348             bo = res->bo;
349             if (i == 0)
350                nvc0->state.uniform_buffer_bound[s] = 0;
351          }
352
353          if (bo != nvc0->screen->uniforms)
354             nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_CONSTANT, res,
355                                      NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
356
357          if (rebind) {
358             MARK_RING (chan, 4, 2);
359             BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
360             OUT_RING  (chan, align(res->base.width0, 0x100));
361             OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
362             OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
363             BEGIN_RING(chan, RING_3D(CB_BIND(s)), 1);
364             OUT_RING  (chan, (i << 4) | 1);
365          }
366
367          while (words) {
368             unsigned nr = AVAIL_RING(chan);
369
370             if (nr < 16) {
371                FIRE_RING(chan);
372                continue;
373             }
374             nr = MIN2(MIN2(nr - 6, words), NV04_PFIFO_MAX_PACKET_LEN - 1);
375
376             MARK_RING (chan, nr + 5, 2);
377             BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
378             OUT_RING  (chan, align(res->base.width0, 0x100));
379             OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
380             OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
381             BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1);
382             OUT_RING  (chan, offset);
383             OUT_RINGp (chan, &res->data[offset], nr);
384
385             offset += nr * 4;
386             words -= nr;
387          }
388       }
389    }
390 }
391
392 static void
393 nvc0_validate_derived_1(struct nvc0_context *nvc0)
394 {
395    struct nouveau_channel *chan = nvc0->screen->base.channel;
396    boolean early_z;
397
398    early_z = nvc0->fragprog->fp.early_z && !nvc0->zsa->pipe.alpha.enabled;
399
400    if (early_z != nvc0->state.early_z) {
401       nvc0->state.early_z = early_z;
402       IMMED_RING(chan, RING_3D(EARLY_FRAGMENT_TESTS), early_z);
403    }
404 }
405
406 static void
407 nvc0_switch_pipe_context(struct nvc0_context *ctx_to)
408 {
409    struct nvc0_context *ctx_from = ctx_to->screen->cur_ctx;
410
411    if (ctx_from)
412       ctx_to->state = ctx_from->state;
413
414    ctx_to->dirty = ~0;
415
416    if (!ctx_to->vertex)
417       ctx_to->dirty &= ~(NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS);
418
419    if (!ctx_to->vertprog)
420       ctx_to->dirty &= ~NVC0_NEW_VERTPROG;
421    if (!ctx_to->fragprog)
422       ctx_to->dirty &= ~NVC0_NEW_FRAGPROG;
423
424    if (!ctx_to->blend)
425       ctx_to->dirty &= ~NVC0_NEW_BLEND;
426    if (!ctx_to->rast)
427       ctx_to->dirty &= ~NVC0_NEW_RASTERIZER;
428    if (!ctx_to->zsa)
429       ctx_to->dirty &= ~NVC0_NEW_ZSA;
430
431    ctx_to->screen->base.channel->user_private = ctx_to->screen->cur_ctx =
432       ctx_to;
433 }
434
435 static struct state_validate {
436     void (*func)(struct nvc0_context *);
437     uint32_t states;
438 } validate_list[] = {
439     { nvc0_validate_fb,            NVC0_NEW_FRAMEBUFFER },
440     { nvc0_validate_blend,         NVC0_NEW_BLEND },
441     { nvc0_validate_zsa,           NVC0_NEW_ZSA },
442     { nvc0_validate_rasterizer,    NVC0_NEW_RASTERIZER },
443     { nvc0_validate_blend_colour,  NVC0_NEW_BLEND_COLOUR },
444     { nvc0_validate_stencil_ref,   NVC0_NEW_STENCIL_REF },
445     { nvc0_validate_stipple,       NVC0_NEW_STIPPLE },
446     { nvc0_validate_scissor,       NVC0_NEW_SCISSOR | NVC0_NEW_RASTERIZER },
447     { nvc0_validate_viewport,      NVC0_NEW_VIEWPORT },
448     { nvc0_validate_clip,          NVC0_NEW_CLIP },
449     { nvc0_vertprog_validate,      NVC0_NEW_VERTPROG },
450     { nvc0_tctlprog_validate,      NVC0_NEW_TCTLPROG },
451     { nvc0_tevlprog_validate,      NVC0_NEW_TEVLPROG },
452     { nvc0_gmtyprog_validate,      NVC0_NEW_GMTYPROG },
453     { nvc0_fragprog_validate,      NVC0_NEW_FRAGPROG },
454     { nvc0_validate_derived_1,     NVC0_NEW_FRAGPROG | NVC0_NEW_ZSA },
455     { nvc0_constbufs_validate,     NVC0_NEW_CONSTBUF },
456     { nvc0_validate_textures,      NVC0_NEW_TEXTURES },
457     { nvc0_validate_samplers,      NVC0_NEW_SAMPLERS },
458     { nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS },
459     { nvc0_tfb_validate,           NVC0_NEW_TFB | NVC0_NEW_TFB_BUFFERS }
460 };
461 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
462
463 boolean
464 nvc0_state_validate(struct nvc0_context *nvc0)
465 {
466    unsigned i;
467
468    if (nvc0->screen->cur_ctx != nvc0)
469       nvc0_switch_pipe_context(nvc0);
470
471    if (nvc0->dirty) {
472       for (i = 0; i < validate_list_len; ++i) {
473          struct state_validate *validate = &validate_list[i];
474
475          if (nvc0->dirty & validate->states)
476             validate->func(nvc0);
477       }
478       nvc0->dirty = 0;
479    }
480
481    nvc0_bufctx_emit_relocs(nvc0);
482
483    return TRUE;
484 }