2 #include "util/u_viewport.h"
4 #include "nv50/nv50_context.h"
7 nv50_fb_set_null_rt(struct nouveau_pushbuf
*push
, unsigned i
)
9 BEGIN_NV04(push
, NV50_3D(RT_ADDRESS_HIGH(i
)), 4);
14 BEGIN_NV04(push
, NV50_3D(RT_HORIZ(i
)), 2);
20 nv50_validate_fb(struct nv50_context
*nv50
)
22 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
23 struct pipe_framebuffer_state
*fb
= &nv50
->framebuffer
;
25 unsigned ms_mode
= NV50_3D_MULTISAMPLE_MODE_MS1
;
26 uint32_t array_size
= 0xffff, array_mode
= 0;
28 nouveau_bufctx_reset(nv50
->bufctx_3d
, NV50_BIND_3D_FB
);
30 BEGIN_NV04(push
, NV50_3D(RT_CONTROL
), 1);
31 PUSH_DATA (push
, (076543210 << 4) | fb
->nr_cbufs
);
32 BEGIN_NV04(push
, NV50_3D(SCREEN_SCISSOR_HORIZ
), 2);
33 PUSH_DATA (push
, fb
->width
<< 16);
34 PUSH_DATA (push
, fb
->height
<< 16);
36 for (i
= 0; i
< fb
->nr_cbufs
; ++i
) {
37 struct nv50_miptree
*mt
;
38 struct nv50_surface
*sf
;
39 struct nouveau_bo
*bo
;
42 nv50_fb_set_null_rt(push
, i
);
46 mt
= nv50_miptree(fb
->cbufs
[i
]->texture
);
47 sf
= nv50_surface(fb
->cbufs
[i
]);
50 array_size
= MIN2(array_size
, sf
->depth
);
52 array_mode
= NV50_3D_RT_ARRAY_MODE_MODE_3D
; /* 1 << 16 */
54 /* can't mix 3D with ARRAY or have RTs of different depth/array_size */
55 assert(mt
->layout_3d
|| !array_mode
|| array_size
== 1);
57 BEGIN_NV04(push
, NV50_3D(RT_ADDRESS_HIGH(i
)), 5);
58 PUSH_DATAh(push
, mt
->base
.address
+ sf
->offset
);
59 PUSH_DATA (push
, mt
->base
.address
+ sf
->offset
);
60 PUSH_DATA (push
, nv50_format_table
[sf
->base
.format
].rt
);
61 if (likely(nouveau_bo_memtype(bo
))) {
62 assert(sf
->base
.texture
->target
!= PIPE_BUFFER
);
64 PUSH_DATA (push
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
65 PUSH_DATA (push
, mt
->layer_stride
>> 2);
66 BEGIN_NV04(push
, NV50_3D(RT_HORIZ(i
)), 2);
67 PUSH_DATA (push
, sf
->width
);
68 PUSH_DATA (push
, sf
->height
);
69 BEGIN_NV04(push
, NV50_3D(RT_ARRAY_MODE
), 1);
70 PUSH_DATA (push
, array_mode
| array_size
);
71 nv50
->rt_array_mode
= array_mode
| array_size
;
75 BEGIN_NV04(push
, NV50_3D(RT_HORIZ(i
)), 2);
76 PUSH_DATA (push
, NV50_3D_RT_HORIZ_LINEAR
| mt
->level
[0].pitch
);
77 PUSH_DATA (push
, sf
->height
);
78 BEGIN_NV04(push
, NV50_3D(RT_ARRAY_MODE
), 1);
85 ms_mode
= mt
->ms_mode
;
87 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
88 nv50
->state
.rt_serialize
= true;
89 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
90 mt
->base
.status
&= ~NOUVEAU_BUFFER_STATUS_GPU_READING
;
92 /* only register for writing, otherwise we'd always serialize here */
93 BCTX_REFN(nv50
->bufctx_3d
, 3D_FB
, &mt
->base
, WR
);
97 struct nv50_miptree
*mt
= nv50_miptree(fb
->zsbuf
->texture
);
98 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
99 int unk
= mt
->base
.base
.target
== PIPE_TEXTURE_3D
|| sf
->depth
== 1;
101 BEGIN_NV04(push
, NV50_3D(ZETA_ADDRESS_HIGH
), 5);
102 PUSH_DATAh(push
, mt
->base
.address
+ sf
->offset
);
103 PUSH_DATA (push
, mt
->base
.address
+ sf
->offset
);
104 PUSH_DATA (push
, nv50_format_table
[fb
->zsbuf
->format
].rt
);
105 PUSH_DATA (push
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
106 PUSH_DATA (push
, mt
->layer_stride
>> 2);
107 BEGIN_NV04(push
, NV50_3D(ZETA_ENABLE
), 1);
109 BEGIN_NV04(push
, NV50_3D(ZETA_HORIZ
), 3);
110 PUSH_DATA (push
, sf
->width
);
111 PUSH_DATA (push
, sf
->height
);
112 PUSH_DATA (push
, (unk
<< 16) | sf
->depth
);
114 ms_mode
= mt
->ms_mode
;
116 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
117 nv50
->state
.rt_serialize
= true;
118 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
119 mt
->base
.status
&= ~NOUVEAU_BUFFER_STATUS_GPU_READING
;
121 BCTX_REFN(nv50
->bufctx_3d
, 3D_FB
, &mt
->base
, WR
);
123 BEGIN_NV04(push
, NV50_3D(ZETA_ENABLE
), 1);
127 BEGIN_NV04(push
, NV50_3D(MULTISAMPLE_MODE
), 1);
128 PUSH_DATA (push
, ms_mode
);
130 /* Only need to initialize the first viewport, which is used for clears */
131 BEGIN_NV04(push
, NV50_3D(VIEWPORT_HORIZ(0)), 2);
132 PUSH_DATA (push
, fb
->width
<< 16);
133 PUSH_DATA (push
, fb
->height
<< 16);
135 if (nv50
->screen
->tesla
->oclass
>= NVA3_3D_CLASS
) {
136 unsigned ms
= 1 << ms_mode
;
137 BEGIN_NV04(push
, NV50_3D(CB_ADDR
), 1);
138 PUSH_DATA (push
, (NV50_CB_AUX_SAMPLE_OFFSET
<< (8 - 2)) | NV50_CB_AUX
);
139 BEGIN_NI04(push
, NV50_3D(CB_DATA(0)), 2 * ms
);
140 for (i
= 0; i
< ms
; i
++) {
142 nv50
->base
.pipe
.get_sample_position(&nv50
->base
.pipe
, ms
, i
, xy
);
143 PUSH_DATAf(push
, xy
[0]);
144 PUSH_DATAf(push
, xy
[1]);
150 nv50_validate_blend_colour(struct nv50_context
*nv50
)
152 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
154 BEGIN_NV04(push
, NV50_3D(BLEND_COLOR(0)), 4);
155 PUSH_DATAf(push
, nv50
->blend_colour
.color
[0]);
156 PUSH_DATAf(push
, nv50
->blend_colour
.color
[1]);
157 PUSH_DATAf(push
, nv50
->blend_colour
.color
[2]);
158 PUSH_DATAf(push
, nv50
->blend_colour
.color
[3]);
162 nv50_validate_stencil_ref(struct nv50_context
*nv50
)
164 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
166 BEGIN_NV04(push
, NV50_3D(STENCIL_FRONT_FUNC_REF
), 1);
167 PUSH_DATA (push
, nv50
->stencil_ref
.ref_value
[0]);
168 BEGIN_NV04(push
, NV50_3D(STENCIL_BACK_FUNC_REF
), 1);
169 PUSH_DATA (push
, nv50
->stencil_ref
.ref_value
[1]);
173 nv50_validate_stipple(struct nv50_context
*nv50
)
175 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
178 BEGIN_NV04(push
, NV50_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
179 for (i
= 0; i
< 32; ++i
)
180 PUSH_DATA(push
, util_bswap32(nv50
->stipple
.stipple
[i
]));
184 nv50_validate_scissor(struct nv50_context
*nv50
)
186 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
187 #ifdef NV50_SCISSORS_CLIPPING
188 int minx
, maxx
, miny
, maxy
, i
;
189 bool rast_scissor
= nv50
->rast
? nv50
->rast
->pipe
.scissor
: false;
191 if (!(nv50
->dirty_3d
&
192 (NV50_NEW_3D_SCISSOR
| NV50_NEW_3D_VIEWPORT
| NV50_NEW_3D_FRAMEBUFFER
)) &&
193 nv50
->state
.scissor
== rast_scissor
)
196 if (nv50
->state
.scissor
!= rast_scissor
)
197 nv50
->scissors_dirty
= (1 << NV50_MAX_VIEWPORTS
) - 1;
199 nv50
->state
.scissor
= rast_scissor
;
201 if ((nv50
->dirty_3d
& NV50_NEW_3D_FRAMEBUFFER
) && !nv50
->state
.scissor
)
202 nv50
->scissors_dirty
= (1 << NV50_MAX_VIEWPORTS
) - 1;
204 for (i
= 0; i
< NV50_MAX_VIEWPORTS
; i
++) {
205 struct pipe_scissor_state
*s
= &nv50
->scissors
[i
];
206 struct pipe_viewport_state
*vp
= &nv50
->viewports
[i
];
208 if (!(nv50
->scissors_dirty
& (1 << i
)) &&
209 !(nv50
->viewports_dirty
& (1 << i
)))
212 if (nv50
->state
.scissor
) {
219 maxx
= nv50
->framebuffer
.width
;
221 maxy
= nv50
->framebuffer
.height
;
224 minx
= MAX2(minx
, (int)(vp
->translate
[0] - fabsf(vp
->scale
[0])));
225 maxx
= MIN2(maxx
, (int)(vp
->translate
[0] + fabsf(vp
->scale
[0])));
226 miny
= MAX2(miny
, (int)(vp
->translate
[1] - fabsf(vp
->scale
[1])));
227 maxy
= MIN2(maxy
, (int)(vp
->translate
[1] + fabsf(vp
->scale
[1])));
229 minx
= MIN2(minx
, 8192);
230 maxx
= MAX2(maxx
, 0);
231 miny
= MIN2(miny
, 8192);
232 maxy
= MAX2(maxy
, 0);
234 BEGIN_NV04(push
, NV50_3D(SCISSOR_HORIZ(i
)), 2);
235 PUSH_DATA (push
, (maxx
<< 16) | minx
);
236 PUSH_DATA (push
, (maxy
<< 16) | miny
);
238 BEGIN_NV04(push
, NV50_3D(SCISSOR_HORIZ(i
)), 2);
239 PUSH_DATA (push
, (s
->maxx
<< 16) | s
->minx
);
240 PUSH_DATA (push
, (s
->maxy
<< 16) | s
->miny
);
244 nv50
->scissors_dirty
= 0;
248 nv50_validate_viewport(struct nv50_context
*nv50
)
250 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
254 for (i
= 0; i
< NV50_MAX_VIEWPORTS
; i
++) {
255 struct pipe_viewport_state
*vpt
= &nv50
->viewports
[i
];
257 if (!(nv50
->viewports_dirty
& (1 << i
)))
260 BEGIN_NV04(push
, NV50_3D(VIEWPORT_TRANSLATE_X(i
)), 3);
261 PUSH_DATAf(push
, vpt
->translate
[0]);
262 PUSH_DATAf(push
, vpt
->translate
[1]);
263 PUSH_DATAf(push
, vpt
->translate
[2]);
264 BEGIN_NV04(push
, NV50_3D(VIEWPORT_SCALE_X(i
)), 3);
265 PUSH_DATAf(push
, vpt
->scale
[0]);
266 PUSH_DATAf(push
, vpt
->scale
[1]);
267 PUSH_DATAf(push
, vpt
->scale
[2]);
269 /* If the halfz setting ever changes, the viewports will also get
270 * updated. The rast will get updated before the validate function has a
271 * chance to hit, so we can just use it directly without an atom
274 util_viewport_zmin_zmax(vpt
, nv50
->rast
->pipe
.clip_halfz
, &zmin
, &zmax
);
276 #ifdef NV50_SCISSORS_CLIPPING
277 BEGIN_NV04(push
, NV50_3D(DEPTH_RANGE_NEAR(i
)), 2);
278 PUSH_DATAf(push
, zmin
);
279 PUSH_DATAf(push
, zmax
);
283 nv50
->viewports_dirty
= 0;
287 nv50_validate_window_rects(struct nv50_context
*nv50
)
289 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
290 bool enable
= nv50
->window_rect
.rects
> 0 || nv50
->window_rect
.inclusive
;
293 BEGIN_NV04(push
, NV50_3D(CLIP_RECTS_EN
), 1);
294 PUSH_DATA (push
, enable
);
298 BEGIN_NV04(push
, NV50_3D(CLIP_RECTS_MODE
), 1);
299 PUSH_DATA (push
, !nv50
->window_rect
.inclusive
);
300 BEGIN_NV04(push
, NV50_3D(CLIP_RECT_HORIZ(0)), NV50_MAX_WINDOW_RECTANGLES
* 2);
301 for (i
= 0; i
< nv50
->window_rect
.rects
; i
++) {
302 struct pipe_scissor_state
*s
= &nv50
->window_rect
.rect
[i
];
303 PUSH_DATA(push
, (s
->maxx
<< 16) | s
->minx
);
304 PUSH_DATA(push
, (s
->maxy
<< 16) | s
->miny
);
306 for (; i
< NV50_MAX_WINDOW_RECTANGLES
; i
++) {
313 nv50_check_program_ucps(struct nv50_context
*nv50
,
314 struct nv50_program
*vp
, uint8_t mask
)
316 const unsigned n
= util_logbase2(mask
) + 1;
318 if (vp
->vp
.clpd_nr
>= n
)
320 nv50_program_destroy(nv50
, vp
);
323 if (likely(vp
== nv50
->vertprog
)) {
324 nv50
->dirty_3d
|= NV50_NEW_3D_VERTPROG
;
325 nv50_vertprog_validate(nv50
);
327 nv50
->dirty_3d
|= NV50_NEW_3D_GMTYPROG
;
328 nv50_gmtyprog_validate(nv50
);
330 nv50_fp_linkage_validate(nv50
);
333 /* alpha test is disabled if there are no color RTs, so make sure we have at
334 * least one if alpha test is enabled. Note that this must run after
335 * nv50_validate_fb, otherwise that will override the RT count setting.
338 nv50_validate_derived_2(struct nv50_context
*nv50
)
340 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
342 if (nv50
->zsa
&& nv50
->zsa
->pipe
.alpha
.enabled
&&
343 nv50
->framebuffer
.nr_cbufs
== 0) {
344 nv50_fb_set_null_rt(push
, 0);
345 BEGIN_NV04(push
, NV50_3D(RT_CONTROL
), 1);
346 PUSH_DATA (push
, (076543210 << 4) | 1);
351 nv50_validate_clip(struct nv50_context
*nv50
)
353 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
354 struct nv50_program
*vp
;
355 uint8_t clip_enable
= nv50
->rast
->pipe
.clip_plane_enable
;
357 if (nv50
->dirty_3d
& NV50_NEW_3D_CLIP
) {
358 BEGIN_NV04(push
, NV50_3D(CB_ADDR
), 1);
359 PUSH_DATA (push
, (NV50_CB_AUX_UCP_OFFSET
<< 8) | NV50_CB_AUX
);
360 BEGIN_NI04(push
, NV50_3D(CB_DATA(0)), PIPE_MAX_CLIP_PLANES
* 4);
361 PUSH_DATAp(push
, &nv50
->clip
.ucp
[0][0], PIPE_MAX_CLIP_PLANES
* 4);
369 nv50_check_program_ucps(nv50
, vp
, clip_enable
);
371 clip_enable
&= vp
->vp
.clip_enable
;
372 clip_enable
|= vp
->vp
.cull_enable
;
374 BEGIN_NV04(push
, NV50_3D(CLIP_DISTANCE_ENABLE
), 1);
375 PUSH_DATA (push
, clip_enable
);
377 if (nv50
->state
.clip_mode
!= vp
->vp
.clip_mode
) {
378 nv50
->state
.clip_mode
= vp
->vp
.clip_mode
;
379 BEGIN_NV04(push
, NV50_3D(CLIP_DISTANCE_MODE
), 1);
380 PUSH_DATA (push
, vp
->vp
.clip_mode
);
385 nv50_validate_blend(struct nv50_context
*nv50
)
387 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
389 PUSH_SPACE(push
, nv50
->blend
->size
);
390 PUSH_DATAp(push
, nv50
->blend
->state
, nv50
->blend
->size
);
394 nv50_validate_zsa(struct nv50_context
*nv50
)
396 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
398 PUSH_SPACE(push
, nv50
->zsa
->size
);
399 PUSH_DATAp(push
, nv50
->zsa
->state
, nv50
->zsa
->size
);
403 nv50_validate_rasterizer(struct nv50_context
*nv50
)
405 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
407 PUSH_SPACE(push
, nv50
->rast
->size
);
408 PUSH_DATAp(push
, nv50
->rast
->state
, nv50
->rast
->size
);
412 nv50_validate_sample_mask(struct nv50_context
*nv50
)
414 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
418 nv50
->sample_mask
& 0xffff,
419 nv50
->sample_mask
& 0xffff,
420 nv50
->sample_mask
& 0xffff,
421 nv50
->sample_mask
& 0xffff
424 BEGIN_NV04(push
, NV50_3D(MSAA_MASK(0)), 4);
425 PUSH_DATA (push
, mask
[0]);
426 PUSH_DATA (push
, mask
[1]);
427 PUSH_DATA (push
, mask
[2]);
428 PUSH_DATA (push
, mask
[3]);
432 nv50_validate_min_samples(struct nv50_context
*nv50
)
434 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
437 if (nv50
->screen
->tesla
->oclass
< NVA3_3D_CLASS
)
440 samples
= util_next_power_of_two(nv50
->min_samples
);
442 samples
|= NVA3_3D_SAMPLE_SHADING_ENABLE
;
444 BEGIN_NV04(push
, SUBC_3D(NVA3_3D_SAMPLE_SHADING
), 1);
445 PUSH_DATA (push
, samples
);
449 nv50_switch_pipe_context(struct nv50_context
*ctx_to
)
451 struct nv50_context
*ctx_from
= ctx_to
->screen
->cur_ctx
;
454 ctx_to
->state
= ctx_from
->state
;
456 ctx_to
->state
= ctx_to
->screen
->save_state
;
458 ctx_to
->dirty_3d
= ~0;
459 ctx_to
->dirty_cp
= ~0;
460 ctx_to
->viewports_dirty
= ~0;
461 ctx_to
->scissors_dirty
= ~0;
463 ctx_to
->constbuf_dirty
[0] =
464 ctx_to
->constbuf_dirty
[1] =
465 ctx_to
->constbuf_dirty
[2] = (1 << NV50_MAX_PIPE_CONSTBUFS
) - 1;
468 ctx_to
->dirty_3d
&= ~(NV50_NEW_3D_VERTEX
| NV50_NEW_3D_ARRAYS
);
470 if (!ctx_to
->vertprog
)
471 ctx_to
->dirty_3d
&= ~NV50_NEW_3D_VERTPROG
;
472 if (!ctx_to
->fragprog
)
473 ctx_to
->dirty_3d
&= ~NV50_NEW_3D_FRAGPROG
;
476 ctx_to
->dirty_3d
&= ~NV50_NEW_3D_BLEND
;
478 #ifdef NV50_SCISSORS_CLIPPING
479 ctx_to
->dirty_3d
&= ~(NV50_NEW_3D_RASTERIZER
| NV50_NEW_3D_SCISSOR
);
481 ctx_to
->dirty_3d
&= ~NV50_NEW_3D_RASTERIZER
;
484 ctx_to
->dirty_3d
&= ~NV50_NEW_3D_ZSA
;
486 ctx_to
->screen
->cur_ctx
= ctx_to
;
489 static struct nv50_state_validate
490 validate_list_3d
[] = {
491 { nv50_validate_fb
, NV50_NEW_3D_FRAMEBUFFER
},
492 { nv50_validate_blend
, NV50_NEW_3D_BLEND
},
493 { nv50_validate_zsa
, NV50_NEW_3D_ZSA
},
494 { nv50_validate_sample_mask
, NV50_NEW_3D_SAMPLE_MASK
},
495 { nv50_validate_rasterizer
, NV50_NEW_3D_RASTERIZER
},
496 { nv50_validate_blend_colour
, NV50_NEW_3D_BLEND_COLOUR
},
497 { nv50_validate_stencil_ref
, NV50_NEW_3D_STENCIL_REF
},
498 { nv50_validate_stipple
, NV50_NEW_3D_STIPPLE
},
499 #ifdef NV50_SCISSORS_CLIPPING
500 { nv50_validate_scissor
, NV50_NEW_3D_SCISSOR
| NV50_NEW_3D_VIEWPORT
|
501 NV50_NEW_3D_RASTERIZER
|
502 NV50_NEW_3D_FRAMEBUFFER
},
504 { nv50_validate_scissor
, NV50_NEW_3D_SCISSOR
},
506 { nv50_validate_viewport
, NV50_NEW_3D_VIEWPORT
},
507 { nv50_validate_window_rects
, NV50_NEW_3D_WINDOW_RECTS
},
508 { nv50_vertprog_validate
, NV50_NEW_3D_VERTPROG
},
509 { nv50_gmtyprog_validate
, NV50_NEW_3D_GMTYPROG
},
510 { nv50_fragprog_validate
, NV50_NEW_3D_FRAGPROG
| NV50_NEW_3D_RASTERIZER
|
511 NV50_NEW_3D_MIN_SAMPLES
| NV50_NEW_3D_ZSA
|
512 NV50_NEW_3D_FRAMEBUFFER
},
513 { nv50_fp_linkage_validate
, NV50_NEW_3D_FRAGPROG
| NV50_NEW_3D_VERTPROG
|
514 NV50_NEW_3D_GMTYPROG
| NV50_NEW_3D_RASTERIZER
},
515 { nv50_gp_linkage_validate
, NV50_NEW_3D_GMTYPROG
| NV50_NEW_3D_VERTPROG
},
516 { nv50_validate_derived_rs
, NV50_NEW_3D_FRAGPROG
| NV50_NEW_3D_RASTERIZER
|
517 NV50_NEW_3D_VERTPROG
| NV50_NEW_3D_GMTYPROG
},
518 { nv50_validate_derived_2
, NV50_NEW_3D_ZSA
| NV50_NEW_3D_FRAMEBUFFER
},
519 { nv50_validate_clip
, NV50_NEW_3D_CLIP
| NV50_NEW_3D_RASTERIZER
|
520 NV50_NEW_3D_VERTPROG
| NV50_NEW_3D_GMTYPROG
},
521 { nv50_constbufs_validate
, NV50_NEW_3D_CONSTBUF
},
522 { nv50_validate_textures
, NV50_NEW_3D_TEXTURES
},
523 { nv50_validate_samplers
, NV50_NEW_3D_SAMPLERS
},
524 { nv50_stream_output_validate
, NV50_NEW_3D_STRMOUT
|
525 NV50_NEW_3D_VERTPROG
| NV50_NEW_3D_GMTYPROG
},
526 { nv50_vertex_arrays_validate
, NV50_NEW_3D_VERTEX
| NV50_NEW_3D_ARRAYS
},
527 { nv50_validate_min_samples
, NV50_NEW_3D_MIN_SAMPLES
},
531 nv50_state_validate(struct nv50_context
*nv50
, uint32_t mask
,
532 struct nv50_state_validate
*validate_list
, int size
,
533 uint32_t *dirty
, struct nouveau_bufctx
*bufctx
)
539 if (nv50
->screen
->cur_ctx
!= nv50
)
540 nv50_switch_pipe_context(nv50
);
542 state_mask
= *dirty
& mask
;
545 for (i
= 0; i
< size
; i
++) {
546 struct nv50_state_validate
*validate
= &validate_list
[i
];
548 if (state_mask
& validate
->states
)
549 validate
->func(nv50
);
551 *dirty
&= ~state_mask
;
553 if (nv50
->state
.rt_serialize
) {
554 nv50
->state
.rt_serialize
= false;
555 BEGIN_NV04(nv50
->base
.pushbuf
, SUBC_3D(NV50_GRAPH_SERIALIZE
), 1);
556 PUSH_DATA (nv50
->base
.pushbuf
, 0);
559 nv50_bufctx_fence(bufctx
, false);
561 nouveau_pushbuf_bufctx(nv50
->base
.pushbuf
, bufctx
);
562 ret
= nouveau_pushbuf_validate(nv50
->base
.pushbuf
);
568 nv50_state_validate_3d(struct nv50_context
*nv50
, uint32_t mask
)
572 ret
= nv50_state_validate(nv50
, mask
, validate_list_3d
,
573 ARRAY_SIZE(validate_list_3d
), &nv50
->dirty_3d
,
576 if (unlikely(nv50
->state
.flushed
)) {
577 nv50
->state
.flushed
= false;
578 nv50_bufctx_fence(nv50
->bufctx_3d
, true);