Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1.  
  2. #include "nv50/nv50_context.h"
  3. #include "nv50/nv50_defs.xml.h"
  4.  
  5. static INLINE void
  6. nv50_fb_set_null_rt(struct nouveau_pushbuf *push, unsigned i)
  7. {
  8.    BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(i)), 4);
  9.    PUSH_DATA (push, 0);
  10.    PUSH_DATA (push, 0);
  11.    PUSH_DATA (push, 0);
  12.    PUSH_DATA (push, 0);
  13.    BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);
  14.    PUSH_DATA (push, 64);
  15.    PUSH_DATA (push, 0);
  16. }
  17.  
  18. static void
  19. nv50_validate_fb(struct nv50_context *nv50)
  20. {
  21.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  22.    struct pipe_framebuffer_state *fb = &nv50->framebuffer;
  23.    unsigned i;
  24.    unsigned ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1;
  25.    uint32_t array_size = 0xffff, array_mode = 0;
  26.  
  27.    nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
  28.  
  29.    BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);
  30.    PUSH_DATA (push, (076543210 << 4) | fb->nr_cbufs);
  31.    BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);
  32.    PUSH_DATA (push, fb->width << 16);
  33.    PUSH_DATA (push, fb->height << 16);
  34.  
  35.    for (i = 0; i < fb->nr_cbufs; ++i) {
  36.       struct nv50_miptree *mt;
  37.       struct nv50_surface *sf;
  38.       struct nouveau_bo *bo;
  39.  
  40.       if (!fb->cbufs[i]) {
  41.          nv50_fb_set_null_rt(push, i);
  42.          continue;
  43.       }
  44.  
  45.       mt = nv50_miptree(fb->cbufs[i]->texture);
  46.       sf = nv50_surface(fb->cbufs[i]);
  47.       bo = mt->base.bo;
  48.  
  49.       array_size = MIN2(array_size, sf->depth);
  50.       if (mt->layout_3d)
  51.          array_mode = NV50_3D_RT_ARRAY_MODE_MODE_3D; /* 1 << 16 */
  52.  
  53.       /* can't mix 3D with ARRAY or have RTs of different depth/array_size */
  54.       assert(mt->layout_3d || !array_mode || array_size == 1);
  55.  
  56.       BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(i)), 5);
  57.       PUSH_DATAh(push, mt->base.address + sf->offset);
  58.       PUSH_DATA (push, mt->base.address + sf->offset);
  59.       PUSH_DATA (push, nv50_format_table[sf->base.format].rt);
  60.       if (likely(nouveau_bo_memtype(bo))) {
  61.          PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
  62.          PUSH_DATA (push, mt->layer_stride >> 2);
  63.          BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);
  64.          PUSH_DATA (push, sf->width);
  65.          PUSH_DATA (push, sf->height);
  66.          BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);
  67.          PUSH_DATA (push, array_mode | array_size);
  68.          nv50->rt_array_mode = array_mode | array_size;
  69.       } else {
  70.          PUSH_DATA (push, 0);
  71.          PUSH_DATA (push, 0);
  72.          BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);
  73.          PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | mt->level[0].pitch);
  74.          PUSH_DATA (push, sf->height);
  75.          BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);
  76.          PUSH_DATA (push, 0);
  77.  
  78.          assert(!fb->zsbuf);
  79.          assert(!mt->ms_mode);
  80.       }
  81.  
  82.       ms_mode = mt->ms_mode;
  83.  
  84.       if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
  85.          nv50->state.rt_serialize = TRUE;
  86.       mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
  87.       mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
  88.  
  89.       /* only register for writing, otherwise we'd always serialize here */
  90.       BCTX_REFN(nv50->bufctx_3d, FB, &mt->base, WR);
  91.    }
  92.  
  93.    if (fb->zsbuf) {
  94.       struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
  95.       struct nv50_surface *sf = nv50_surface(fb->zsbuf);
  96.       int unk = mt->base.base.target == PIPE_TEXTURE_3D || sf->depth == 1;
  97.  
  98.       BEGIN_NV04(push, NV50_3D(ZETA_ADDRESS_HIGH), 5);
  99.       PUSH_DATAh(push, mt->base.address + sf->offset);
  100.       PUSH_DATA (push, mt->base.address + sf->offset);
  101.       PUSH_DATA (push, nv50_format_table[fb->zsbuf->format].rt);
  102.       PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
  103.       PUSH_DATA (push, mt->layer_stride >> 2);
  104.       BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
  105.       PUSH_DATA (push, 1);
  106.       BEGIN_NV04(push, NV50_3D(ZETA_HORIZ), 3);
  107.       PUSH_DATA (push, sf->width);
  108.       PUSH_DATA (push, sf->height);
  109.       PUSH_DATA (push, (unk << 16) | sf->depth);
  110.  
  111.       ms_mode = mt->ms_mode;
  112.  
  113.       if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
  114.          nv50->state.rt_serialize = TRUE;
  115.       mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
  116.       mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING;
  117.  
  118.       BCTX_REFN(nv50->bufctx_3d, FB, &mt->base, WR);
  119.    } else {
  120.       BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
  121.       PUSH_DATA (push, 0);
  122.    }
  123.  
  124.    BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);
  125.    PUSH_DATA (push, ms_mode);
  126.  
  127.    /* Only need to initialize the first viewport, which is used for clears */
  128.    BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
  129.    PUSH_DATA (push, fb->width << 16);
  130.    PUSH_DATA (push, fb->height << 16);
  131.  
  132.    if (nv50->screen->tesla->oclass >= NVA3_3D_CLASS) {
  133.       unsigned ms = 1 << ms_mode;
  134.       BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
  135.       PUSH_DATA (push, (NV50_CB_AUX_SAMPLE_OFFSET << (8 - 2)) | NV50_CB_AUX);
  136.       BEGIN_NI04(push, NV50_3D(CB_DATA(0)), 2 * ms);
  137.       for (i = 0; i < ms; i++) {
  138.          float xy[2];
  139.          nv50->base.pipe.get_sample_position(&nv50->base.pipe, ms, i, xy);
  140.          PUSH_DATAf(push, xy[0]);
  141.          PUSH_DATAf(push, xy[1]);
  142.       }
  143.    }
  144. }
  145.  
  146. static void
  147. nv50_validate_blend_colour(struct nv50_context *nv50)
  148. {
  149.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  150.  
  151.    BEGIN_NV04(push, NV50_3D(BLEND_COLOR(0)), 4);
  152.    PUSH_DATAf(push, nv50->blend_colour.color[0]);
  153.    PUSH_DATAf(push, nv50->blend_colour.color[1]);
  154.    PUSH_DATAf(push, nv50->blend_colour.color[2]);
  155.    PUSH_DATAf(push, nv50->blend_colour.color[3]);
  156. }
  157.  
  158. static void
  159. nv50_validate_stencil_ref(struct nv50_context *nv50)
  160. {
  161.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  162.  
  163.    BEGIN_NV04(push, NV50_3D(STENCIL_FRONT_FUNC_REF), 1);
  164.    PUSH_DATA (push, nv50->stencil_ref.ref_value[0]);
  165.    BEGIN_NV04(push, NV50_3D(STENCIL_BACK_FUNC_REF), 1);
  166.    PUSH_DATA (push, nv50->stencil_ref.ref_value[1]);
  167. }
  168.  
  169. static void
  170. nv50_validate_stipple(struct nv50_context *nv50)
  171. {
  172.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  173.    unsigned i;
  174.  
  175.    BEGIN_NV04(push, NV50_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
  176.    for (i = 0; i < 32; ++i)
  177.       PUSH_DATA(push, util_bswap32(nv50->stipple.stipple[i]));
  178. }
  179.  
  180. static void
  181. nv50_validate_scissor(struct nv50_context *nv50)
  182. {
  183.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  184. #ifdef NV50_SCISSORS_CLIPPING
  185.    int minx, maxx, miny, maxy, i;
  186.  
  187.    if (!(nv50->dirty &
  188.          (NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | NV50_NEW_FRAMEBUFFER)) &&
  189.        nv50->state.scissor == nv50->rast->pipe.scissor)
  190.       return;
  191.  
  192.    if (nv50->state.scissor != nv50->rast->pipe.scissor)
  193.       nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;
  194.  
  195.    nv50->state.scissor = nv50->rast->pipe.scissor;
  196.  
  197.    if ((nv50->dirty & NV50_NEW_FRAMEBUFFER) && !nv50->state.scissor)
  198.       nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;
  199.  
  200.    for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
  201.       struct pipe_scissor_state *s = &nv50->scissors[i];
  202.       struct pipe_viewport_state *vp = &nv50->viewports[i];
  203.  
  204.       if (!(nv50->scissors_dirty & (1 << i)) &&
  205.           !(nv50->viewports_dirty & (1 << i)))
  206.          continue;
  207.  
  208.       if (nv50->state.scissor) {
  209.          minx = s->minx;
  210.          maxx = s->maxx;
  211.          miny = s->miny;
  212.          maxy = s->maxy;
  213.       } else {
  214.          minx = 0;
  215.          maxx = nv50->framebuffer.width;
  216.          miny = 0;
  217.          maxy = nv50->framebuffer.height;
  218.       }
  219.  
  220.       minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
  221.       maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
  222.       miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
  223.       maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
  224.  
  225.       minx = MIN2(minx, 8192);
  226.       maxx = MAX2(maxx, 0);
  227.       miny = MIN2(miny, 8192);
  228.       maxy = MAX2(maxy, 0);
  229.  
  230.       BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(i)), 2);
  231.       PUSH_DATA (push, (maxx << 16) | minx);
  232.       PUSH_DATA (push, (maxy << 16) | miny);
  233. #else
  234.       BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(i)), 2);
  235.       PUSH_DATA (push, (s->maxx << 16) | s->minx);
  236.       PUSH_DATA (push, (s->maxy << 16) | s->miny);
  237. #endif
  238.    }
  239.  
  240.    nv50->scissors_dirty = 0;
  241. }
  242.  
  243. static void
  244. nv50_validate_viewport(struct nv50_context *nv50)
  245. {
  246.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  247.    float zmin, zmax;
  248.    int i;
  249.  
  250.    for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
  251.       struct pipe_viewport_state *vpt = &nv50->viewports[i];
  252.  
  253.       if (!(nv50->viewports_dirty & (1 << i)))
  254.          continue;
  255.  
  256.       BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSLATE_X(i)), 3);
  257.       PUSH_DATAf(push, vpt->translate[0]);
  258.       PUSH_DATAf(push, vpt->translate[1]);
  259.       PUSH_DATAf(push, vpt->translate[2]);
  260.       BEGIN_NV04(push, NV50_3D(VIEWPORT_SCALE_X(i)), 3);
  261.       PUSH_DATAf(push, vpt->scale[0]);
  262.       PUSH_DATAf(push, vpt->scale[1]);
  263.       PUSH_DATAf(push, vpt->scale[2]);
  264.  
  265.       zmin = vpt->translate[2] - fabsf(vpt->scale[2]);
  266.       zmax = vpt->translate[2] + fabsf(vpt->scale[2]);
  267.  
  268. #ifdef NV50_SCISSORS_CLIPPING
  269.       BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(i)), 2);
  270.       PUSH_DATAf(push, zmin);
  271.       PUSH_DATAf(push, zmax);
  272. #endif
  273.    }
  274.  
  275.    nv50->viewports_dirty = 0;
  276. }
  277.  
  278. static INLINE void
  279. nv50_check_program_ucps(struct nv50_context *nv50,
  280.                         struct nv50_program *vp, uint8_t mask)
  281. {
  282.    const unsigned n = util_logbase2(mask) + 1;
  283.  
  284.    if (vp->vp.clpd_nr >= n)
  285.       return;
  286.    nv50_program_destroy(nv50, vp);
  287.  
  288.    vp->vp.clpd_nr = n;
  289.    if (likely(vp == nv50->vertprog)) {
  290.       nv50->dirty |= NV50_NEW_VERTPROG;
  291.       nv50_vertprog_validate(nv50);
  292.    } else {
  293.       nv50->dirty |= NV50_NEW_GMTYPROG;
  294.       nv50_gmtyprog_validate(nv50);
  295.    }
  296.    nv50_fp_linkage_validate(nv50);
  297. }
  298.  
  299. static void
  300. nv50_validate_clip(struct nv50_context *nv50)
  301. {
  302.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  303.    struct nv50_program *vp;
  304.    uint8_t clip_enable;
  305.  
  306.    if (nv50->dirty & NV50_NEW_CLIP) {
  307.       BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
  308.       PUSH_DATA (push, (NV50_CB_AUX_UCP_OFFSET << 8) | NV50_CB_AUX);
  309.       BEGIN_NI04(push, NV50_3D(CB_DATA(0)), PIPE_MAX_CLIP_PLANES * 4);
  310.       PUSH_DATAp(push, &nv50->clip.ucp[0][0], PIPE_MAX_CLIP_PLANES * 4);
  311.    }
  312.  
  313.    vp = nv50->gmtyprog;
  314.    if (likely(!vp))
  315.       vp = nv50->vertprog;
  316.  
  317.    clip_enable = nv50->rast->pipe.clip_plane_enable;
  318.  
  319.    BEGIN_NV04(push, NV50_3D(CLIP_DISTANCE_ENABLE), 1);
  320.    PUSH_DATA (push, clip_enable);
  321.  
  322.    if (clip_enable)
  323.       nv50_check_program_ucps(nv50, vp, clip_enable);
  324. }
  325.  
  326. static void
  327. nv50_validate_blend(struct nv50_context *nv50)
  328. {
  329.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  330.  
  331.    PUSH_SPACE(push, nv50->blend->size);
  332.    PUSH_DATAp(push, nv50->blend->state, nv50->blend->size);
  333. }
  334.  
  335. static void
  336. nv50_validate_zsa(struct nv50_context *nv50)
  337. {
  338.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  339.  
  340.    PUSH_SPACE(push, nv50->zsa->size);
  341.    PUSH_DATAp(push, nv50->zsa->state, nv50->zsa->size);
  342. }
  343.  
  344. static void
  345. nv50_validate_rasterizer(struct nv50_context *nv50)
  346. {
  347.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  348.  
  349.    PUSH_SPACE(push, nv50->rast->size);
  350.    PUSH_DATAp(push, nv50->rast->state, nv50->rast->size);
  351. }
  352.  
  353. static void
  354. nv50_validate_sample_mask(struct nv50_context *nv50)
  355. {
  356.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  357.  
  358.    unsigned mask[4] =
  359.    {
  360.       nv50->sample_mask & 0xffff,
  361.       nv50->sample_mask & 0xffff,
  362.       nv50->sample_mask & 0xffff,
  363.       nv50->sample_mask & 0xffff
  364.    };
  365.  
  366.    BEGIN_NV04(push, NV50_3D(MSAA_MASK(0)), 4);
  367.    PUSH_DATA (push, mask[0]);
  368.    PUSH_DATA (push, mask[1]);
  369.    PUSH_DATA (push, mask[2]);
  370.    PUSH_DATA (push, mask[3]);
  371. }
  372.  
  373. static void
  374. nv50_validate_min_samples(struct nv50_context *nv50)
  375. {
  376.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  377.    int samples;
  378.  
  379.    if (nv50->screen->tesla->oclass < NVA3_3D_CLASS)
  380.       return;
  381.  
  382.    samples = util_next_power_of_two(nv50->min_samples);
  383.    if (samples > 1)
  384.       samples |= NVA3_3D_SAMPLE_SHADING_ENABLE;
  385.  
  386.    BEGIN_NV04(push, SUBC_3D(NVA3_3D_SAMPLE_SHADING), 1);
  387.    PUSH_DATA (push, samples);
  388. }
  389.  
  390. static void
  391. nv50_switch_pipe_context(struct nv50_context *ctx_to)
  392. {
  393.    struct nv50_context *ctx_from = ctx_to->screen->cur_ctx;
  394.  
  395.    if (ctx_from)
  396.       ctx_to->state = ctx_from->state;
  397.    else
  398.       ctx_to->state = ctx_to->screen->save_state;
  399.  
  400.    ctx_to->dirty = ~0;
  401.    ctx_to->viewports_dirty = ~0;
  402.    ctx_to->scissors_dirty = ~0;
  403.  
  404.    ctx_to->constbuf_dirty[0] =
  405.    ctx_to->constbuf_dirty[1] =
  406.    ctx_to->constbuf_dirty[2] = (1 << NV50_MAX_PIPE_CONSTBUFS) - 1;
  407.  
  408.    if (!ctx_to->vertex)
  409.       ctx_to->dirty &= ~(NV50_NEW_VERTEX | NV50_NEW_ARRAYS);
  410.  
  411.    if (!ctx_to->vertprog)
  412.       ctx_to->dirty &= ~NV50_NEW_VERTPROG;
  413.    if (!ctx_to->fragprog)
  414.       ctx_to->dirty &= ~NV50_NEW_FRAGPROG;
  415.  
  416.    if (!ctx_to->blend)
  417.       ctx_to->dirty &= ~NV50_NEW_BLEND;
  418.    if (!ctx_to->rast)
  419. #ifdef NV50_SCISSORS_CLIPPING
  420.       ctx_to->dirty &= ~(NV50_NEW_RASTERIZER | NV50_NEW_SCISSOR);
  421. #else
  422.       ctx_to->dirty &= ~NV50_NEW_RASTERIZER;
  423. #endif
  424.    if (!ctx_to->zsa)
  425.       ctx_to->dirty &= ~NV50_NEW_ZSA;
  426.  
  427.    ctx_to->screen->cur_ctx = ctx_to;
  428. }
  429.  
  430. static struct state_validate {
  431.     void (*func)(struct nv50_context *);
  432.     uint32_t states;
  433. } validate_list[] = {
  434.     { nv50_validate_fb,            NV50_NEW_FRAMEBUFFER },
  435.     { nv50_validate_blend,         NV50_NEW_BLEND },
  436.     { nv50_validate_zsa,           NV50_NEW_ZSA },
  437.     { nv50_validate_sample_mask,   NV50_NEW_SAMPLE_MASK },
  438.     { nv50_validate_rasterizer,    NV50_NEW_RASTERIZER },
  439.     { nv50_validate_blend_colour,  NV50_NEW_BLEND_COLOUR },
  440.     { nv50_validate_stencil_ref,   NV50_NEW_STENCIL_REF },
  441.     { nv50_validate_stipple,       NV50_NEW_STIPPLE },
  442. #ifdef NV50_SCISSORS_CLIPPING
  443.     { nv50_validate_scissor,       NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT |
  444.                                    NV50_NEW_RASTERIZER |
  445.                                    NV50_NEW_FRAMEBUFFER },
  446. #else
  447.     { nv50_validate_scissor,       NV50_NEW_SCISSOR },
  448. #endif
  449.     { nv50_validate_viewport,      NV50_NEW_VIEWPORT },
  450.     { nv50_vertprog_validate,      NV50_NEW_VERTPROG },
  451.     { nv50_gmtyprog_validate,      NV50_NEW_GMTYPROG },
  452.     { nv50_fragprog_validate,      NV50_NEW_FRAGPROG |
  453.                                    NV50_NEW_MIN_SAMPLES },
  454.     { nv50_fp_linkage_validate,    NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
  455.                                    NV50_NEW_GMTYPROG | NV50_NEW_RASTERIZER },
  456.     { nv50_gp_linkage_validate,    NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG },
  457.     { nv50_validate_derived_rs,    NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER |
  458.                                    NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
  459.     { nv50_validate_clip,          NV50_NEW_CLIP | NV50_NEW_RASTERIZER |
  460.                                    NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
  461.     { nv50_constbufs_validate,     NV50_NEW_CONSTBUF },
  462.     { nv50_validate_textures,      NV50_NEW_TEXTURES },
  463.     { nv50_validate_samplers,      NV50_NEW_SAMPLERS },
  464.     { nv50_stream_output_validate, NV50_NEW_STRMOUT |
  465.                                    NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
  466.     { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS },
  467.     { nv50_validate_min_samples,   NV50_NEW_MIN_SAMPLES },
  468. };
  469. #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
  470.  
  471. boolean
  472. nv50_state_validate(struct nv50_context *nv50, uint32_t mask, unsigned words)
  473. {
  474.    uint32_t state_mask;
  475.    int ret;
  476.    unsigned i;
  477.  
  478.    if (nv50->screen->cur_ctx != nv50)
  479.       nv50_switch_pipe_context(nv50);
  480.  
  481.    state_mask = nv50->dirty & mask;
  482.  
  483.    if (state_mask) {
  484.       for (i = 0; i < validate_list_len; ++i) {
  485.          struct state_validate *validate = &validate_list[i];
  486.  
  487.          if (state_mask & validate->states)
  488.             validate->func(nv50);
  489.       }
  490.       nv50->dirty &= ~state_mask;
  491.  
  492.       if (nv50->state.rt_serialize) {
  493.          nv50->state.rt_serialize = FALSE;
  494.          BEGIN_NV04(nv50->base.pushbuf, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);
  495.          PUSH_DATA (nv50->base.pushbuf, 0);
  496.       }
  497.  
  498.       nv50_bufctx_fence(nv50->bufctx_3d, FALSE);
  499.    }
  500.    nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx_3d);
  501.    ret = nouveau_pushbuf_validate(nv50->base.pushbuf);
  502.  
  503.    if (unlikely(nv50->state.flushed)) {
  504.       nv50->state.flushed = FALSE;
  505.       nv50_bufctx_fence(nv50->bufctx_3d, TRUE);
  506.    }
  507.    return !ret;
  508. }
  509.