Home | History | Annotate | Download | only in nv30
      1 /*
      2  * Copyright 2012 Red Hat Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20  * OTHER DEALINGS IN THE SOFTWARE.
     21  *
     22  * Authors: Ben Skeggs
     23  *
     24  */
     25 
     26 #include "util/u_format.h"
     27 #include "util/u_math.h"
     28 #include "util/u_half.h"
     29 
     30 #include "nv_object.xml.h"
     31 #include "nv30/nv30-40_3d.xml.h"
     32 #include "nv30/nv30_context.h"
     33 #include "nv30/nv30_format.h"
     34 
     35 static void
     36 nv30_validate_fb(struct nv30_context *nv30)
     37 {
     38    struct pipe_screen *pscreen = &nv30->screen->base.base;
     39    struct pipe_framebuffer_state *fb = &nv30->framebuffer;
     40    struct nouveau_pushbuf *push = nv30->base.pushbuf;
     41    struct nouveau_object *eng3d = nv30->screen->eng3d;
     42    uint32_t rt_format;
     43    int h = fb->height;
     44    int w = fb->width;
     45    int x = 0;
     46    int y = 0;
     47 
     48    nv30->state.rt_enable = (NV30_3D_RT_ENABLE_COLOR0 << fb->nr_cbufs) - 1;
     49    if (nv30->state.rt_enable > 1)
     50       nv30->state.rt_enable |= NV30_3D_RT_ENABLE_MRT;
     51 
     52    rt_format = 0;
     53    if (fb->nr_cbufs > 0) {
     54       struct nv30_miptree *mt = nv30_miptree(fb->cbufs[0]->texture);
     55       rt_format |= nv30_format(pscreen, fb->cbufs[0]->format)->hw;
     56       rt_format |= mt->ms_mode;
     57       if (mt->swizzled)
     58          rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
     59       else
     60          rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
     61    } else {
     62       if (fb->zsbuf && util_format_get_blocksize(fb->zsbuf->format) > 2)
     63          rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
     64       else
     65          rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;
     66    }
     67 
     68    if (fb->zsbuf) {
     69       rt_format |= nv30_format(pscreen, fb->zsbuf->format)->hw;
     70       if (nv30_miptree(fb->zsbuf->texture)->swizzled)
     71          rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
     72       else
     73          rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
     74    } else {
     75       if (fb->nr_cbufs && util_format_get_blocksize(fb->cbufs[0]->format) > 2)
     76          rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
     77       else
     78          rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;
     79    }
     80 
     81    /* hardware rounds down render target offset to 64 bytes, but surfaces
     82     * with a size of 2x2 pixel (16bpp) or 1x1 pixel (32bpp) have an
     83     * unaligned start aaddress.  For these two important square formats
     84     * we can hack around this limitation by adjusting the viewport origin
     85     */
     86    if (nv30->state.rt_enable) {
     87       int off = nv30_surface(fb->cbufs[0])->offset & 63;
     88       if (off) {
     89          x += off / (util_format_get_blocksize(fb->cbufs[0]->format) * 2);
     90          w  = 16;
     91          h  = 2;
     92       }
     93    }
     94 
     95    if (rt_format & NV30_3D_RT_FORMAT_TYPE_SWIZZLED) {
     96       rt_format |= util_logbase2(w) << 16;
     97       rt_format |= util_logbase2(h) << 24;
     98    }
     99 
    100    if (!PUSH_SPACE(push, 64))
    101       return;
    102    PUSH_RESET(push, BUFCTX_FB);
    103 
    104    BEGIN_NV04(push, SUBC_3D(0x1da4), 1);
    105    PUSH_DATA (push, 0);
    106    BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
    107    PUSH_DATA (push, w << 16);
    108    PUSH_DATA (push, h << 16);
    109    PUSH_DATA (push, rt_format);
    110    BEGIN_NV04(push, NV30_3D(VIEWPORT_TX_ORIGIN), 4);
    111    PUSH_DATA (push, (y << 16) | x);
    112    PUSH_DATA (push, 0);
    113    PUSH_DATA (push, ((w - 1) << 16) | 0);
    114    PUSH_DATA (push, ((h - 1) << 16) | 0);
    115 
    116    if ((nv30->state.rt_enable & NV30_3D_RT_ENABLE_COLOR0) || fb->zsbuf) {
    117       struct nv30_surface *rsf = nv30_surface(fb->cbufs[0]);
    118       struct nv30_surface *zsf = nv30_surface(fb->zsbuf);
    119       struct nouveau_bo *rbo, *zbo;
    120 
    121       if (!rsf)      rsf = zsf;
    122       else if (!zsf) zsf = rsf;
    123       rbo = nv30_miptree(rsf->base.texture)->base.bo;
    124       zbo = nv30_miptree(zsf->base.texture)->base.bo;
    125 
    126       if (eng3d->oclass >= NV40_3D_CLASS) {
    127          BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
    128          PUSH_DATA (push, zsf->pitch);
    129          BEGIN_NV04(push, NV40_3D(COLOR0_PITCH), 3);
    130          PUSH_DATA (push, rsf->pitch);
    131       } else {
    132          BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 3);
    133          PUSH_DATA (push, (zsf->pitch << 16) | rsf->pitch);
    134       }
    135       PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), BUFCTX_FB, rbo, rsf->offset & ~63,
    136                        NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
    137       PUSH_MTHDl(push, NV30_3D(ZETA_OFFSET), BUFCTX_FB, zbo, zsf->offset & ~63,
    138                        NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
    139    }
    140 
    141    if (nv30->state.rt_enable & NV30_3D_RT_ENABLE_COLOR1) {
    142       struct nv30_surface *sf = nv30_surface(fb->cbufs[1]);
    143       struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
    144 
    145       BEGIN_NV04(push, NV30_3D(COLOR1_OFFSET), 2);
    146       PUSH_MTHDl(push, NV30_3D(COLOR1_OFFSET), BUFCTX_FB, bo, sf->offset,
    147                        NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
    148       PUSH_DATA (push, sf->pitch);
    149    }
    150 
    151    if (nv30->state.rt_enable & NV40_3D_RT_ENABLE_COLOR2) {
    152       struct nv30_surface *sf = nv30_surface(fb->cbufs[2]);
    153       struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
    154 
    155       BEGIN_NV04(push, NV40_3D(COLOR2_OFFSET), 1);
    156       PUSH_MTHDl(push, NV40_3D(COLOR2_OFFSET), BUFCTX_FB, bo, sf->offset,
    157                        NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
    158       BEGIN_NV04(push, NV40_3D(COLOR2_PITCH), 1);
    159       PUSH_DATA (push, sf->pitch);
    160    }
    161 
    162    if (nv30->state.rt_enable & NV40_3D_RT_ENABLE_COLOR3) {
    163       struct nv30_surface *sf = nv30_surface(fb->cbufs[3]);
    164       struct nouveau_bo *bo = nv30_miptree(sf->base.texture)->base.bo;
    165 
    166       BEGIN_NV04(push, NV40_3D(COLOR3_OFFSET), 1);
    167       PUSH_MTHDl(push, NV40_3D(COLOR3_OFFSET), BUFCTX_FB, bo, sf->offset,
    168                        NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
    169       BEGIN_NV04(push, NV40_3D(COLOR3_PITCH), 1);
    170       PUSH_DATA (push, sf->pitch);
    171    }
    172 }
    173 
    174 static void
    175 nv30_validate_blend_colour(struct nv30_context *nv30)
    176 {
    177    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    178    float *rgba = nv30->blend_colour.color;
    179 
    180    if (nv30->framebuffer.nr_cbufs) {
    181       switch (nv30->framebuffer.cbufs[0]->format) {
    182       case PIPE_FORMAT_R16G16B16A16_FLOAT:
    183       case PIPE_FORMAT_R32G32B32A32_FLOAT:
    184          BEGIN_NV04(push, NV30_3D(BLEND_COLOR), 1);
    185          PUSH_DATA (push, (util_float_to_half(rgba[0]) <<  0) |
    186                           (util_float_to_half(rgba[1]) << 16));
    187          BEGIN_NV04(push, SUBC_3D(0x037c), 1);
    188          PUSH_DATA (push, (util_float_to_half(rgba[2]) <<  0) |
    189                           (util_float_to_half(rgba[3]) << 16));
    190          break;
    191       default:
    192          break;
    193       }
    194    }
    195 
    196    BEGIN_NV04(push, NV30_3D(BLEND_COLOR), 1);
    197    PUSH_DATA (push, (float_to_ubyte(rgba[3]) << 24) |
    198                     (float_to_ubyte(rgba[0]) << 16) |
    199                     (float_to_ubyte(rgba[1]) <<  8) |
    200                     (float_to_ubyte(rgba[2]) <<  0));
    201 }
    202 
    203 static void
    204 nv30_validate_stencil_ref(struct nv30_context *nv30)
    205 {
    206    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    207 
    208    BEGIN_NV04(push, NV30_3D(STENCIL_FUNC_REF(0)), 1);
    209    PUSH_DATA (push, nv30->stencil_ref.ref_value[0]);
    210    BEGIN_NV04(push, NV30_3D(STENCIL_FUNC_REF(1)), 1);
    211    PUSH_DATA (push, nv30->stencil_ref.ref_value[1]);
    212 }
    213 
    214 static void
    215 nv30_validate_stipple(struct nv30_context *nv30)
    216 {
    217    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    218 
    219    BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
    220    PUSH_DATAp(push, nv30->stipple.stipple, 32);
    221 }
    222 
    223 static void
    224 nv30_validate_scissor(struct nv30_context *nv30)
    225 {
    226    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    227    struct pipe_scissor_state *s = &nv30->scissor;
    228    bool rast_scissor = nv30->rast ? nv30->rast->pipe.scissor : false;
    229 
    230    if (!(nv30->dirty & NV30_NEW_SCISSOR) &&
    231        rast_scissor != nv30->state.scissor_off)
    232       return;
    233    nv30->state.scissor_off = !rast_scissor;
    234 
    235    BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
    236    if (rast_scissor) {
    237       PUSH_DATA (push, ((s->maxx - s->minx) << 16) | s->minx);
    238       PUSH_DATA (push, ((s->maxy - s->miny) << 16) | s->miny);
    239    } else {
    240       PUSH_DATA (push, 0x10000000);
    241       PUSH_DATA (push, 0x10000000);
    242    }
    243 }
    244 
    245 static void
    246 nv30_validate_viewport(struct nv30_context *nv30)
    247 {
    248    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    249    struct pipe_viewport_state *vp = &nv30->viewport;
    250 
    251    unsigned x = CLAMP(vp->translate[0] - fabsf(vp->scale[0]), 0, 4095);
    252    unsigned y = CLAMP(vp->translate[1] - fabsf(vp->scale[1]), 0, 4095);
    253    unsigned w = CLAMP(2.0f * fabsf(vp->scale[0]), 0, 4096);
    254    unsigned h = CLAMP(2.0f * fabsf(vp->scale[1]), 0, 4096);
    255 
    256    BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
    257    PUSH_DATAf(push, vp->translate[0]);
    258    PUSH_DATAf(push, vp->translate[1]);
    259    PUSH_DATAf(push, vp->translate[2]);
    260    PUSH_DATAf(push, 0.0f);
    261    PUSH_DATAf(push, vp->scale[0]);
    262    PUSH_DATAf(push, vp->scale[1]);
    263    PUSH_DATAf(push, vp->scale[2]);
    264    PUSH_DATAf(push, 0.0f);
    265    BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
    266    PUSH_DATAf(push, vp->translate[2] - fabsf(vp->scale[2]));
    267    PUSH_DATAf(push, vp->translate[2] + fabsf(vp->scale[2]));
    268 
    269    BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
    270    PUSH_DATA (push, (w << 16) | x);
    271    PUSH_DATA (push, (h << 16) | y);
    272 }
    273 
    274 static void
    275 nv30_validate_clip(struct nv30_context *nv30)
    276 {
    277    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    278    unsigned i;
    279    uint32_t clpd_enable = 0;
    280 
    281    for (i = 0; i < 6; i++) {
    282       if (nv30->dirty & NV30_NEW_CLIP) {
    283          BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 5);
    284          PUSH_DATA (push, i);
    285          PUSH_DATAp(push, nv30->clip.ucp[i], 4);
    286       }
    287       if (nv30->rast->pipe.clip_plane_enable & (1 << i))
    288          clpd_enable |= 2 << (4*i);
    289    }
    290 
    291    BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1);
    292    PUSH_DATA (push, clpd_enable);
    293 }
    294 
    295 static void
    296 nv30_validate_blend(struct nv30_context *nv30)
    297 {
    298    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    299 
    300    PUSH_SPACE(push, nv30->blend->size);
    301    PUSH_DATAp(push, nv30->blend->data, nv30->blend->size);
    302 }
    303 
    304 static void
    305 nv30_validate_zsa(struct nv30_context *nv30)
    306 {
    307    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    308 
    309    PUSH_SPACE(push, nv30->zsa->size);
    310    PUSH_DATAp(push, nv30->zsa->data, nv30->zsa->size);
    311 }
    312 
    313 static void
    314 nv30_validate_rasterizer(struct nv30_context *nv30)
    315 {
    316    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    317 
    318    PUSH_SPACE(push, nv30->rast->size);
    319    PUSH_DATAp(push, nv30->rast->data, nv30->rast->size);
    320 }
    321 
    322 static void
    323 nv30_validate_multisample(struct nv30_context *nv30)
    324 {
    325    struct pipe_rasterizer_state *rasterizer = &nv30->rast->pipe;
    326    struct pipe_blend_state *blend = &nv30->blend->pipe;
    327    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    328    uint32_t ctrl = nv30->sample_mask << 16;
    329 
    330    if (blend->alpha_to_one)
    331       ctrl |= 0x00000100;
    332    if (blend->alpha_to_coverage)
    333       ctrl |= 0x00000010;
    334    if (rasterizer->multisample)
    335       ctrl |= 0x00000001;
    336 
    337    BEGIN_NV04(push, NV30_3D(MULTISAMPLE_CONTROL), 1);
    338    PUSH_DATA (push, ctrl);
    339 }
    340 
    341 static void
    342 nv30_validate_fragment(struct nv30_context *nv30)
    343 {
    344    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    345    struct nv30_fragprog *fp = nv30->fragprog.program;
    346 
    347    BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
    348    PUSH_DATA (push, nv30->state.rt_enable & (fp ? ~fp->rt_enable : 0x1f));
    349    BEGIN_NV04(push, NV30_3D(COORD_CONVENTIONS), 1);
    350    PUSH_DATA (push, (fp ? fp->coord_conventions : 0) | nv30->framebuffer.height);
    351 }
    352 
    353 static void
    354 nv30_validate_point_coord(struct nv30_context *nv30)
    355 {
    356    struct pipe_rasterizer_state *rasterizer = &nv30->rast->pipe;
    357    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    358    struct nv30_fragprog *fp = nv30->fragprog.program;
    359    uint32_t hw = 0x00000000;
    360 
    361    if (rasterizer) {
    362       hw |= (nv30->rast->pipe.sprite_coord_enable & 0xff) << 8;
    363       if (fp)
    364          hw |= fp->point_sprite_control;
    365 
    366       if (rasterizer->sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT) {
    367          if (hw)
    368             nv30->draw_flags |= NV30_NEW_RASTERIZER;
    369       } else
    370       if (rasterizer->point_quad_rasterization) {
    371          hw |= NV30_3D_POINT_SPRITE_ENABLE;
    372       }
    373    }
    374 
    375    BEGIN_NV04(push, NV30_3D(POINT_SPRITE), 1);
    376    PUSH_DATA (push, hw);
    377 }
    378 
    379 struct state_validate {
    380    void (*func)(struct nv30_context *);
    381    uint32_t mask;
    382 };
    383 
    384 static struct state_validate hwtnl_validate_list[] = {
    385     { nv30_validate_fb,            NV30_NEW_FRAMEBUFFER },
    386     { nv30_validate_blend,         NV30_NEW_BLEND },
    387     { nv30_validate_zsa,           NV30_NEW_ZSA },
    388     { nv30_validate_rasterizer,    NV30_NEW_RASTERIZER },
    389     { nv30_validate_multisample,   NV30_NEW_SAMPLE_MASK | NV30_NEW_BLEND |
    390                                    NV30_NEW_RASTERIZER },
    391     { nv30_validate_blend_colour,  NV30_NEW_BLEND_COLOUR |
    392                                    NV30_NEW_FRAMEBUFFER },
    393     { nv30_validate_stencil_ref,   NV30_NEW_STENCIL_REF },
    394     { nv30_validate_stipple,       NV30_NEW_STIPPLE },
    395     { nv30_validate_scissor,       NV30_NEW_SCISSOR | NV30_NEW_RASTERIZER },
    396     { nv30_validate_viewport,      NV30_NEW_VIEWPORT },
    397     { nv30_validate_clip,          NV30_NEW_CLIP | NV30_NEW_RASTERIZER },
    398     { nv30_fragprog_validate,      NV30_NEW_FRAGPROG | NV30_NEW_FRAGCONST },
    399     { nv30_vertprog_validate,      NV30_NEW_VERTPROG | NV30_NEW_VERTCONST |
    400                                    NV30_NEW_FRAGPROG | NV30_NEW_RASTERIZER },
    401     { nv30_validate_fragment,      NV30_NEW_FRAMEBUFFER | NV30_NEW_FRAGPROG },
    402     { nv30_validate_point_coord,   NV30_NEW_RASTERIZER | NV30_NEW_FRAGPROG },
    403     { nv30_fragtex_validate,       NV30_NEW_FRAGTEX },
    404     { nv40_verttex_validate,       NV30_NEW_VERTTEX },
    405     { nv30_vbo_validate,           NV30_NEW_VERTEX | NV30_NEW_ARRAYS },
    406     {}
    407 };
    408 
    409 #define NV30_SWTNL_MASK (NV30_NEW_VIEWPORT |  \
    410                          NV30_NEW_CLIP |      \
    411                          NV30_NEW_VERTPROG |  \
    412                          NV30_NEW_VERTCONST | \
    413                          NV30_NEW_VERTTEX |   \
    414                          NV30_NEW_VERTEX |    \
    415                          NV30_NEW_ARRAYS)
    416 
    417 static struct state_validate swtnl_validate_list[] = {
    418     { nv30_validate_fb,            NV30_NEW_FRAMEBUFFER },
    419     { nv30_validate_blend,         NV30_NEW_BLEND },
    420     { nv30_validate_zsa,           NV30_NEW_ZSA },
    421     { nv30_validate_rasterizer,    NV30_NEW_RASTERIZER },
    422     { nv30_validate_multisample,   NV30_NEW_SAMPLE_MASK | NV30_NEW_BLEND |
    423                                    NV30_NEW_RASTERIZER },
    424     { nv30_validate_blend_colour,  NV30_NEW_BLEND_COLOUR |
    425                                    NV30_NEW_FRAMEBUFFER },
    426     { nv30_validate_stencil_ref,   NV30_NEW_STENCIL_REF },
    427     { nv30_validate_stipple,       NV30_NEW_STIPPLE },
    428     { nv30_validate_scissor,       NV30_NEW_SCISSOR | NV30_NEW_RASTERIZER },
    429     { nv30_fragprog_validate,      NV30_NEW_FRAGPROG | NV30_NEW_FRAGCONST },
    430     { nv30_validate_fragment,      NV30_NEW_FRAMEBUFFER | NV30_NEW_FRAGPROG },
    431     { nv30_fragtex_validate,       NV30_NEW_FRAGTEX },
    432     {}
    433 };
    434 
    435 static void
    436 nv30_state_context_switch(struct nv30_context *nv30)
    437 {
    438    struct nv30_context *prev = nv30->screen->cur_ctx;
    439 
    440    if (prev)
    441       nv30->state = prev->state;
    442    nv30->dirty = NV30_NEW_ALL;
    443 
    444    if (!nv30->vertex)
    445       nv30->dirty &= ~(NV30_NEW_VERTEX | NV30_NEW_ARRAYS);
    446 
    447    if (!nv30->vertprog.program)
    448       nv30->dirty &= ~NV30_NEW_VERTPROG;
    449    if (!nv30->fragprog.program)
    450       nv30->dirty &= ~NV30_NEW_FRAGPROG;
    451 
    452    if (!nv30->blend)
    453       nv30->dirty &= ~NV30_NEW_BLEND;
    454    if (!nv30->rast)
    455       nv30->dirty &= ~NV30_NEW_RASTERIZER;
    456    if (!nv30->zsa)
    457       nv30->dirty &= ~NV30_NEW_ZSA;
    458 
    459    nv30->screen->cur_ctx = nv30;
    460    nv30->base.pushbuf->user_priv = &nv30->bufctx;
    461 }
    462 
    463 bool
    464 nv30_state_validate(struct nv30_context *nv30, uint32_t mask, bool hwtnl)
    465 {
    466    struct nouveau_screen *screen = &nv30->screen->base;
    467    struct nouveau_pushbuf *push = nv30->base.pushbuf;
    468    struct nouveau_bufctx *bctx = nv30->bufctx;
    469    struct nouveau_bufref *bref;
    470    struct state_validate *validate;
    471 
    472    if (nv30->screen->cur_ctx != nv30)
    473       nv30_state_context_switch(nv30);
    474 
    475    if (hwtnl) {
    476       nv30->draw_dirty |= nv30->dirty;
    477       if (nv30->draw_flags) {
    478          nv30->draw_flags &= ~nv30->dirty;
    479          if (!nv30->draw_flags)
    480             nv30->dirty |= NV30_SWTNL_MASK;
    481       }
    482    }
    483 
    484    if (!nv30->draw_flags)
    485       validate = hwtnl_validate_list;
    486    else
    487       validate = swtnl_validate_list;
    488 
    489    mask &= nv30->dirty;
    490 
    491    if (mask) {
    492       while (validate->func) {
    493          if (mask & validate->mask)
    494             validate->func(nv30);
    495          validate++;
    496       }
    497 
    498       nv30->dirty &= ~mask;
    499    }
    500 
    501    nouveau_pushbuf_bufctx(push, bctx);
    502    if (nouveau_pushbuf_validate(push)) {
    503       nouveau_pushbuf_bufctx(push, NULL);
    504       return false;
    505    }
    506 
    507    /*XXX*/
    508    BEGIN_NV04(push, NV30_3D(VTX_CACHE_INVALIDATE_1710), 1);
    509    PUSH_DATA (push, 0);
    510    if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) {
    511       BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
    512       PUSH_DATA (push, 2);
    513       BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
    514       PUSH_DATA (push, 1);
    515       BEGIN_NV04(push, NV30_3D(R1718), 1);
    516       PUSH_DATA (push, 0);
    517       BEGIN_NV04(push, NV30_3D(R1718), 1);
    518       PUSH_DATA (push, 0);
    519       BEGIN_NV04(push, NV30_3D(R1718), 1);
    520       PUSH_DATA (push, 0);
    521    }
    522 
    523    LIST_FOR_EACH_ENTRY(bref, &bctx->current, thead) {
    524       struct nv04_resource *res = bref->priv;
    525       if (res && res->mm) {
    526          nouveau_fence_ref(screen->fence.current, &res->fence);
    527 
    528          if (bref->flags & NOUVEAU_BO_RD)
    529             res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
    530 
    531          if (bref->flags & NOUVEAU_BO_WR) {
    532             nouveau_fence_ref(screen->fence.current, &res->fence_wr);
    533             res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
    534          }
    535       }
    536    }
    537 
    538    return true;
    539 }
    540 
    541 void
    542 nv30_state_release(struct nv30_context *nv30)
    543 {
    544    nouveau_pushbuf_bufctx(nv30->base.pushbuf, NULL);
    545 }
    546