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