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