• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include "util/u_framebuffer.h"
3 #include "util/u_math.h"
4 #include "util/u_viewport.h"
5 
6 #include "nvc0/nvc0_context.h"
7 
8 #if 0
9 static void
10 nvc0_validate_zcull(struct nvc0_context *nvc0)
11 {
12     struct nouveau_pushbuf *push = nvc0->base.pushbuf;
13     struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
14     struct nv50_surface *sf = nv50_surface(fb->zsbuf);
15     struct nv50_miptree *mt = nv50_miptree(sf->base.texture);
16     struct nouveau_bo *bo = mt->base.bo;
17     uint32_t size;
18     uint32_t offset = align(mt->total_size, 1 << 17);
19     unsigned width, height;
20 
21     assert(mt->base.base.depth0 == 1 && mt->base.base.array_size < 2);
22 
23     size = mt->total_size * 2;
24 
25     height = align(fb->height, 32);
26     width = fb->width % 224;
27     if (width)
28        width = fb->width + (224 - width);
29     else
30        width = fb->width;
31 
32     BEGIN_NVC0(push, NVC0_3D(ZCULL_REGION), 1);
33     PUSH_DATA (push, 0);
34     BEGIN_NVC0(push, NVC0_3D(ZCULL_ADDRESS_HIGH), 2);
35     PUSH_DATAh(push, bo->offset + offset);
36     PUSH_DATA (push, bo->offset + offset);
37     offset += 1 << 17;
38     BEGIN_NVC0(push, NVC0_3D(ZCULL_LIMIT_HIGH), 2);
39     PUSH_DATAh(push, bo->offset + offset);
40     PUSH_DATA (push, bo->offset + offset);
41     BEGIN_NVC0(push, SUBC_3D(0x07e0), 2);
42     PUSH_DATA (push, size);
43     PUSH_DATA (push, size >> 16);
44     BEGIN_NVC0(push, SUBC_3D(0x15c8), 1); /* bits 0x3 */
45     PUSH_DATA (push, 2);
46     BEGIN_NVC0(push, NVC0_3D(ZCULL_WIDTH), 4);
47     PUSH_DATA (push, width);
48     PUSH_DATA (push, height);
49     PUSH_DATA (push, 1);
50     PUSH_DATA (push, 0);
51     BEGIN_NVC0(push, NVC0_3D(ZCULL_WINDOW_OFFSET_X), 2);
52     PUSH_DATA (push, 0);
53     PUSH_DATA (push, 0);
54     BEGIN_NVC0(push, NVC0_3D(ZCULL_INVALIDATE), 1);
55     PUSH_DATA (push, 0);
56 }
57 #endif
58 
59 static inline void
nvc0_fb_set_null_rt(struct nouveau_pushbuf * push,unsigned i,unsigned layers)60 nvc0_fb_set_null_rt(struct nouveau_pushbuf *push, unsigned i, unsigned layers)
61 {
62    BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(i)), 9);
63    PUSH_DATA (push, 0);
64    PUSH_DATA (push, 0);
65    PUSH_DATA (push, 64);     // width
66    PUSH_DATA (push, 0);      // height
67    PUSH_DATA (push, 0);      // format
68    PUSH_DATA (push, 0);      // tile mode
69    PUSH_DATA (push, layers); // layers
70    PUSH_DATA (push, 0);      // layer stride
71    PUSH_DATA (push, 0);      // base layer
72 }
73 
74 static void
nvc0_validate_fb(struct nvc0_context * nvc0)75 nvc0_validate_fb(struct nvc0_context *nvc0)
76 {
77    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
78    struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
79    struct nvc0_screen *screen = nvc0->screen;
80    unsigned i, ms;
81    unsigned ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1;
82    unsigned nr_cbufs = fb->nr_cbufs;
83    bool serialize = false;
84 
85    nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB);
86 
87    BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
88    PUSH_DATA (push, fb->width << 16);
89    PUSH_DATA (push, fb->height << 16);
90 
91    for (i = 0; i < fb->nr_cbufs; ++i) {
92       struct nv50_surface *sf;
93       struct nv04_resource *res;
94       struct nouveau_bo *bo;
95 
96       if (!fb->cbufs[i]) {
97          nvc0_fb_set_null_rt(push, i, 0);
98          continue;
99       }
100 
101       sf = nv50_surface(fb->cbufs[i]);
102       res = nv04_resource(sf->base.texture);
103       bo = res->bo;
104 
105       BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(i)), 9);
106       PUSH_DATAh(push, res->address + sf->offset);
107       PUSH_DATA (push, res->address + sf->offset);
108       if (likely(nouveau_bo_memtype(bo))) {
109          struct nv50_miptree *mt = nv50_miptree(sf->base.texture);
110 
111          assert(sf->base.texture->target != PIPE_BUFFER);
112 
113          PUSH_DATA(push, sf->width);
114          PUSH_DATA(push, sf->height);
115          PUSH_DATA(push, nvc0_format_table[sf->base.format].rt);
116          PUSH_DATA(push, (mt->layout_3d << 16) |
117                           mt->level[sf->base.u.tex.level].tile_mode);
118          PUSH_DATA(push, sf->base.u.tex.first_layer + sf->depth);
119          PUSH_DATA(push, mt->layer_stride >> 2);
120          PUSH_DATA(push, sf->base.u.tex.first_layer);
121 
122          ms_mode = mt->ms_mode;
123       } else {
124          if (res->base.target == PIPE_BUFFER) {
125             PUSH_DATA(push, 262144);
126             PUSH_DATA(push, 1);
127          } else {
128             PUSH_DATA(push, nv50_miptree(sf->base.texture)->level[0].pitch);
129             PUSH_DATA(push, sf->height);
130          }
131          PUSH_DATA(push, nvc0_format_table[sf->base.format].rt);
132          PUSH_DATA(push, 1 << 12);
133          PUSH_DATA(push, 1);
134          PUSH_DATA(push, 0);
135          PUSH_DATA(push, 0);
136 
137          nvc0_resource_fence(res, NOUVEAU_BO_WR);
138 
139          assert(!fb->zsbuf);
140       }
141 
142       if (res->status & NOUVEAU_BUFFER_STATUS_GPU_READING)
143          serialize = true;
144       res->status |=  NOUVEAU_BUFFER_STATUS_GPU_WRITING;
145       res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
146 
147       /* only register for writing, otherwise we'd always serialize here */
148       BCTX_REFN(nvc0->bufctx_3d, 3D_FB, res, WR);
149    }
150 
151    if (fb->zsbuf) {
152       struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
153       struct nv50_surface *sf = nv50_surface(fb->zsbuf);
154       int unk = mt->base.base.target == PIPE_TEXTURE_2D;
155 
156       BEGIN_NVC0(push, NVC0_3D(ZETA_ADDRESS_HIGH), 5);
157       PUSH_DATAh(push, mt->base.address + sf->offset);
158       PUSH_DATA (push, mt->base.address + sf->offset);
159       PUSH_DATA (push, nvc0_format_table[fb->zsbuf->format].rt);
160       PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
161       PUSH_DATA (push, mt->layer_stride >> 2);
162       BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1);
163       PUSH_DATA (push, 1);
164       BEGIN_NVC0(push, NVC0_3D(ZETA_HORIZ), 3);
165       PUSH_DATA (push, sf->width);
166       PUSH_DATA (push, sf->height);
167       PUSH_DATA (push, (unk << 16) |
168                 (sf->base.u.tex.first_layer + sf->depth));
169       BEGIN_NVC0(push, NVC0_3D(ZETA_BASE_LAYER), 1);
170       PUSH_DATA (push, sf->base.u.tex.first_layer);
171 
172       ms_mode = mt->ms_mode;
173 
174       if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
175          serialize = true;
176       mt->base.status |=  NOUVEAU_BUFFER_STATUS_GPU_WRITING;
177       mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
178 
179       BCTX_REFN(nvc0->bufctx_3d, 3D_FB, &mt->base, WR);
180    } else {
181        BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1);
182       PUSH_DATA (push, 0);
183    }
184 
185    if (nr_cbufs == 0 && !fb->zsbuf) {
186       assert(util_is_power_of_two(fb->samples));
187       assert(fb->samples <= 8);
188 
189       nvc0_fb_set_null_rt(push, 0, fb->layers);
190 
191       if (fb->samples > 1)
192          ms_mode = ffs(fb->samples) - 1;
193       nr_cbufs = 1;
194    }
195 
196    BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1);
197    PUSH_DATA (push, (076543210 << 4) | nr_cbufs);
198    IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), ms_mode);
199 
200    ms = 1 << ms_mode;
201    BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
202    PUSH_DATA (push, NVC0_CB_AUX_SIZE);
203    PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(4));
204    PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(4));
205    BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 2 * ms);
206    PUSH_DATA (push, NVC0_CB_AUX_SAMPLE_INFO);
207    for (i = 0; i < ms; i++) {
208       float xy[2];
209       nvc0->base.pipe.get_sample_position(&nvc0->base.pipe, ms, i, xy);
210       PUSH_DATAf(push, xy[0]);
211       PUSH_DATAf(push, xy[1]);
212    }
213 
214    if (screen->base.class_3d >= GM200_3D_CLASS) {
215       const uint8_t (*ptr)[2] = nvc0_get_sample_locations(ms);
216       uint32_t val[4] = {};
217 
218       for (i = 0; i < 16; i++) {
219          val[i / 4] |= ptr[i % ms][0] << (((i % 4) * 8) + 0);
220          val[i / 4] |= ptr[i % ms][1] << (((i % 4) * 8) + 4);
221       }
222 
223       BEGIN_NVC0(push, SUBC_3D(0x11e0), 4);
224       PUSH_DATAp(push, val, 4);
225    }
226 
227    if (serialize)
228       IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0);
229 
230    NOUVEAU_DRV_STAT(&nvc0->screen->base, gpu_serialize_count, serialize);
231 }
232 
233 static void
nvc0_validate_blend_colour(struct nvc0_context * nvc0)234 nvc0_validate_blend_colour(struct nvc0_context *nvc0)
235 {
236    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
237 
238    BEGIN_NVC0(push, NVC0_3D(BLEND_COLOR(0)), 4);
239    PUSH_DATAf(push, nvc0->blend_colour.color[0]);
240    PUSH_DATAf(push, nvc0->blend_colour.color[1]);
241    PUSH_DATAf(push, nvc0->blend_colour.color[2]);
242    PUSH_DATAf(push, nvc0->blend_colour.color[3]);
243 }
244 
245 static void
nvc0_validate_stencil_ref(struct nvc0_context * nvc0)246 nvc0_validate_stencil_ref(struct nvc0_context *nvc0)
247 {
248     struct nouveau_pushbuf *push = nvc0->base.pushbuf;
249     const ubyte *ref = &nvc0->stencil_ref.ref_value[0];
250 
251     IMMED_NVC0(push, NVC0_3D(STENCIL_FRONT_FUNC_REF), ref[0]);
252     IMMED_NVC0(push, NVC0_3D(STENCIL_BACK_FUNC_REF), ref[1]);
253 }
254 
255 static void
nvc0_validate_stipple(struct nvc0_context * nvc0)256 nvc0_validate_stipple(struct nvc0_context *nvc0)
257 {
258     struct nouveau_pushbuf *push = nvc0->base.pushbuf;
259     unsigned i;
260 
261     BEGIN_NVC0(push, NVC0_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
262     for (i = 0; i < 32; ++i)
263         PUSH_DATA(push, util_bswap32(nvc0->stipple.stipple[i]));
264 }
265 
266 static void
nvc0_validate_scissor(struct nvc0_context * nvc0)267 nvc0_validate_scissor(struct nvc0_context *nvc0)
268 {
269    int i;
270    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
271 
272    if (!(nvc0->dirty_3d & NVC0_NEW_3D_SCISSOR) &&
273       nvc0->rast->pipe.scissor == nvc0->state.scissor)
274       return;
275 
276    if (nvc0->state.scissor != nvc0->rast->pipe.scissor)
277       nvc0->scissors_dirty = (1 << NVC0_MAX_VIEWPORTS) - 1;
278 
279    nvc0->state.scissor = nvc0->rast->pipe.scissor;
280 
281    for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) {
282       struct pipe_scissor_state *s = &nvc0->scissors[i];
283       if (!(nvc0->scissors_dirty & (1 << i)))
284          continue;
285 
286       BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(i)), 2);
287       if (nvc0->rast->pipe.scissor) {
288          PUSH_DATA(push, (s->maxx << 16) | s->minx);
289          PUSH_DATA(push, (s->maxy << 16) | s->miny);
290       } else {
291          PUSH_DATA(push, (0xffff << 16) | 0);
292          PUSH_DATA(push, (0xffff << 16) | 0);
293       }
294    }
295    nvc0->scissors_dirty = 0;
296 }
297 
298 static void
nvc0_validate_viewport(struct nvc0_context * nvc0)299 nvc0_validate_viewport(struct nvc0_context *nvc0)
300 {
301    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
302    int x, y, w, h, i;
303    float zmin, zmax;
304 
305    for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) {
306       struct pipe_viewport_state *vp = &nvc0->viewports[i];
307 
308       if (!(nvc0->viewports_dirty & (1 << i)))
309          continue;
310 
311       BEGIN_NVC0(push, NVC0_3D(VIEWPORT_TRANSLATE_X(i)), 3);
312       PUSH_DATAf(push, vp->translate[0]);
313       PUSH_DATAf(push, vp->translate[1]);
314       PUSH_DATAf(push, vp->translate[2]);
315 
316       BEGIN_NVC0(push, NVC0_3D(VIEWPORT_SCALE_X(i)), 3);
317       PUSH_DATAf(push, vp->scale[0]);
318       PUSH_DATAf(push, vp->scale[1]);
319       PUSH_DATAf(push, vp->scale[2]);
320 
321       /* now set the viewport rectangle to viewport dimensions for clipping */
322 
323       x = util_iround(MAX2(0.0f, vp->translate[0] - fabsf(vp->scale[0])));
324       y = util_iround(MAX2(0.0f, vp->translate[1] - fabsf(vp->scale[1])));
325       w = util_iround(vp->translate[0] + fabsf(vp->scale[0])) - x;
326       h = util_iround(vp->translate[1] + fabsf(vp->scale[1])) - y;
327 
328       BEGIN_NVC0(push, NVC0_3D(VIEWPORT_HORIZ(i)), 2);
329       PUSH_DATA (push, (w << 16) | x);
330       PUSH_DATA (push, (h << 16) | y);
331 
332       /* If the halfz setting ever changes, the viewports will also get
333        * updated. The rast will get updated before the validate function has a
334        * chance to hit, so we can just use it directly without an atom
335        * dependency.
336        */
337       util_viewport_zmin_zmax(vp, nvc0->rast->pipe.clip_halfz, &zmin, &zmax);
338 
339       BEGIN_NVC0(push, NVC0_3D(DEPTH_RANGE_NEAR(i)), 2);
340       PUSH_DATAf(push, zmin);
341       PUSH_DATAf(push, zmax);
342    }
343    nvc0->viewports_dirty = 0;
344 }
345 
346 static void
nvc0_validate_window_rects(struct nvc0_context * nvc0)347 nvc0_validate_window_rects(struct nvc0_context *nvc0)
348 {
349    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
350    bool enable = nvc0->window_rect.rects > 0 || nvc0->window_rect.inclusive;
351    int i;
352 
353    IMMED_NVC0(push, NVC0_3D(CLIP_RECTS_EN), enable);
354    if (!enable)
355       return;
356 
357    IMMED_NVC0(push, NVC0_3D(CLIP_RECTS_MODE), !nvc0->window_rect.inclusive);
358    BEGIN_NVC0(push, NVC0_3D(CLIP_RECT_HORIZ(0)), NVC0_MAX_WINDOW_RECTANGLES * 2);
359    for (i = 0; i < nvc0->window_rect.rects; i++) {
360       struct pipe_scissor_state *s = &nvc0->window_rect.rect[i];
361       PUSH_DATA(push, (s->maxx << 16) | s->minx);
362       PUSH_DATA(push, (s->maxy << 16) | s->miny);
363    }
364    for (; i < NVC0_MAX_WINDOW_RECTANGLES; i++) {
365       PUSH_DATA(push, 0);
366       PUSH_DATA(push, 0);
367    }
368 }
369 
370 static inline void
nvc0_upload_uclip_planes(struct nvc0_context * nvc0,unsigned s)371 nvc0_upload_uclip_planes(struct nvc0_context *nvc0, unsigned s)
372 {
373    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
374    struct nvc0_screen *screen = nvc0->screen;
375 
376    BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
377    PUSH_DATA (push, NVC0_CB_AUX_SIZE);
378    PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s));
379    PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s));
380    BEGIN_1IC0(push, NVC0_3D(CB_POS), PIPE_MAX_CLIP_PLANES * 4 + 1);
381    PUSH_DATA (push, NVC0_CB_AUX_UCP_INFO);
382    PUSH_DATAp(push, &nvc0->clip.ucp[0][0], PIPE_MAX_CLIP_PLANES * 4);
383 }
384 
385 static inline void
nvc0_check_program_ucps(struct nvc0_context * nvc0,struct nvc0_program * vp,uint8_t mask)386 nvc0_check_program_ucps(struct nvc0_context *nvc0,
387                         struct nvc0_program *vp, uint8_t mask)
388 {
389    const unsigned n = util_logbase2(mask) + 1;
390 
391    if (vp->vp.num_ucps >= n)
392       return;
393    nvc0_program_destroy(nvc0, vp);
394 
395    vp->vp.num_ucps = n;
396    if (likely(vp == nvc0->vertprog))
397       nvc0_vertprog_validate(nvc0);
398    else
399    if (likely(vp == nvc0->gmtyprog))
400       nvc0_gmtyprog_validate(nvc0);
401    else
402       nvc0_tevlprog_validate(nvc0);
403 }
404 
405 static void
nvc0_validate_clip(struct nvc0_context * nvc0)406 nvc0_validate_clip(struct nvc0_context *nvc0)
407 {
408    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
409    struct nvc0_program *vp;
410    unsigned stage;
411    uint8_t clip_enable = nvc0->rast->pipe.clip_plane_enable;
412 
413    if (nvc0->gmtyprog) {
414       stage = 3;
415       vp = nvc0->gmtyprog;
416    } else
417    if (nvc0->tevlprog) {
418       stage = 2;
419       vp = nvc0->tevlprog;
420    } else {
421       stage = 0;
422       vp = nvc0->vertprog;
423    }
424 
425    if (clip_enable && vp->vp.num_ucps < PIPE_MAX_CLIP_PLANES)
426       nvc0_check_program_ucps(nvc0, vp, clip_enable);
427 
428    if (nvc0->dirty_3d & (NVC0_NEW_3D_CLIP | (NVC0_NEW_3D_VERTPROG << stage)))
429       if (vp->vp.num_ucps > 0 && vp->vp.num_ucps <= PIPE_MAX_CLIP_PLANES)
430          nvc0_upload_uclip_planes(nvc0, stage);
431 
432    clip_enable &= vp->vp.clip_enable;
433    clip_enable |= vp->vp.cull_enable;
434 
435    if (nvc0->state.clip_enable != clip_enable) {
436       nvc0->state.clip_enable = clip_enable;
437       IMMED_NVC0(push, NVC0_3D(CLIP_DISTANCE_ENABLE), clip_enable);
438    }
439    if (nvc0->state.clip_mode != vp->vp.clip_mode) {
440       nvc0->state.clip_mode = vp->vp.clip_mode;
441       BEGIN_NVC0(push, NVC0_3D(CLIP_DISTANCE_MODE), 1);
442       PUSH_DATA (push, vp->vp.clip_mode);
443    }
444 }
445 
446 static void
nvc0_validate_blend(struct nvc0_context * nvc0)447 nvc0_validate_blend(struct nvc0_context *nvc0)
448 {
449    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
450 
451    PUSH_SPACE(push, nvc0->blend->size);
452    PUSH_DATAp(push, nvc0->blend->state, nvc0->blend->size);
453 }
454 
455 static void
nvc0_validate_zsa(struct nvc0_context * nvc0)456 nvc0_validate_zsa(struct nvc0_context *nvc0)
457 {
458    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
459 
460    PUSH_SPACE(push, nvc0->zsa->size);
461    PUSH_DATAp(push, nvc0->zsa->state, nvc0->zsa->size);
462 }
463 
464 static void
nvc0_validate_rasterizer(struct nvc0_context * nvc0)465 nvc0_validate_rasterizer(struct nvc0_context *nvc0)
466 {
467    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
468 
469    PUSH_SPACE(push, nvc0->rast->size);
470    PUSH_DATAp(push, nvc0->rast->state, nvc0->rast->size);
471 }
472 
473 static void
nvc0_constbufs_validate(struct nvc0_context * nvc0)474 nvc0_constbufs_validate(struct nvc0_context *nvc0)
475 {
476    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
477    unsigned s;
478 
479    for (s = 0; s < 5; ++s) {
480       while (nvc0->constbuf_dirty[s]) {
481          int i = ffs(nvc0->constbuf_dirty[s]) - 1;
482          nvc0->constbuf_dirty[s] &= ~(1 << i);
483 
484          if (nvc0->constbuf[s][i].user) {
485             struct nouveau_bo *bo = nvc0->screen->uniform_bo;
486             const unsigned base = NVC0_CB_USR_INFO(s);
487             const unsigned size = nvc0->constbuf[s][0].size;
488             assert(i == 0); /* we really only want OpenGL uniforms here */
489             assert(nvc0->constbuf[s][0].u.data);
490 
491             if (nvc0->state.uniform_buffer_bound[s] < size) {
492                nvc0->state.uniform_buffer_bound[s] = align(size, 0x100);
493 
494                BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
495                PUSH_DATA (push, nvc0->state.uniform_buffer_bound[s]);
496                PUSH_DATAh(push, bo->offset + base);
497                PUSH_DATA (push, bo->offset + base);
498                BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
499                PUSH_DATA (push, (0 << 4) | 1);
500             }
501             nvc0_cb_bo_push(&nvc0->base, bo, NV_VRAM_DOMAIN(&nvc0->screen->base),
502                          base, nvc0->state.uniform_buffer_bound[s],
503                          0, (size + 3) / 4,
504                          nvc0->constbuf[s][0].u.data);
505          } else {
506             struct nv04_resource *res =
507                nv04_resource(nvc0->constbuf[s][i].u.buf);
508             if (res) {
509                BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
510                PUSH_DATA (push, nvc0->constbuf[s][i].size);
511                PUSH_DATAh(push, res->address + nvc0->constbuf[s][i].offset);
512                PUSH_DATA (push, res->address + nvc0->constbuf[s][i].offset);
513                BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
514                PUSH_DATA (push, (i << 4) | 1);
515 
516                BCTX_REFN(nvc0->bufctx_3d, 3D_CB(s, i), res, RD);
517 
518                nvc0->cb_dirty = 1; /* Force cache flush for UBO. */
519                res->cb_bindings[s] |= 1 << i;
520             } else {
521                BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
522                PUSH_DATA (push, (i << 4) | 0);
523             }
524             if (i == 0)
525                nvc0->state.uniform_buffer_bound[s] = 0;
526          }
527       }
528    }
529 
530    if (nvc0->screen->base.class_3d < NVE4_3D_CLASS) {
531       /* Invalidate all COMPUTE constbufs because they are aliased with 3D. */
532       nvc0->dirty_cp |= NVC0_NEW_CP_CONSTBUF;
533       nvc0->constbuf_dirty[5] |= nvc0->constbuf_valid[5];
534       nvc0->state.uniform_buffer_bound[5] = 0;
535    }
536 }
537 
538 static void
nvc0_validate_buffers(struct nvc0_context * nvc0)539 nvc0_validate_buffers(struct nvc0_context *nvc0)
540 {
541    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
542    struct nvc0_screen *screen = nvc0->screen;
543    int i, s;
544 
545    for (s = 0; s < 5; s++) {
546       BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
547       PUSH_DATA (push, NVC0_CB_AUX_SIZE);
548       PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s));
549       PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s));
550       BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 4 * NVC0_MAX_BUFFERS);
551       PUSH_DATA (push, NVC0_CB_AUX_BUF_INFO(0));
552       for (i = 0; i < NVC0_MAX_BUFFERS; i++) {
553          if (nvc0->buffers[s][i].buffer) {
554             struct nv04_resource *res =
555                nv04_resource(nvc0->buffers[s][i].buffer);
556             PUSH_DATA (push, res->address + nvc0->buffers[s][i].buffer_offset);
557             PUSH_DATAh(push, res->address + nvc0->buffers[s][i].buffer_offset);
558             PUSH_DATA (push, nvc0->buffers[s][i].buffer_size);
559             PUSH_DATA (push, 0);
560             BCTX_REFN(nvc0->bufctx_3d, 3D_BUF, res, RDWR);
561             util_range_add(&res->valid_buffer_range,
562                            nvc0->buffers[s][i].buffer_offset,
563                            nvc0->buffers[s][i].buffer_offset +
564                            nvc0->buffers[s][i].buffer_size);
565          } else {
566             PUSH_DATA (push, 0);
567             PUSH_DATA (push, 0);
568             PUSH_DATA (push, 0);
569             PUSH_DATA (push, 0);
570          }
571       }
572    }
573 
574 }
575 
576 static void
nvc0_validate_sample_mask(struct nvc0_context * nvc0)577 nvc0_validate_sample_mask(struct nvc0_context *nvc0)
578 {
579    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
580 
581    unsigned mask[4] =
582    {
583       nvc0->sample_mask & 0xffff,
584       nvc0->sample_mask & 0xffff,
585       nvc0->sample_mask & 0xffff,
586       nvc0->sample_mask & 0xffff
587    };
588 
589    BEGIN_NVC0(push, NVC0_3D(MSAA_MASK(0)), 4);
590    PUSH_DATA (push, mask[0]);
591    PUSH_DATA (push, mask[1]);
592    PUSH_DATA (push, mask[2]);
593    PUSH_DATA (push, mask[3]);
594 }
595 
596 static void
nvc0_validate_min_samples(struct nvc0_context * nvc0)597 nvc0_validate_min_samples(struct nvc0_context *nvc0)
598 {
599    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
600    int samples;
601 
602    samples = util_next_power_of_two(nvc0->min_samples);
603    if (samples > 1) {
604       // If we're using the incoming sample mask and doing sample shading, we
605       // have to do sample shading "to the max", otherwise there's no way to
606       // tell which sets of samples are covered by the current invocation.
607       // Similarly for reading the framebuffer.
608       if (nvc0->fragprog->fp.sample_mask_in ||
609           nvc0->fragprog->fp.reads_framebuffer)
610          samples = util_framebuffer_get_num_samples(&nvc0->framebuffer);
611       samples |= NVC0_3D_SAMPLE_SHADING_ENABLE;
612    }
613 
614    IMMED_NVC0(push, NVC0_3D(SAMPLE_SHADING), samples);
615 }
616 
617 static void
nvc0_validate_driverconst(struct nvc0_context * nvc0)618 nvc0_validate_driverconst(struct nvc0_context *nvc0)
619 {
620    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
621    struct nvc0_screen *screen = nvc0->screen;
622    int i;
623 
624    for (i = 0; i < 5; ++i) {
625       BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
626       PUSH_DATA (push, NVC0_CB_AUX_SIZE);
627       PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i));
628       PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i));
629       BEGIN_NVC0(push, NVC0_3D(CB_BIND(i)), 1);
630       PUSH_DATA (push, (15 << 4) | 1);
631    }
632 
633    nvc0->dirty_cp |= NVC0_NEW_CP_DRIVERCONST;
634 }
635 
636 static void
nvc0_validate_fp_zsa_rast(struct nvc0_context * nvc0)637 nvc0_validate_fp_zsa_rast(struct nvc0_context *nvc0)
638 {
639    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
640    bool rasterizer_discard;
641 
642    if (nvc0->rast && nvc0->rast->pipe.rasterizer_discard) {
643       rasterizer_discard = true;
644    } else {
645       bool zs = nvc0->zsa &&
646          (nvc0->zsa->pipe.depth.enabled || nvc0->zsa->pipe.stencil[0].enabled);
647       rasterizer_discard = !zs &&
648          (!nvc0->fragprog || !nvc0->fragprog->hdr[18]);
649    }
650 
651    if (rasterizer_discard != nvc0->state.rasterizer_discard) {
652       nvc0->state.rasterizer_discard = rasterizer_discard;
653       IMMED_NVC0(push, NVC0_3D(RASTERIZE_ENABLE), !rasterizer_discard);
654    }
655 }
656 
657 /* alpha test is disabled if there are no color RTs, so make sure we have at
658  * least one if alpha test is enabled. Note that this must run after
659  * nvc0_validate_fb, otherwise that will override the RT count setting.
660  */
661 static void
nvc0_validate_zsa_fb(struct nvc0_context * nvc0)662 nvc0_validate_zsa_fb(struct nvc0_context *nvc0)
663 {
664    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
665 
666    if (nvc0->zsa && nvc0->zsa->pipe.alpha.enabled &&
667        nvc0->framebuffer.zsbuf &&
668        nvc0->framebuffer.nr_cbufs == 0) {
669       nvc0_fb_set_null_rt(push, 0, 0);
670       BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1);
671       PUSH_DATA (push, (076543210 << 4) | 1);
672    }
673 }
674 
675 static void
nvc0_validate_rast_fb(struct nvc0_context * nvc0)676 nvc0_validate_rast_fb(struct nvc0_context *nvc0)
677 {
678    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
679    struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
680    struct pipe_rasterizer_state *rast = &nvc0->rast->pipe;
681 
682    if (!rast)
683       return;
684 
685    if (rast->offset_units_unscaled) {
686       BEGIN_NVC0(push, NVC0_3D(POLYGON_OFFSET_UNITS), 1);
687       if (fb->zsbuf && fb->zsbuf->format == PIPE_FORMAT_Z16_UNORM)
688          PUSH_DATAf(push, rast->offset_units * (1 << 16));
689       else
690          PUSH_DATAf(push, rast->offset_units * (1 << 24));
691    }
692 }
693 
694 
695 static void
nvc0_validate_tess_state(struct nvc0_context * nvc0)696 nvc0_validate_tess_state(struct nvc0_context *nvc0)
697 {
698    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
699 
700    BEGIN_NVC0(push, NVC0_3D(TESS_LEVEL_OUTER(0)), 6);
701    PUSH_DATAp(push, nvc0->default_tess_outer, 4);
702    PUSH_DATAp(push, nvc0->default_tess_inner, 2);
703 }
704 
705 /* If we have a frag shader bound which tries to read from the framebuffer, we
706  * have to make sure that the fb is bound as a texture in the expected
707  * location. For Fermi, that's in the special driver slot 16, while for Kepler
708  * it's a regular binding stored in the driver constbuf.
709  */
710 static void
nvc0_validate_fbread(struct nvc0_context * nvc0)711 nvc0_validate_fbread(struct nvc0_context *nvc0)
712 {
713    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
714    struct nvc0_screen *screen = nvc0->screen;
715    struct pipe_context *pipe = &nvc0->base.pipe;
716    struct pipe_sampler_view *old_view = nvc0->fbtexture;
717    struct pipe_sampler_view *new_view = NULL;
718 
719    if (nvc0->fragprog &&
720        nvc0->fragprog->fp.reads_framebuffer &&
721        nvc0->framebuffer.nr_cbufs &&
722        nvc0->framebuffer.cbufs[0]) {
723       struct pipe_sampler_view tmpl;
724       struct pipe_surface *sf = nvc0->framebuffer.cbufs[0];
725 
726       tmpl.target = PIPE_TEXTURE_2D_ARRAY;
727       tmpl.format = sf->format;
728       tmpl.u.tex.first_level = tmpl.u.tex.last_level = sf->u.tex.level;
729       tmpl.u.tex.first_layer = sf->u.tex.first_layer;
730       tmpl.u.tex.last_layer = sf->u.tex.last_layer;
731       tmpl.swizzle_r = PIPE_SWIZZLE_X;
732       tmpl.swizzle_g = PIPE_SWIZZLE_Y;
733       tmpl.swizzle_b = PIPE_SWIZZLE_Z;
734       tmpl.swizzle_a = PIPE_SWIZZLE_W;
735 
736       /* Bail if it's the same parameters */
737       if (old_view && old_view->texture == sf->texture &&
738           old_view->format == sf->format &&
739           old_view->u.tex.first_level == sf->u.tex.level &&
740           old_view->u.tex.first_layer == sf->u.tex.first_layer &&
741           old_view->u.tex.last_layer == sf->u.tex.last_layer)
742          return;
743 
744       new_view = pipe->create_sampler_view(pipe, sf->texture, &tmpl);
745    } else if (old_view == NULL) {
746       return;
747    }
748 
749    if (old_view)
750       pipe_sampler_view_reference(&nvc0->fbtexture, NULL);
751    nvc0->fbtexture = new_view;
752 
753    if (screen->default_tsc->id < 0) {
754       struct nv50_tsc_entry *tsc = nv50_tsc_entry(screen->default_tsc);
755       tsc->id = nvc0_screen_tsc_alloc(screen, tsc);
756       nvc0->base.push_data(&nvc0->base, screen->txc, 65536 + tsc->id * 32,
757                            NV_VRAM_DOMAIN(&screen->base), 32, tsc->tsc);
758       screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32);
759 
760       IMMED_NVC0(push, NVC0_3D(TSC_FLUSH), 0);
761       if (screen->base.class_3d < NVE4_3D_CLASS) {
762          BEGIN_NVC0(push, NVC0_3D(BIND_TSC2(0)), 1);
763          PUSH_DATA (push, (tsc->id << 12) | 1);
764       }
765    }
766 
767    if (new_view) {
768       struct nv50_tic_entry *tic = nv50_tic_entry(new_view);
769       assert(tic->id < 0);
770       tic->id = nvc0_screen_tic_alloc(screen, tic);
771       nvc0->base.push_data(&nvc0->base, screen->txc, tic->id * 32,
772                            NV_VRAM_DOMAIN(&screen->base), 32, tic->tic);
773       screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
774 
775       if (screen->base.class_3d >= NVE4_3D_CLASS) {
776          BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
777          PUSH_DATA (push, NVC0_CB_AUX_SIZE);
778          PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(4));
779          PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(4));
780          BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 1);
781          PUSH_DATA (push, NVC0_CB_AUX_FB_TEX_INFO);
782          PUSH_DATA (push, (screen->default_tsc->id << 20) | tic->id);
783       } else {
784          BEGIN_NVC0(push, NVC0_3D(BIND_TIC2(0)), 1);
785          PUSH_DATA (push, (tic->id << 9) | 1);
786       }
787 
788       IMMED_NVC0(push, NVC0_3D(TIC_FLUSH), 0);
789    }
790 }
791 
792 static void
nvc0_switch_pipe_context(struct nvc0_context * ctx_to)793 nvc0_switch_pipe_context(struct nvc0_context *ctx_to)
794 {
795    struct nvc0_context *ctx_from = ctx_to->screen->cur_ctx;
796    unsigned s;
797 
798    if (ctx_from)
799       ctx_to->state = ctx_from->state;
800    else
801       ctx_to->state = ctx_to->screen->save_state;
802 
803    ctx_to->dirty_3d = ~0;
804    ctx_to->dirty_cp = ~0;
805    ctx_to->viewports_dirty = ~0;
806    ctx_to->scissors_dirty = ~0;
807 
808    for (s = 0; s < 6; ++s) {
809       ctx_to->samplers_dirty[s] = ~0;
810       ctx_to->textures_dirty[s] = ~0;
811       ctx_to->constbuf_dirty[s] = (1 << NVC0_MAX_PIPE_CONSTBUFS) - 1;
812       ctx_to->buffers_dirty[s]  = ~0;
813       ctx_to->images_dirty[s]   = ~0;
814    }
815 
816    /* Reset tfb as the shader that owns it may have been deleted. */
817    ctx_to->state.tfb = NULL;
818 
819    if (!ctx_to->vertex)
820       ctx_to->dirty_3d &= ~(NVC0_NEW_3D_VERTEX | NVC0_NEW_3D_ARRAYS);
821    if (!ctx_to->idxbuf.buffer)
822       ctx_to->dirty_3d &= ~NVC0_NEW_3D_IDXBUF;
823 
824    if (!ctx_to->vertprog)
825       ctx_to->dirty_3d &= ~NVC0_NEW_3D_VERTPROG;
826    if (!ctx_to->fragprog)
827       ctx_to->dirty_3d &= ~NVC0_NEW_3D_FRAGPROG;
828 
829    if (!ctx_to->blend)
830       ctx_to->dirty_3d &= ~NVC0_NEW_3D_BLEND;
831    if (!ctx_to->rast)
832       ctx_to->dirty_3d &= ~(NVC0_NEW_3D_RASTERIZER | NVC0_NEW_3D_SCISSOR);
833    if (!ctx_to->zsa)
834       ctx_to->dirty_3d &= ~NVC0_NEW_3D_ZSA;
835 
836    ctx_to->screen->cur_ctx = ctx_to;
837 }
838 
839 static struct nvc0_state_validate
840 validate_list_3d[] = {
841     { nvc0_validate_fb,            NVC0_NEW_3D_FRAMEBUFFER },
842     { nvc0_validate_blend,         NVC0_NEW_3D_BLEND },
843     { nvc0_validate_zsa,           NVC0_NEW_3D_ZSA },
844     { nvc0_validate_sample_mask,   NVC0_NEW_3D_SAMPLE_MASK },
845     { nvc0_validate_rasterizer,    NVC0_NEW_3D_RASTERIZER },
846     { nvc0_validate_blend_colour,  NVC0_NEW_3D_BLEND_COLOUR },
847     { nvc0_validate_stencil_ref,   NVC0_NEW_3D_STENCIL_REF },
848     { nvc0_validate_stipple,       NVC0_NEW_3D_STIPPLE },
849     { nvc0_validate_scissor,       NVC0_NEW_3D_SCISSOR | NVC0_NEW_3D_RASTERIZER },
850     { nvc0_validate_viewport,      NVC0_NEW_3D_VIEWPORT },
851     { nvc0_validate_window_rects,  NVC0_NEW_3D_WINDOW_RECTS },
852     { nvc0_vertprog_validate,      NVC0_NEW_3D_VERTPROG },
853     { nvc0_tctlprog_validate,      NVC0_NEW_3D_TCTLPROG },
854     { nvc0_tevlprog_validate,      NVC0_NEW_3D_TEVLPROG },
855     { nvc0_validate_tess_state,    NVC0_NEW_3D_TESSFACTOR },
856     { nvc0_gmtyprog_validate,      NVC0_NEW_3D_GMTYPROG },
857     { nvc0_validate_min_samples,   NVC0_NEW_3D_MIN_SAMPLES |
858                                    NVC0_NEW_3D_FRAGPROG |
859                                    NVC0_NEW_3D_FRAMEBUFFER },
860     { nvc0_fragprog_validate,      NVC0_NEW_3D_FRAGPROG | NVC0_NEW_3D_RASTERIZER },
861     { nvc0_validate_fp_zsa_rast,   NVC0_NEW_3D_FRAGPROG | NVC0_NEW_3D_ZSA |
862                                    NVC0_NEW_3D_RASTERIZER },
863     { nvc0_validate_zsa_fb,        NVC0_NEW_3D_ZSA | NVC0_NEW_3D_FRAMEBUFFER },
864     { nvc0_validate_rast_fb,       NVC0_NEW_3D_RASTERIZER | NVC0_NEW_3D_FRAMEBUFFER },
865     { nvc0_validate_clip,          NVC0_NEW_3D_CLIP | NVC0_NEW_3D_RASTERIZER |
866                                    NVC0_NEW_3D_VERTPROG |
867                                    NVC0_NEW_3D_TEVLPROG |
868                                    NVC0_NEW_3D_GMTYPROG },
869     { nvc0_constbufs_validate,     NVC0_NEW_3D_CONSTBUF },
870     { nvc0_validate_textures,      NVC0_NEW_3D_TEXTURES },
871     { nvc0_validate_samplers,      NVC0_NEW_3D_SAMPLERS },
872     { nve4_set_tex_handles,        NVC0_NEW_3D_TEXTURES | NVC0_NEW_3D_SAMPLERS },
873     { nvc0_validate_fbread,        NVC0_NEW_3D_FRAGPROG |
874                                    NVC0_NEW_3D_FRAMEBUFFER },
875     { nvc0_vertex_arrays_validate, NVC0_NEW_3D_VERTEX | NVC0_NEW_3D_ARRAYS },
876     { nvc0_validate_surfaces,      NVC0_NEW_3D_SURFACES },
877     { nvc0_validate_buffers,       NVC0_NEW_3D_BUFFERS },
878     { nvc0_idxbuf_validate,        NVC0_NEW_3D_IDXBUF },
879     { nvc0_tfb_validate,           NVC0_NEW_3D_TFB_TARGETS | NVC0_NEW_3D_GMTYPROG },
880     { nvc0_validate_driverconst,   NVC0_NEW_3D_DRIVERCONST },
881 };
882 
883 bool
nvc0_state_validate(struct nvc0_context * nvc0,uint32_t mask,struct nvc0_state_validate * validate_list,int size,uint32_t * dirty,struct nouveau_bufctx * bufctx)884 nvc0_state_validate(struct nvc0_context *nvc0, uint32_t mask,
885                     struct nvc0_state_validate *validate_list, int size,
886                     uint32_t *dirty, struct nouveau_bufctx *bufctx)
887 {
888    uint32_t state_mask;
889    int ret;
890    unsigned i;
891 
892    if (nvc0->screen->cur_ctx != nvc0)
893       nvc0_switch_pipe_context(nvc0);
894 
895    state_mask = *dirty & mask;
896 
897    if (state_mask) {
898       for (i = 0; i < size; ++i) {
899          struct nvc0_state_validate *validate = &validate_list[i];
900 
901          if (state_mask & validate->states)
902             validate->func(nvc0);
903       }
904       *dirty &= ~state_mask;
905 
906       nvc0_bufctx_fence(nvc0, bufctx, false);
907    }
908 
909    nouveau_pushbuf_bufctx(nvc0->base.pushbuf, bufctx);
910    ret = nouveau_pushbuf_validate(nvc0->base.pushbuf);
911 
912    return !ret;
913 }
914 
915 bool
nvc0_state_validate_3d(struct nvc0_context * nvc0,uint32_t mask)916 nvc0_state_validate_3d(struct nvc0_context *nvc0, uint32_t mask)
917 {
918    bool ret;
919 
920    ret = nvc0_state_validate(nvc0, mask, validate_list_3d,
921                              ARRAY_SIZE(validate_list_3d), &nvc0->dirty_3d,
922                              nvc0->bufctx_3d);
923 
924    if (unlikely(nvc0->state.flushed)) {
925       nvc0->state.flushed = false;
926       nvc0_bufctx_fence(nvc0, nvc0->bufctx_3d, true);
927    }
928    return ret;
929 }
930