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