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