• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
nv30_validate_fb(struct nv30_context * nv30)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
nv30_validate_blend_colour(struct nv30_context * nv30)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
nv30_validate_stencil_ref(struct nv30_context * nv30)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
nv30_validate_stipple(struct nv30_context * nv30)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
nv30_validate_scissor(struct nv30_context * nv30)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
nv30_validate_viewport(struct nv30_context * nv30)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
nv30_validate_clip(struct nv30_context * nv30)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
nv30_validate_blend(struct nv30_context * nv30)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
nv30_validate_zsa(struct nv30_context * nv30)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
nv30_validate_rasterizer(struct nv30_context * nv30)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
nv30_validate_multisample(struct nv30_context * nv30)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
nv30_validate_fragment(struct nv30_context * nv30)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
nv30_validate_point_coord(struct nv30_context * nv30)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
nv30_state_context_switch(struct nv30_context * nv30)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
nv30_state_validate(struct nv30_context * nv30,uint32_t mask,bool hwtnl)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
nv30_state_release(struct nv30_context * nv30)542 nv30_state_release(struct nv30_context *nv30)
543 {
544    nouveau_pushbuf_bufctx(nv30->base.pushbuf, NULL);
545 }
546