nv50_state_validate.c revision b2dcf880e8bcd61be59602f5a2d18c77a5fc60c1
1
2#include "nv50_context.h"
3#include "os/os_time.h"
4
5static void
6nv50_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      OUT_RING  (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
35      OUT_RING  (chan, mt->layer_stride >> 2);
36      BEGIN_RING(chan, RING_3D(RT_HORIZ(i)), 2);
37      OUT_RING  (chan, sf->width);
38      OUT_RING  (chan, sf->height);
39      BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1);
40      OUT_RING  (chan, sf->depth);
41
42      ms_mode = mt->ms_mode;
43
44      if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
45         serialize = TRUE;
46      mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
47      mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING;
48
49      /* only register for writing, otherwise we'd always serialize here */
50      nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base,
51                               NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
52   }
53
54   if (fb->zsbuf) {
55      struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
56      struct nv50_surface *sf = nv50_surface(fb->zsbuf);
57      struct nouveau_bo *bo = mt->base.bo;
58      int unk = mt->base.base.target == PIPE_TEXTURE_2D;
59      uint32_t offset = sf->offset;
60
61      MARK_RING (chan, 12, 2);
62      BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
63      OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
64      OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
65      OUT_RING  (chan, nv50_format_table[fb->zsbuf->format].rt);
66      OUT_RING  (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
67      OUT_RING  (chan, mt->layer_stride >> 2);
68      BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
69      OUT_RING  (chan, 1);
70      BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);
71      OUT_RING  (chan, sf->width);
72      OUT_RING  (chan, sf->height);
73      OUT_RING  (chan, (unk << 16) | sf->depth);
74
75      ms_mode = mt->ms_mode;
76
77      if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
78         serialize = TRUE;
79      mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
80      mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING;
81
82      nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base,
83                               NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
84   } else {
85      BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
86      OUT_RING  (chan, 0);
87   }
88
89   BEGIN_RING(chan, RING_3D(MULTISAMPLE_MODE), 1);
90   OUT_RING  (chan, ms_mode);
91
92   BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
93   OUT_RING  (chan, fb->width << 16);
94   OUT_RING  (chan, fb->height << 16);
95
96   if (serialize) {
97      BEGIN_RING(chan, RING_3D(SERIALIZE), 1);
98      OUT_RING  (chan, 0);
99   }
100}
101
102static void
103nv50_validate_blend_colour(struct nv50_context *nv50)
104{
105   struct nouveau_channel *chan = nv50->screen->base.channel;
106
107   BEGIN_RING(chan, RING_3D(BLEND_COLOR(0)), 4);
108   OUT_RINGf (chan, nv50->blend_colour.color[0]);
109   OUT_RINGf (chan, nv50->blend_colour.color[1]);
110   OUT_RINGf (chan, nv50->blend_colour.color[2]);
111   OUT_RINGf (chan, nv50->blend_colour.color[3]);
112}
113
114static void
115nv50_validate_stencil_ref(struct nv50_context *nv50)
116{
117   struct nouveau_channel *chan = nv50->screen->base.channel;
118
119   BEGIN_RING(chan, RING_3D(STENCIL_FRONT_FUNC_REF), 1);
120   OUT_RING  (chan, nv50->stencil_ref.ref_value[0]);
121   BEGIN_RING(chan, RING_3D(STENCIL_BACK_FUNC_REF), 1);
122   OUT_RING  (chan, nv50->stencil_ref.ref_value[1]);
123}
124
125static void
126nv50_validate_stipple(struct nv50_context *nv50)
127{
128   struct nouveau_channel *chan = nv50->screen->base.channel;
129   unsigned i;
130
131   BEGIN_RING(chan, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
132   for (i = 0; i < 32; ++i)
133      OUT_RING(chan, util_bswap32(nv50->stipple.stipple[i]));
134}
135
136static void
137nv50_validate_scissor(struct nv50_context *nv50)
138{
139   struct nouveau_channel *chan = nv50->screen->base.channel;
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_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
169   OUT_RING  (chan, (maxx << 16) | minx);
170   OUT_RING  (chan, (maxy << 16) | miny);
171#else
172   BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
173   OUT_RING  (chan, (s->maxx << 16) | s->minx);
174   OUT_RING  (chan, (s->maxy << 16) | s->miny);
175#endif
176}
177
178static void
179nv50_validate_viewport(struct nv50_context *nv50)
180{
181   struct nouveau_channel *chan = nv50->screen->base.channel;
182   float zmin, zmax;
183
184   BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
185   OUT_RINGf (chan, nv50->viewport.translate[0]);
186   OUT_RINGf (chan, nv50->viewport.translate[1]);
187   OUT_RINGf (chan, nv50->viewport.translate[2]);
188   BEGIN_RING(chan, RING_3D(VIEWPORT_SCALE_X(0)), 3);
189   OUT_RINGf (chan, nv50->viewport.scale[0]);
190   OUT_RINGf (chan, nv50->viewport.scale[1]);
191   OUT_RINGf (chan, 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_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
198   OUT_RINGf (chan, zmin);
199   OUT_RINGf (chan, zmax);
200#endif
201}
202
203static void
204nv50_validate_clip(struct nv50_context *nv50)
205{
206   struct nouveau_channel *chan = nv50->screen->base.channel;
207   uint32_t clip;
208
209   if (nv50->clip.depth_clamp) {
210      clip =
211         NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR |
212         NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR |
213         NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1;
214   } else {
215      clip = 0;
216   }
217
218#ifndef NV50_SCISSORS_CLIPPING
219   clip |=
220      NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK7 |
221      NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1;
222#endif
223
224   BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1);
225   OUT_RING  (chan, clip);
226
227   if (nv50->clip.nr) {
228      BEGIN_RING(chan, RING_3D(CB_ADDR), 1);
229      OUT_RING  (chan, (0 << 8) | NV50_CB_AUX);
230      BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nv50->clip.nr * 4);
231      OUT_RINGp (chan, &nv50->clip.ucp[0][0], nv50->clip.nr * 4);
232   }
233
234   BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1);
235   OUT_RING  (chan, (1 << nv50->clip.nr) - 1);
236
237   if (nv50->vertprog && nv50->clip.nr > nv50->vertprog->vp.clpd_nr)
238      nv50->dirty |= NV50_NEW_VERTPROG;
239}
240
241static void
242nv50_validate_blend(struct nv50_context *nv50)
243{
244   struct nouveau_channel *chan = nv50->screen->base.channel;
245
246   WAIT_RING(chan, nv50->blend->size);
247   OUT_RINGp(chan, nv50->blend->state, nv50->blend->size);
248}
249
250static void
251nv50_validate_zsa(struct nv50_context *nv50)
252{
253   struct nouveau_channel *chan = nv50->screen->base.channel;
254
255   WAIT_RING(chan, nv50->zsa->size);
256   OUT_RINGp(chan, nv50->zsa->state, nv50->zsa->size);
257}
258
259static void
260nv50_validate_rasterizer(struct nv50_context *nv50)
261{
262   struct nouveau_channel *chan = nv50->screen->base.channel;
263
264   WAIT_RING(chan, nv50->rast->size);
265   OUT_RINGp(chan, nv50->rast->state, nv50->rast->size);
266}
267
268static void
269nv50_validate_sample_mask(struct nv50_context *nv50)
270{
271   struct nouveau_channel *chan = nv50->screen->base.channel;
272
273   unsigned mask[4] =
274   {
275      nv50->sample_mask & 0xffff,
276      nv50->sample_mask & 0xffff,
277      nv50->sample_mask & 0xffff,
278      nv50->sample_mask & 0xffff
279   };
280
281   BEGIN_RING(chan, RING_3D(MSAA_MASK(0)), 4);
282   OUT_RING  (chan, mask[0]);
283   OUT_RING  (chan, mask[1]);
284   OUT_RING  (chan, mask[2]);
285   OUT_RING  (chan, mask[3]);
286}
287
288static void
289nv50_switch_pipe_context(struct nv50_context *ctx_to)
290{
291   struct nv50_context *ctx_from = ctx_to->screen->cur_ctx;
292
293   if (ctx_from)
294      ctx_to->state = ctx_from->state;
295
296   ctx_to->dirty = ~0;
297
298   if (!ctx_to->vertex)
299      ctx_to->dirty &= ~(NV50_NEW_VERTEX | NV50_NEW_ARRAYS);
300
301   if (!ctx_to->vertprog)
302      ctx_to->dirty &= ~NV50_NEW_VERTPROG;
303   if (!ctx_to->fragprog)
304      ctx_to->dirty &= ~NV50_NEW_FRAGPROG;
305
306   if (!ctx_to->blend)
307      ctx_to->dirty &= ~NV50_NEW_BLEND;
308   if (!ctx_to->rast)
309      ctx_to->dirty &= ~NV50_NEW_RASTERIZER;
310   if (!ctx_to->zsa)
311      ctx_to->dirty &= ~NV50_NEW_ZSA;
312
313   ctx_to->screen->cur_ctx = ctx_to;
314}
315
316static struct state_validate {
317    void (*func)(struct nv50_context *);
318    uint32_t states;
319} validate_list[] = {
320    { nv50_validate_fb,            NV50_NEW_FRAMEBUFFER },
321    { nv50_validate_blend,         NV50_NEW_BLEND },
322    { nv50_validate_zsa,           NV50_NEW_ZSA },
323    { nv50_validate_sample_mask,   NV50_NEW_SAMPLE_MASK },
324    { nv50_validate_rasterizer,    NV50_NEW_RASTERIZER },
325    { nv50_validate_blend_colour,  NV50_NEW_BLEND_COLOUR },
326    { nv50_validate_stencil_ref,   NV50_NEW_STENCIL_REF },
327    { nv50_validate_stipple,       NV50_NEW_STIPPLE },
328#ifdef NV50_SCISSORS_CLIPPING
329    { nv50_validate_scissor,       NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT |
330                                   NV50_NEW_RASTERIZER |
331                                   NV50_NEW_FRAMEBUFFER },
332#else
333    { nv50_validate_scissor,       NV50_NEW_SCISSOR },
334#endif
335    { nv50_validate_viewport,      NV50_NEW_VIEWPORT },
336    { nv50_validate_clip,          NV50_NEW_CLIP },
337    { nv50_vertprog_validate,      NV50_NEW_VERTPROG },
338    { nv50_gmtyprog_validate,      NV50_NEW_GMTYPROG },
339    { nv50_fragprog_validate,      NV50_NEW_FRAGPROG },
340    { nv50_fp_linkage_validate,    NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
341                                   NV50_NEW_GMTYPROG },
342    { nv50_gp_linkage_validate,    NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG },
343    { nv50_validate_derived_rs,    NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER |
344                                   NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
345    { nv50_constbufs_validate,     NV50_NEW_CONSTBUF },
346    { nv50_validate_textures,      NV50_NEW_TEXTURES },
347    { nv50_validate_samplers,      NV50_NEW_SAMPLERS },
348    { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS }
349};
350#define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
351
352boolean
353nv50_state_validate(struct nv50_context *nv50)
354{
355   unsigned i;
356
357   if (nv50->screen->cur_ctx != nv50)
358      nv50_switch_pipe_context(nv50);
359
360   if (nv50->dirty) {
361      for (i = 0; i < validate_list_len; ++i) {
362         struct state_validate *validate = &validate_list[i];
363
364         if (nv50->dirty & validate->states)
365            validate->func(nv50);
366      }
367      nv50->dirty = 0;
368   }
369
370   nv50_bufctx_emit_relocs(nv50);
371
372   return TRUE;
373}
374