Home | History | Annotate | Download | only in nvc0
      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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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