Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1.  
  2. #include "util/u_math.h"
  3.  
  4. #include "nvc0/nvc0_context.h"
  5. #include "nv50/nv50_defs.xml.h"
  6.  
  7. #if 0
  8. static void
  9. nvc0_validate_zcull(struct nvc0_context *nvc0)
  10. {
  11.     struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  12.     struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
  13.     struct nv50_surface *sf = nv50_surface(fb->zsbuf);
  14.     struct nv50_miptree *mt = nv50_miptree(sf->base.texture);
  15.     struct nouveau_bo *bo = mt->base.bo;
  16.     uint32_t size;
  17.     uint32_t offset = align(mt->total_size, 1 << 17);
  18.     unsigned width, height;
  19.  
  20.     assert(mt->base.base.depth0 == 1 && mt->base.base.array_size < 2);
  21.  
  22.     size = mt->total_size * 2;
  23.  
  24.     height = align(fb->height, 32);
  25.     width = fb->width % 224;
  26.     if (width)
  27.        width = fb->width + (224 - width);
  28.     else
  29.        width = fb->width;
  30.  
  31.     BEGIN_NVC0(push, NVC0_3D(ZCULL_REGION), 1);
  32.     PUSH_DATA (push, 0);
  33.     BEGIN_NVC0(push, NVC0_3D(ZCULL_ADDRESS_HIGH), 2);
  34.     PUSH_DATAh(push, bo->offset + offset);
  35.     PUSH_DATA (push, bo->offset + offset);
  36.     offset += 1 << 17;
  37.     BEGIN_NVC0(push, NVC0_3D(ZCULL_LIMIT_HIGH), 2);
  38.     PUSH_DATAh(push, bo->offset + offset);
  39.     PUSH_DATA (push, bo->offset + offset);
  40.     BEGIN_NVC0(push, SUBC_3D(0x07e0), 2);
  41.     PUSH_DATA (push, size);
  42.     PUSH_DATA (push, size >> 16);
  43.     BEGIN_NVC0(push, SUBC_3D(0x15c8), 1); /* bits 0x3 */
  44.     PUSH_DATA (push, 2);
  45.     BEGIN_NVC0(push, NVC0_3D(ZCULL_WIDTH), 4);
  46.     PUSH_DATA (push, width);
  47.     PUSH_DATA (push, height);
  48.     PUSH_DATA (push, 1);
  49.     PUSH_DATA (push, 0);
  50.     BEGIN_NVC0(push, NVC0_3D(ZCULL_WINDOW_OFFSET_X), 2);
  51.     PUSH_DATA (push, 0);
  52.     PUSH_DATA (push, 0);
  53.     BEGIN_NVC0(push, NVC0_3D(ZCULL_INVALIDATE), 1);
  54.     PUSH_DATA (push, 0);
  55. }
  56. #endif
  57.  
  58. static INLINE void
  59. nvc0_fb_set_null_rt(struct nouveau_pushbuf *push, unsigned i)
  60. {
  61.    BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(i)), 6);
  62.    PUSH_DATA (push, 0);
  63.    PUSH_DATA (push, 0);
  64.    PUSH_DATA (push, 64);
  65.    PUSH_DATA (push, 0);
  66.    PUSH_DATA (push, 0);
  67.    PUSH_DATA (push, 0);
  68. }
  69.  
  70. static void
  71. nvc0_validate_fb(struct nvc0_context *nvc0)
  72. {
  73.     struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  74.     struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
  75.     unsigned i, ms;
  76.     unsigned ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1;
  77.     boolean serialize = FALSE;
  78.  
  79.     nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_FB);
  80.  
  81.     BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1);
  82.     PUSH_DATA (push, (076543210 << 4) | fb->nr_cbufs);
  83.     BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
  84.     PUSH_DATA (push, fb->width << 16);
  85.     PUSH_DATA (push, fb->height << 16);
  86.  
  87.     for (i = 0; i < fb->nr_cbufs; ++i) {
  88.         struct nv50_surface *sf;
  89.         struct nv04_resource *res;
  90.         struct nouveau_bo *bo;
  91.  
  92.         if (!fb->cbufs[i]) {
  93.            nvc0_fb_set_null_rt(push, i);
  94.            continue;
  95.         }
  96.  
  97.         sf = nv50_surface(fb->cbufs[i]);
  98.         res = nv04_resource(sf->base.texture);
  99.         bo = res->bo;
  100.  
  101.         BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(i)), 9);
  102.         PUSH_DATAh(push, res->address + sf->offset);
  103.         PUSH_DATA (push, res->address + sf->offset);
  104.         if (likely(nouveau_bo_memtype(bo))) {
  105.            struct nv50_miptree *mt = nv50_miptree(sf->base.texture);
  106.  
  107.            assert(sf->base.texture->target != PIPE_BUFFER);
  108.  
  109.            PUSH_DATA(push, sf->width);
  110.            PUSH_DATA(push, sf->height);
  111.            PUSH_DATA(push, nvc0_format_table[sf->base.format].rt);
  112.            PUSH_DATA(push, (mt->layout_3d << 16) |
  113.                     mt->level[sf->base.u.tex.level].tile_mode);
  114.            PUSH_DATA(push, sf->base.u.tex.first_layer + sf->depth);
  115.            PUSH_DATA(push, mt->layer_stride >> 2);
  116.            PUSH_DATA(push, sf->base.u.tex.first_layer);
  117.  
  118.            ms_mode = mt->ms_mode;
  119.         } else {
  120.            if (res->base.target == PIPE_BUFFER) {
  121.               PUSH_DATA(push, 262144);
  122.               PUSH_DATA(push, 1);
  123.            } else {
  124.               PUSH_DATA(push, nv50_miptree(sf->base.texture)->level[0].pitch);
  125.               PUSH_DATA(push, sf->height);
  126.            }
  127.            PUSH_DATA(push, nvc0_format_table[sf->base.format].rt);
  128.            PUSH_DATA(push, 1 << 12);
  129.            PUSH_DATA(push, 1);
  130.            PUSH_DATA(push, 0);
  131.            PUSH_DATA(push, 0);
  132.  
  133.            nvc0_resource_fence(res, NOUVEAU_BO_WR);
  134.  
  135.            assert(!fb->zsbuf);
  136.         }
  137.  
  138.         if (res->status & NOUVEAU_BUFFER_STATUS_GPU_READING)
  139.            serialize = TRUE;
  140.         res->status |=  NOUVEAU_BUFFER_STATUS_GPU_WRITING;
  141.         res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
  142.  
  143.         /* only register for writing, otherwise we'd always serialize here */
  144.         BCTX_REFN(nvc0->bufctx_3d, FB, res, WR);
  145.     }
  146.  
  147.     if (fb->zsbuf) {
  148.         struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
  149.         struct nv50_surface *sf = nv50_surface(fb->zsbuf);
  150.         int unk = mt->base.base.target == PIPE_TEXTURE_2D;
  151.  
  152.         BEGIN_NVC0(push, NVC0_3D(ZETA_ADDRESS_HIGH), 5);
  153.         PUSH_DATAh(push, mt->base.address + sf->offset);
  154.         PUSH_DATA (push, mt->base.address + sf->offset);
  155.         PUSH_DATA (push, nvc0_format_table[fb->zsbuf->format].rt);
  156.         PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
  157.         PUSH_DATA (push, mt->layer_stride >> 2);
  158.         BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1);
  159.         PUSH_DATA (push, 1);
  160.         BEGIN_NVC0(push, NVC0_3D(ZETA_HORIZ), 3);
  161.         PUSH_DATA (push, sf->width);
  162.         PUSH_DATA (push, sf->height);
  163.         PUSH_DATA (push, (unk << 16) |
  164.                    (sf->base.u.tex.first_layer + sf->depth));
  165.         BEGIN_NVC0(push, NVC0_3D(ZETA_BASE_LAYER), 1);
  166.         PUSH_DATA (push, sf->base.u.tex.first_layer);
  167.  
  168.         ms_mode = mt->ms_mode;
  169.  
  170.         if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
  171.            serialize = TRUE;
  172.         mt->base.status |=  NOUVEAU_BUFFER_STATUS_GPU_WRITING;
  173.         mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
  174.  
  175.         BCTX_REFN(nvc0->bufctx_3d, FB, &mt->base, WR);
  176.     } else {
  177.         BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1);
  178.         PUSH_DATA (push, 0);
  179.     }
  180.  
  181.     IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), ms_mode);
  182.  
  183.     ms = 1 << ms_mode;
  184.     BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
  185.     PUSH_DATA (push, 512);
  186.     PUSH_DATAh(push, nvc0->screen->uniform_bo->offset + (5 << 16) + (4 << 9));
  187.     PUSH_DATA (push, nvc0->screen->uniform_bo->offset + (5 << 16) + (4 << 9));
  188.     BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 2 * ms);
  189.     PUSH_DATA (push, 256 + 128);
  190.     for (i = 0; i < ms; i++) {
  191.        float xy[2];
  192.        nvc0->base.pipe.get_sample_position(&nvc0->base.pipe, ms, i, xy);
  193.        PUSH_DATAf(push, xy[0]);
  194.        PUSH_DATAf(push, xy[1]);
  195.     }
  196.  
  197.     if (serialize)
  198.        IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0);
  199.  
  200.     NOUVEAU_DRV_STAT(&nvc0->screen->base, gpu_serialize_count, serialize);
  201. }
  202.  
  203. static void
  204. nvc0_validate_blend_colour(struct nvc0_context *nvc0)
  205. {
  206.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  207.  
  208.    BEGIN_NVC0(push, NVC0_3D(BLEND_COLOR(0)), 4);
  209.    PUSH_DATAf(push, nvc0->blend_colour.color[0]);
  210.    PUSH_DATAf(push, nvc0->blend_colour.color[1]);
  211.    PUSH_DATAf(push, nvc0->blend_colour.color[2]);
  212.    PUSH_DATAf(push, nvc0->blend_colour.color[3]);
  213. }
  214.  
  215. static void
  216. nvc0_validate_stencil_ref(struct nvc0_context *nvc0)
  217. {
  218.     struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  219.     const ubyte *ref = &nvc0->stencil_ref.ref_value[0];
  220.  
  221.     IMMED_NVC0(push, NVC0_3D(STENCIL_FRONT_FUNC_REF), ref[0]);
  222.     IMMED_NVC0(push, NVC0_3D(STENCIL_BACK_FUNC_REF), ref[1]);
  223. }
  224.  
  225. static void
  226. nvc0_validate_stipple(struct nvc0_context *nvc0)
  227. {
  228.     struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  229.     unsigned i;
  230.  
  231.     BEGIN_NVC0(push, NVC0_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
  232.     for (i = 0; i < 32; ++i)
  233.         PUSH_DATA(push, util_bswap32(nvc0->stipple.stipple[i]));
  234. }
  235.  
  236. static void
  237. nvc0_validate_scissor(struct nvc0_context *nvc0)
  238. {
  239.    int i;
  240.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  241.  
  242.    if (!(nvc0->dirty & NVC0_NEW_SCISSOR) &&
  243.       nvc0->rast->pipe.scissor == nvc0->state.scissor)
  244.       return;
  245.  
  246.    if (nvc0->state.scissor != nvc0->rast->pipe.scissor)
  247.       nvc0->scissors_dirty = (1 << NVC0_MAX_VIEWPORTS) - 1;
  248.  
  249.    nvc0->state.scissor = nvc0->rast->pipe.scissor;
  250.  
  251.    for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) {
  252.       struct pipe_scissor_state *s = &nvc0->scissors[i];
  253.       if (!(nvc0->scissors_dirty & (1 << i)))
  254.          continue;
  255.  
  256.       BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(i)), 2);
  257.       if (nvc0->rast->pipe.scissor) {
  258.          PUSH_DATA(push, (s->maxx << 16) | s->minx);
  259.          PUSH_DATA(push, (s->maxy << 16) | s->miny);
  260.       } else {
  261.          PUSH_DATA(push, (0xffff << 16) | 0);
  262.          PUSH_DATA(push, (0xffff << 16) | 0);
  263.       }
  264.    }
  265.    nvc0->scissors_dirty = 0;
  266. }
  267.  
  268. static void
  269. nvc0_validate_viewport(struct nvc0_context *nvc0)
  270. {
  271.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  272.    int x, y, w, h, i;
  273.    float zmin, zmax;
  274.  
  275.    for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) {
  276.       struct pipe_viewport_state *vp = &nvc0->viewports[i];
  277.  
  278.       if (!(nvc0->viewports_dirty & (1 << i)))
  279.          continue;
  280.  
  281.       BEGIN_NVC0(push, NVC0_3D(VIEWPORT_TRANSLATE_X(i)), 3);
  282.       PUSH_DATAf(push, vp->translate[0]);
  283.       PUSH_DATAf(push, vp->translate[1]);
  284.       PUSH_DATAf(push, vp->translate[2]);
  285.  
  286.       BEGIN_NVC0(push, NVC0_3D(VIEWPORT_SCALE_X(i)), 3);
  287.       PUSH_DATAf(push, vp->scale[0]);
  288.       PUSH_DATAf(push, vp->scale[1]);
  289.       PUSH_DATAf(push, vp->scale[2]);
  290.  
  291.       /* now set the viewport rectangle to viewport dimensions for clipping */
  292.  
  293.       x = util_iround(MAX2(0.0f, vp->translate[0] - fabsf(vp->scale[0])));
  294.       y = util_iround(MAX2(0.0f, vp->translate[1] - fabsf(vp->scale[1])));
  295.       w = util_iround(vp->translate[0] + fabsf(vp->scale[0])) - x;
  296.       h = util_iround(vp->translate[1] + fabsf(vp->scale[1])) - y;
  297.  
  298.       BEGIN_NVC0(push, NVC0_3D(VIEWPORT_HORIZ(i)), 2);
  299.       PUSH_DATA (push, (w << 16) | x);
  300.       PUSH_DATA (push, (h << 16) | y);
  301.  
  302.       zmin = vp->translate[2] - fabsf(vp->scale[2]);
  303.       zmax = vp->translate[2] + fabsf(vp->scale[2]);
  304.  
  305.       BEGIN_NVC0(push, NVC0_3D(DEPTH_RANGE_NEAR(i)), 2);
  306.       PUSH_DATAf(push, zmin);
  307.       PUSH_DATAf(push, zmax);
  308.    }
  309.    nvc0->viewports_dirty = 0;
  310. }
  311.  
  312. static INLINE void
  313. nvc0_upload_uclip_planes(struct nvc0_context *nvc0, unsigned s)
  314. {
  315.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  316.    struct nouveau_bo *bo = nvc0->screen->uniform_bo;
  317.  
  318.    BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
  319.    PUSH_DATA (push, 512);
  320.    PUSH_DATAh(push, bo->offset + (5 << 16) + (s << 9));
  321.    PUSH_DATA (push, bo->offset + (5 << 16) + (s << 9));
  322.    BEGIN_1IC0(push, NVC0_3D(CB_POS), PIPE_MAX_CLIP_PLANES * 4 + 1);
  323.    PUSH_DATA (push, 256);
  324.    PUSH_DATAp(push, &nvc0->clip.ucp[0][0], PIPE_MAX_CLIP_PLANES * 4);
  325. }
  326.  
  327. static INLINE void
  328. nvc0_check_program_ucps(struct nvc0_context *nvc0,
  329.                         struct nvc0_program *vp, uint8_t mask)
  330. {
  331.    const unsigned n = util_logbase2(mask) + 1;
  332.  
  333.    if (vp->vp.num_ucps >= n)
  334.       return;
  335.    nvc0_program_destroy(nvc0, vp);
  336.  
  337.    vp->vp.num_ucps = n;
  338.    if (likely(vp == nvc0->vertprog))
  339.       nvc0_vertprog_validate(nvc0);
  340.    else
  341.    if (likely(vp == nvc0->gmtyprog))
  342.       nvc0_vertprog_validate(nvc0);
  343.    else
  344.       nvc0_tevlprog_validate(nvc0);
  345. }
  346.  
  347. static void
  348. nvc0_validate_clip(struct nvc0_context *nvc0)
  349. {
  350.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  351.    struct nvc0_program *vp;
  352.    unsigned stage;
  353.    uint8_t clip_enable = nvc0->rast->pipe.clip_plane_enable;
  354.  
  355.    if (nvc0->gmtyprog) {
  356.       stage = 3;
  357.       vp = nvc0->gmtyprog;
  358.    } else
  359.    if (nvc0->tevlprog) {
  360.       stage = 2;
  361.       vp = nvc0->tevlprog;
  362.    } else {
  363.       stage = 0;
  364.       vp = nvc0->vertprog;
  365.    }
  366.  
  367.    if (clip_enable && vp->vp.num_ucps < PIPE_MAX_CLIP_PLANES)
  368.       nvc0_check_program_ucps(nvc0, vp, clip_enable);
  369.  
  370.    if (nvc0->dirty & (NVC0_NEW_CLIP | (NVC0_NEW_VERTPROG << stage)))
  371.       if (vp->vp.num_ucps > 0 && vp->vp.num_ucps <= PIPE_MAX_CLIP_PLANES)
  372.          nvc0_upload_uclip_planes(nvc0, stage);
  373.  
  374.    clip_enable &= vp->vp.clip_enable;
  375.  
  376.    if (nvc0->state.clip_enable != clip_enable) {
  377.       nvc0->state.clip_enable = clip_enable;
  378.       IMMED_NVC0(push, NVC0_3D(CLIP_DISTANCE_ENABLE), clip_enable);
  379.    }
  380.    if (nvc0->state.clip_mode != vp->vp.clip_mode) {
  381.       nvc0->state.clip_mode = vp->vp.clip_mode;
  382.       BEGIN_NVC0(push, NVC0_3D(CLIP_DISTANCE_MODE), 1);
  383.       PUSH_DATA (push, vp->vp.clip_mode);
  384.    }
  385. }
  386.  
  387. static void
  388. nvc0_validate_blend(struct nvc0_context *nvc0)
  389. {
  390.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  391.  
  392.    PUSH_SPACE(push, nvc0->blend->size);
  393.    PUSH_DATAp(push, nvc0->blend->state, nvc0->blend->size);
  394. }
  395.  
  396. static void
  397. nvc0_validate_zsa(struct nvc0_context *nvc0)
  398. {
  399.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  400.  
  401.    PUSH_SPACE(push, nvc0->zsa->size);
  402.    PUSH_DATAp(push, nvc0->zsa->state, nvc0->zsa->size);
  403. }
  404.  
  405. static void
  406. nvc0_validate_rasterizer(struct nvc0_context *nvc0)
  407. {
  408.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  409.  
  410.    PUSH_SPACE(push, nvc0->rast->size);
  411.    PUSH_DATAp(push, nvc0->rast->state, nvc0->rast->size);
  412. }
  413.  
  414. static void
  415. nvc0_constbufs_validate(struct nvc0_context *nvc0)
  416. {
  417.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  418.    unsigned s;
  419.  
  420.    for (s = 0; s < 5; ++s) {
  421.       while (nvc0->constbuf_dirty[s]) {
  422.          int i = ffs(nvc0->constbuf_dirty[s]) - 1;
  423.          nvc0->constbuf_dirty[s] &= ~(1 << i);
  424.  
  425.          if (nvc0->constbuf[s][i].user) {
  426.             struct nouveau_bo *bo = nvc0->screen->uniform_bo;
  427.             const unsigned base = s << 16;
  428.             const unsigned size = nvc0->constbuf[s][0].size;
  429.             assert(i == 0); /* we really only want OpenGL uniforms here */
  430.             assert(nvc0->constbuf[s][0].u.data);
  431.  
  432.             if (nvc0->state.uniform_buffer_bound[s] < size) {
  433.                nvc0->state.uniform_buffer_bound[s] = align(size, 0x100);
  434.  
  435.                BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
  436.                PUSH_DATA (push, nvc0->state.uniform_buffer_bound[s]);
  437.                PUSH_DATAh(push, bo->offset + base);
  438.                PUSH_DATA (push, bo->offset + base);
  439.                BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
  440.                PUSH_DATA (push, (0 << 4) | 1);
  441.             }
  442.             nvc0_cb_push(&nvc0->base, bo, NOUVEAU_BO_VRAM,
  443.                          base, nvc0->state.uniform_buffer_bound[s],
  444.                          0, (size + 3) / 4,
  445.                          nvc0->constbuf[s][0].u.data);
  446.          } else {
  447.             struct nv04_resource *res =
  448.                nv04_resource(nvc0->constbuf[s][i].u.buf);
  449.             if (res) {
  450.                BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
  451.                PUSH_DATA (push, nvc0->constbuf[s][i].size);
  452.                PUSH_DATAh(push, res->address + nvc0->constbuf[s][i].offset);
  453.                PUSH_DATA (push, res->address + nvc0->constbuf[s][i].offset);
  454.                BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
  455.                PUSH_DATA (push, (i << 4) | 1);
  456.  
  457.                BCTX_REFN(nvc0->bufctx_3d, CB(s, i), res, RD);
  458.             } else {
  459.                BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
  460.                PUSH_DATA (push, (i << 4) | 0);
  461.             }
  462.             if (i == 0)
  463.                nvc0->state.uniform_buffer_bound[s] = 0;
  464.          }
  465.       }
  466.    }
  467. }
  468.  
  469. static void
  470. nvc0_validate_sample_mask(struct nvc0_context *nvc0)
  471. {
  472.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  473.  
  474.    unsigned mask[4] =
  475.    {
  476.       nvc0->sample_mask & 0xffff,
  477.       nvc0->sample_mask & 0xffff,
  478.       nvc0->sample_mask & 0xffff,
  479.       nvc0->sample_mask & 0xffff
  480.    };
  481.  
  482.    BEGIN_NVC0(push, NVC0_3D(MSAA_MASK(0)), 4);
  483.    PUSH_DATA (push, mask[0]);
  484.    PUSH_DATA (push, mask[1]);
  485.    PUSH_DATA (push, mask[2]);
  486.    PUSH_DATA (push, mask[3]);
  487. }
  488.  
  489. static void
  490. nvc0_validate_min_samples(struct nvc0_context *nvc0)
  491. {
  492.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  493.    int samples;
  494.  
  495.    samples = util_next_power_of_two(nvc0->min_samples);
  496.    if (samples > 1)
  497.       samples |= NVC0_3D_SAMPLE_SHADING_ENABLE;
  498.  
  499.    IMMED_NVC0(push, NVC0_3D(SAMPLE_SHADING), samples);
  500. }
  501.  
  502. void
  503. nvc0_validate_global_residents(struct nvc0_context *nvc0,
  504.                                struct nouveau_bufctx *bctx, int bin)
  505. {
  506.    unsigned i;
  507.  
  508.    for (i = 0; i < nvc0->global_residents.size / sizeof(struct pipe_resource *);
  509.         ++i) {
  510.       struct pipe_resource *res = *util_dynarray_element(
  511.          &nvc0->global_residents, struct pipe_resource *, i);
  512.       if (res)
  513.          nvc0_add_resident(bctx, bin, nv04_resource(res), NOUVEAU_BO_RDWR);
  514.    }
  515. }
  516.  
  517. static void
  518. nvc0_validate_derived_1(struct nvc0_context *nvc0)
  519. {
  520.    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
  521.    boolean rasterizer_discard;
  522.  
  523.    if (nvc0->rast && nvc0->rast->pipe.rasterizer_discard) {
  524.       rasterizer_discard = TRUE;
  525.    } else {
  526.       boolean zs = nvc0->zsa &&
  527.          (nvc0->zsa->pipe.depth.enabled || nvc0->zsa->pipe.stencil[0].enabled);
  528.       rasterizer_discard = !zs &&
  529.          (!nvc0->fragprog || !nvc0->fragprog->hdr[18]);
  530.    }
  531.  
  532.    if (rasterizer_discard != nvc0->state.rasterizer_discard) {
  533.       nvc0->state.rasterizer_discard = rasterizer_discard;
  534.       IMMED_NVC0(push, NVC0_3D(RASTERIZE_ENABLE), !rasterizer_discard);
  535.    }
  536. }
  537.  
  538. static void
  539. nvc0_switch_pipe_context(struct nvc0_context *ctx_to)
  540. {
  541.    struct nvc0_context *ctx_from = ctx_to->screen->cur_ctx;
  542.    unsigned s;
  543.  
  544.    if (ctx_from)
  545.       ctx_to->state = ctx_from->state;
  546.    else
  547.       ctx_to->state = ctx_to->screen->save_state;
  548.  
  549.    ctx_to->dirty = ~0;
  550.    ctx_to->viewports_dirty = ~0;
  551.    ctx_to->scissors_dirty = ~0;
  552.  
  553.    for (s = 0; s < 5; ++s) {
  554.       ctx_to->samplers_dirty[s] = ~0;
  555.       ctx_to->textures_dirty[s] = ~0;
  556.       ctx_to->constbuf_dirty[s] = (1 << NVC0_MAX_PIPE_CONSTBUFS) - 1;
  557.    }
  558.  
  559.    if (!ctx_to->vertex)
  560.       ctx_to->dirty &= ~(NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS);
  561.    if (!ctx_to->idxbuf.buffer)
  562.       ctx_to->dirty &= ~NVC0_NEW_IDXBUF;
  563.  
  564.    if (!ctx_to->vertprog)
  565.       ctx_to->dirty &= ~NVC0_NEW_VERTPROG;
  566.    if (!ctx_to->fragprog)
  567.       ctx_to->dirty &= ~NVC0_NEW_FRAGPROG;
  568.  
  569.    if (!ctx_to->blend)
  570.       ctx_to->dirty &= ~NVC0_NEW_BLEND;
  571.    if (!ctx_to->rast)
  572.       ctx_to->dirty &= ~(NVC0_NEW_RASTERIZER | NVC0_NEW_SCISSOR);
  573.    if (!ctx_to->zsa)
  574.       ctx_to->dirty &= ~NVC0_NEW_ZSA;
  575.  
  576.    ctx_to->screen->cur_ctx = ctx_to;
  577. }
  578.  
  579. static struct state_validate {
  580.     void (*func)(struct nvc0_context *);
  581.     uint32_t states;
  582. } validate_list[] = {
  583.     { nvc0_validate_fb,            NVC0_NEW_FRAMEBUFFER },
  584.     { nvc0_validate_blend,         NVC0_NEW_BLEND },
  585.     { nvc0_validate_zsa,           NVC0_NEW_ZSA },
  586.     { nvc0_validate_sample_mask,   NVC0_NEW_SAMPLE_MASK },
  587.     { nvc0_validate_rasterizer,    NVC0_NEW_RASTERIZER },
  588.     { nvc0_validate_blend_colour,  NVC0_NEW_BLEND_COLOUR },
  589.     { nvc0_validate_stencil_ref,   NVC0_NEW_STENCIL_REF },
  590.     { nvc0_validate_stipple,       NVC0_NEW_STIPPLE },
  591.     { nvc0_validate_scissor,       NVC0_NEW_SCISSOR | NVC0_NEW_RASTERIZER },
  592.     { nvc0_validate_viewport,      NVC0_NEW_VIEWPORT },
  593.     { nvc0_vertprog_validate,      NVC0_NEW_VERTPROG },
  594.     { nvc0_tctlprog_validate,      NVC0_NEW_TCTLPROG },
  595.     { nvc0_tevlprog_validate,      NVC0_NEW_TEVLPROG },
  596.     { nvc0_gmtyprog_validate,      NVC0_NEW_GMTYPROG },
  597.     { nvc0_fragprog_validate,      NVC0_NEW_FRAGPROG },
  598.     { nvc0_validate_derived_1,     NVC0_NEW_FRAGPROG | NVC0_NEW_ZSA |
  599.                                    NVC0_NEW_RASTERIZER },
  600.     { nvc0_validate_clip,          NVC0_NEW_CLIP | NVC0_NEW_RASTERIZER |
  601.                                    NVC0_NEW_VERTPROG |
  602.                                    NVC0_NEW_TEVLPROG |
  603.                                    NVC0_NEW_GMTYPROG },
  604.     { nvc0_constbufs_validate,     NVC0_NEW_CONSTBUF },
  605.     { nvc0_validate_textures,      NVC0_NEW_TEXTURES },
  606.     { nvc0_validate_samplers,      NVC0_NEW_SAMPLERS },
  607.     { nve4_set_tex_handles,        NVC0_NEW_TEXTURES | NVC0_NEW_SAMPLERS },
  608.     { nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS },
  609.     { nvc0_validate_surfaces,      NVC0_NEW_SURFACES },
  610.     { nvc0_idxbuf_validate,        NVC0_NEW_IDXBUF },
  611.     { nvc0_tfb_validate,           NVC0_NEW_TFB_TARGETS | NVC0_NEW_GMTYPROG },
  612.     { nvc0_validate_min_samples,   NVC0_NEW_MIN_SAMPLES },
  613. };
  614. #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
  615.  
  616. boolean
  617. nvc0_state_validate(struct nvc0_context *nvc0, uint32_t mask, unsigned words)
  618. {
  619.    uint32_t state_mask;
  620.    int ret;
  621.    unsigned i;
  622.  
  623.    if (nvc0->screen->cur_ctx != nvc0)
  624.       nvc0_switch_pipe_context(nvc0);
  625.  
  626.    state_mask = nvc0->dirty & mask;
  627.  
  628.    if (state_mask) {
  629.       for (i = 0; i < validate_list_len; ++i) {
  630.          struct state_validate *validate = &validate_list[i];
  631.  
  632.          if (state_mask & validate->states)
  633.             validate->func(nvc0);
  634.       }
  635.       nvc0->dirty &= ~state_mask;
  636.  
  637.       nvc0_bufctx_fence(nvc0, nvc0->bufctx_3d, FALSE);
  638.    }
  639.  
  640.    nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx_3d);
  641.    ret = nouveau_pushbuf_validate(nvc0->base.pushbuf);
  642.  
  643.    if (unlikely(nvc0->state.flushed)) {
  644.       nvc0->state.flushed = FALSE;
  645.       nvc0_bufctx_fence(nvc0, nvc0->bufctx_3d, TRUE);
  646.    }
  647.    return !ret;
  648. }
  649.