2 #include "util/u_format.h"
3 #include "util/u_math.h"
5 #include "nvc0/nvc0_context.h"
9 nvc0_validate_zcull(struct nvc0_context
*nvc0
)
11 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
12 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
13 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
14 struct nv50_miptree
*mt
= nv50_miptree(sf
->base
.texture
);
15 struct nouveau_bo
*bo
= mt
->base
.bo
;
17 uint32_t offset
= align(mt
->total_size
, 1 << 17);
18 unsigned width
, height
;
20 assert(mt
->base
.base
.depth0
== 1 && mt
->base
.base
.array_size
< 2);
22 size
= mt
->total_size
* 2;
24 height
= align(fb
->height
, 32);
25 width
= fb
->width
% 224;
27 width
= fb
->width
+ (224 - width
);
31 BEGIN_NVC0(push
, NVC0_3D(ZCULL_REGION
), 1);
33 BEGIN_NVC0(push
, NVC0_3D(ZCULL_ADDRESS_HIGH
), 2);
34 PUSH_DATAh(push
, bo
->offset
+ offset
);
35 PUSH_DATA (push
, bo
->offset
+ offset
);
37 BEGIN_NVC0(push
, NVC0_3D(ZCULL_LIMIT_HIGH
), 2);
38 PUSH_DATAh(push
, bo
->offset
+ offset
);
39 PUSH_DATA (push
, bo
->offset
+ offset
);
40 BEGIN_NVC0(push
, SUBC_3D(0x07e0), 2);
41 PUSH_DATA (push
, size
);
42 PUSH_DATA (push
, size
>> 16);
43 BEGIN_NVC0(push
, SUBC_3D(0x15c8), 1); /* bits 0x3 */
45 BEGIN_NVC0(push
, NVC0_3D(ZCULL_WIDTH
), 4);
46 PUSH_DATA (push
, width
);
47 PUSH_DATA (push
, height
);
50 BEGIN_NVC0(push
, NVC0_3D(ZCULL_WINDOW_OFFSET_X
), 2);
53 BEGIN_NVC0(push
, NVC0_3D(ZCULL_INVALIDATE
), 1);
59 nvc0_fb_set_null_rt(struct nouveau_pushbuf
*push
, unsigned i
)
61 BEGIN_NVC0(push
, NVC0_3D(RT_ADDRESS_HIGH(i
)), 6);
71 nvc0_validate_fb(struct nvc0_context
*nvc0
)
73 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
74 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
76 unsigned ms_mode
= NVC0_3D_MULTISAMPLE_MODE_MS1
;
77 bool serialize
= false;
79 nouveau_bufctx_reset(nvc0
->bufctx_3d
, NVC0_BIND_FB
);
81 BEGIN_NVC0(push
, NVC0_3D(RT_CONTROL
), 1);
82 PUSH_DATA (push
, (076543210 << 4) | fb
->nr_cbufs
);
83 BEGIN_NVC0(push
, NVC0_3D(SCREEN_SCISSOR_HORIZ
), 2);
84 PUSH_DATA (push
, fb
->width
<< 16);
85 PUSH_DATA (push
, fb
->height
<< 16);
87 for (i
= 0; i
< fb
->nr_cbufs
; ++i
) {
88 struct nv50_surface
*sf
;
89 struct nv04_resource
*res
;
90 struct nouveau_bo
*bo
;
93 nvc0_fb_set_null_rt(push
, i
);
97 sf
= nv50_surface(fb
->cbufs
[i
]);
98 res
= nv04_resource(sf
->base
.texture
);
101 BEGIN_NVC0(push
, NVC0_3D(RT_ADDRESS_HIGH(i
)), 9);
102 PUSH_DATAh(push
, res
->address
+ sf
->offset
);
103 PUSH_DATA (push
, res
->address
+ sf
->offset
);
104 if (likely(nouveau_bo_memtype(bo
))) {
105 struct nv50_miptree
*mt
= nv50_miptree(sf
->base
.texture
);
107 assert(sf
->base
.texture
->target
!= PIPE_BUFFER
);
109 PUSH_DATA(push
, sf
->width
);
110 PUSH_DATA(push
, sf
->height
);
111 PUSH_DATA(push
, nvc0_format_table
[sf
->base
.format
].rt
);
112 PUSH_DATA(push
, (mt
->layout_3d
<< 16) |
113 mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
114 PUSH_DATA(push
, sf
->base
.u
.tex
.first_layer
+ sf
->depth
);
115 PUSH_DATA(push
, mt
->layer_stride
>> 2);
116 PUSH_DATA(push
, sf
->base
.u
.tex
.first_layer
);
118 ms_mode
= mt
->ms_mode
;
120 if (res
->base
.target
== PIPE_BUFFER
) {
121 PUSH_DATA(push
, 262144);
124 PUSH_DATA(push
, nv50_miptree(sf
->base
.texture
)->level
[0].pitch
);
125 PUSH_DATA(push
, sf
->height
);
127 PUSH_DATA(push
, nvc0_format_table
[sf
->base
.format
].rt
);
128 PUSH_DATA(push
, 1 << 12);
133 nvc0_resource_fence(res
, NOUVEAU_BO_WR
);
138 if (res
->status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
140 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
141 res
->status
&= ~NOUVEAU_BUFFER_STATUS_GPU_READING
;
143 /* only register for writing, otherwise we'd always serialize here */
144 BCTX_REFN(nvc0
->bufctx_3d
, FB
, res
, WR
);
148 struct nv50_miptree
*mt
= nv50_miptree(fb
->zsbuf
->texture
);
149 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
150 int unk
= mt
->base
.base
.target
== PIPE_TEXTURE_2D
;
152 BEGIN_NVC0(push
, NVC0_3D(ZETA_ADDRESS_HIGH
), 5);
153 PUSH_DATAh(push
, mt
->base
.address
+ sf
->offset
);
154 PUSH_DATA (push
, mt
->base
.address
+ sf
->offset
);
155 PUSH_DATA (push
, nvc0_format_table
[fb
->zsbuf
->format
].rt
);
156 PUSH_DATA (push
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
157 PUSH_DATA (push
, mt
->layer_stride
>> 2);
158 BEGIN_NVC0(push
, NVC0_3D(ZETA_ENABLE
), 1);
160 BEGIN_NVC0(push
, NVC0_3D(ZETA_HORIZ
), 3);
161 PUSH_DATA (push
, sf
->width
);
162 PUSH_DATA (push
, sf
->height
);
163 PUSH_DATA (push
, (unk
<< 16) |
164 (sf
->base
.u
.tex
.first_layer
+ sf
->depth
));
165 BEGIN_NVC0(push
, NVC0_3D(ZETA_BASE_LAYER
), 1);
166 PUSH_DATA (push
, sf
->base
.u
.tex
.first_layer
);
168 ms_mode
= mt
->ms_mode
;
170 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
172 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
173 mt
->base
.status
&= ~NOUVEAU_BUFFER_STATUS_GPU_READING
;
175 BCTX_REFN(nvc0
->bufctx_3d
, FB
, &mt
->base
, WR
);
177 BEGIN_NVC0(push
, NVC0_3D(ZETA_ENABLE
), 1);
181 IMMED_NVC0(push
, NVC0_3D(MULTISAMPLE_MODE
), ms_mode
);
184 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
185 PUSH_DATA (push
, 1024);
186 PUSH_DATAh(push
, nvc0
->screen
->uniform_bo
->offset
+ (5 << 16) + (4 << 10));
187 PUSH_DATA (push
, nvc0
->screen
->uniform_bo
->offset
+ (5 << 16) + (4 << 10));
188 BEGIN_1IC0(push
, NVC0_3D(CB_POS
), 1 + 2 * ms
);
189 PUSH_DATA (push
, 256 + 128);
190 for (i
= 0; i
< ms
; i
++) {
192 nvc0
->base
.pipe
.get_sample_position(&nvc0
->base
.pipe
, ms
, i
, xy
);
193 PUSH_DATAf(push
, xy
[0]);
194 PUSH_DATAf(push
, xy
[1]);
198 IMMED_NVC0(push
, NVC0_3D(SERIALIZE
), 0);
200 NOUVEAU_DRV_STAT(&nvc0
->screen
->base
, gpu_serialize_count
, serialize
);
204 nvc0_validate_blend_colour(struct nvc0_context
*nvc0
)
206 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
208 BEGIN_NVC0(push
, NVC0_3D(BLEND_COLOR(0)), 4);
209 PUSH_DATAf(push
, nvc0
->blend_colour
.color
[0]);
210 PUSH_DATAf(push
, nvc0
->blend_colour
.color
[1]);
211 PUSH_DATAf(push
, nvc0
->blend_colour
.color
[2]);
212 PUSH_DATAf(push
, nvc0
->blend_colour
.color
[3]);
216 nvc0_validate_stencil_ref(struct nvc0_context
*nvc0
)
218 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
219 const ubyte
*ref
= &nvc0
->stencil_ref
.ref_value
[0];
221 IMMED_NVC0(push
, NVC0_3D(STENCIL_FRONT_FUNC_REF
), ref
[0]);
222 IMMED_NVC0(push
, NVC0_3D(STENCIL_BACK_FUNC_REF
), ref
[1]);
226 nvc0_validate_stipple(struct nvc0_context
*nvc0
)
228 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
231 BEGIN_NVC0(push
, NVC0_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
232 for (i
= 0; i
< 32; ++i
)
233 PUSH_DATA(push
, util_bswap32(nvc0
->stipple
.stipple
[i
]));
237 nvc0_validate_scissor(struct nvc0_context
*nvc0
)
240 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
242 if (!(nvc0
->dirty
& NVC0_NEW_SCISSOR
) &&
243 nvc0
->rast
->pipe
.scissor
== nvc0
->state
.scissor
)
246 if (nvc0
->state
.scissor
!= nvc0
->rast
->pipe
.scissor
)
247 nvc0
->scissors_dirty
= (1 << NVC0_MAX_VIEWPORTS
) - 1;
249 nvc0
->state
.scissor
= nvc0
->rast
->pipe
.scissor
;
251 for (i
= 0; i
< NVC0_MAX_VIEWPORTS
; i
++) {
252 struct pipe_scissor_state
*s
= &nvc0
->scissors
[i
];
253 if (!(nvc0
->scissors_dirty
& (1 << i
)))
256 BEGIN_NVC0(push
, NVC0_3D(SCISSOR_HORIZ(i
)), 2);
257 if (nvc0
->rast
->pipe
.scissor
) {
258 PUSH_DATA(push
, (s
->maxx
<< 16) | s
->minx
);
259 PUSH_DATA(push
, (s
->maxy
<< 16) | s
->miny
);
261 PUSH_DATA(push
, (0xffff << 16) | 0);
262 PUSH_DATA(push
, (0xffff << 16) | 0);
265 nvc0
->scissors_dirty
= 0;
269 nvc0_validate_viewport(struct nvc0_context
*nvc0
)
271 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
275 for (i
= 0; i
< NVC0_MAX_VIEWPORTS
; i
++) {
276 struct pipe_viewport_state
*vp
= &nvc0
->viewports
[i
];
278 if (!(nvc0
->viewports_dirty
& (1 << i
)))
281 BEGIN_NVC0(push
, NVC0_3D(VIEWPORT_TRANSLATE_X(i
)), 3);
282 PUSH_DATAf(push
, vp
->translate
[0]);
283 PUSH_DATAf(push
, vp
->translate
[1]);
284 PUSH_DATAf(push
, vp
->translate
[2]);
286 BEGIN_NVC0(push
, NVC0_3D(VIEWPORT_SCALE_X(i
)), 3);
287 PUSH_DATAf(push
, vp
->scale
[0]);
288 PUSH_DATAf(push
, vp
->scale
[1]);
289 PUSH_DATAf(push
, vp
->scale
[2]);
291 /* now set the viewport rectangle to viewport dimensions for clipping */
293 x
= util_iround(MAX2(0.0f
, vp
->translate
[0] - fabsf(vp
->scale
[0])));
294 y
= util_iround(MAX2(0.0f
, vp
->translate
[1] - fabsf(vp
->scale
[1])));
295 w
= util_iround(vp
->translate
[0] + fabsf(vp
->scale
[0])) - x
;
296 h
= util_iround(vp
->translate
[1] + fabsf(vp
->scale
[1])) - y
;
298 BEGIN_NVC0(push
, NVC0_3D(VIEWPORT_HORIZ(i
)), 2);
299 PUSH_DATA (push
, (w
<< 16) | x
);
300 PUSH_DATA (push
, (h
<< 16) | y
);
302 zmin
= vp
->translate
[2] - fabsf(vp
->scale
[2]);
303 zmax
= vp
->translate
[2] + fabsf(vp
->scale
[2]);
305 BEGIN_NVC0(push
, NVC0_3D(DEPTH_RANGE_NEAR(i
)), 2);
306 PUSH_DATAf(push
, zmin
);
307 PUSH_DATAf(push
, zmax
);
309 nvc0
->viewports_dirty
= 0;
313 nvc0_upload_uclip_planes(struct nvc0_context
*nvc0
, unsigned s
)
315 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
316 struct nouveau_bo
*bo
= nvc0
->screen
->uniform_bo
;
318 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
319 PUSH_DATA (push
, 1024);
320 PUSH_DATAh(push
, bo
->offset
+ (5 << 16) + (s
<< 10));
321 PUSH_DATA (push
, bo
->offset
+ (5 << 16) + (s
<< 10));
322 BEGIN_1IC0(push
, NVC0_3D(CB_POS
), PIPE_MAX_CLIP_PLANES
* 4 + 1);
323 PUSH_DATA (push
, 256);
324 PUSH_DATAp(push
, &nvc0
->clip
.ucp
[0][0], PIPE_MAX_CLIP_PLANES
* 4);
328 nvc0_check_program_ucps(struct nvc0_context
*nvc0
,
329 struct nvc0_program
*vp
, uint8_t mask
)
331 const unsigned n
= util_logbase2(mask
) + 1;
333 if (vp
->vp
.num_ucps
>= n
)
335 nvc0_program_destroy(nvc0
, vp
);
338 if (likely(vp
== nvc0
->vertprog
))
339 nvc0_vertprog_validate(nvc0
);
341 if (likely(vp
== nvc0
->gmtyprog
))
342 nvc0_gmtyprog_validate(nvc0
);
344 nvc0_tevlprog_validate(nvc0
);
348 nvc0_validate_clip(struct nvc0_context
*nvc0
)
350 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
351 struct nvc0_program
*vp
;
353 uint8_t clip_enable
= nvc0
->rast
->pipe
.clip_plane_enable
;
355 if (nvc0
->gmtyprog
) {
359 if (nvc0
->tevlprog
) {
367 if (clip_enable
&& vp
->vp
.num_ucps
< PIPE_MAX_CLIP_PLANES
)
368 nvc0_check_program_ucps(nvc0
, vp
, clip_enable
);
370 if (nvc0
->dirty
& (NVC0_NEW_CLIP
| (NVC0_NEW_VERTPROG
<< stage
)))
371 if (vp
->vp
.num_ucps
> 0 && vp
->vp
.num_ucps
<= PIPE_MAX_CLIP_PLANES
)
372 nvc0_upload_uclip_planes(nvc0
, stage
);
374 clip_enable
&= vp
->vp
.clip_enable
;
376 if (nvc0
->state
.clip_enable
!= clip_enable
) {
377 nvc0
->state
.clip_enable
= clip_enable
;
378 IMMED_NVC0(push
, NVC0_3D(CLIP_DISTANCE_ENABLE
), clip_enable
);
380 if (nvc0
->state
.clip_mode
!= vp
->vp
.clip_mode
) {
381 nvc0
->state
.clip_mode
= vp
->vp
.clip_mode
;
382 BEGIN_NVC0(push
, NVC0_3D(CLIP_DISTANCE_MODE
), 1);
383 PUSH_DATA (push
, vp
->vp
.clip_mode
);
388 nvc0_validate_blend(struct nvc0_context
*nvc0
)
390 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
392 PUSH_SPACE(push
, nvc0
->blend
->size
);
393 PUSH_DATAp(push
, nvc0
->blend
->state
, nvc0
->blend
->size
);
397 nvc0_validate_zsa(struct nvc0_context
*nvc0
)
399 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
401 PUSH_SPACE(push
, nvc0
->zsa
->size
);
402 PUSH_DATAp(push
, nvc0
->zsa
->state
, nvc0
->zsa
->size
);
406 nvc0_validate_rasterizer(struct nvc0_context
*nvc0
)
408 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
410 PUSH_SPACE(push
, nvc0
->rast
->size
);
411 PUSH_DATAp(push
, nvc0
->rast
->state
, nvc0
->rast
->size
);
415 nvc0_constbufs_validate(struct nvc0_context
*nvc0
)
417 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
420 for (s
= 0; s
< 5; ++s
) {
421 while (nvc0
->constbuf_dirty
[s
]) {
422 int i
= ffs(nvc0
->constbuf_dirty
[s
]) - 1;
423 nvc0
->constbuf_dirty
[s
] &= ~(1 << i
);
425 if (nvc0
->constbuf
[s
][i
].user
) {
426 struct nouveau_bo
*bo
= nvc0
->screen
->uniform_bo
;
427 const unsigned base
= s
<< 16;
428 const unsigned size
= nvc0
->constbuf
[s
][0].size
;
429 assert(i
== 0); /* we really only want OpenGL uniforms here */
430 assert(nvc0
->constbuf
[s
][0].u
.data
);
432 if (nvc0
->state
.uniform_buffer_bound
[s
] < size
) {
433 nvc0
->state
.uniform_buffer_bound
[s
] = align(size
, 0x100);
435 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
436 PUSH_DATA (push
, nvc0
->state
.uniform_buffer_bound
[s
]);
437 PUSH_DATAh(push
, bo
->offset
+ base
);
438 PUSH_DATA (push
, bo
->offset
+ base
);
439 BEGIN_NVC0(push
, NVC0_3D(CB_BIND(s
)), 1);
440 PUSH_DATA (push
, (0 << 4) | 1);
442 nvc0_cb_bo_push(&nvc0
->base
, bo
, NV_VRAM_DOMAIN(&nvc0
->screen
->base
),
443 base
, nvc0
->state
.uniform_buffer_bound
[s
],
445 nvc0
->constbuf
[s
][0].u
.data
);
447 struct nv04_resource
*res
=
448 nv04_resource(nvc0
->constbuf
[s
][i
].u
.buf
);
450 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
451 PUSH_DATA (push
, nvc0
->constbuf
[s
][i
].size
);
452 PUSH_DATAh(push
, res
->address
+ nvc0
->constbuf
[s
][i
].offset
);
453 PUSH_DATA (push
, res
->address
+ nvc0
->constbuf
[s
][i
].offset
);
454 BEGIN_NVC0(push
, NVC0_3D(CB_BIND(s
)), 1);
455 PUSH_DATA (push
, (i
<< 4) | 1);
457 BCTX_REFN(nvc0
->bufctx_3d
, CB(s
, i
), res
, RD
);
459 nvc0
->cb_dirty
= 1; /* Force cache flush for UBO. */
460 res
->cb_bindings
[s
] |= 1 << i
;
462 BEGIN_NVC0(push
, NVC0_3D(CB_BIND(s
)), 1);
463 PUSH_DATA (push
, (i
<< 4) | 0);
466 nvc0
->state
.uniform_buffer_bound
[s
] = 0;
473 nvc0_validate_buffers(struct nvc0_context
*nvc0
)
475 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
478 for (s
= 0; s
< 5; s
++) {
479 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
480 PUSH_DATA (push
, 1024);
481 PUSH_DATAh(push
, nvc0
->screen
->uniform_bo
->offset
+ (5 << 16) + (s
<< 10));
482 PUSH_DATA (push
, nvc0
->screen
->uniform_bo
->offset
+ (5 << 16) + (s
<< 10));
483 BEGIN_1IC0(push
, NVC0_3D(CB_POS
), 1 + 4 * NVC0_MAX_BUFFERS
);
484 PUSH_DATA (push
, 512);
485 for (i
= 0; i
< NVC0_MAX_BUFFERS
; i
++) {
486 if (nvc0
->buffers
[s
][i
].buffer
) {
487 struct nv04_resource
*res
=
488 nv04_resource(nvc0
->buffers
[s
][i
].buffer
);
489 PUSH_DATA (push
, res
->address
+ nvc0
->buffers
[s
][i
].buffer_offset
);
490 PUSH_DATAh(push
, res
->address
+ nvc0
->buffers
[s
][i
].buffer_offset
);
491 PUSH_DATA (push
, nvc0
->buffers
[s
][i
].buffer_size
);
493 BCTX_REFN(nvc0
->bufctx_3d
, BUF
, res
, RDWR
);
506 nvc0_validate_sample_mask(struct nvc0_context
*nvc0
)
508 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
512 nvc0
->sample_mask
& 0xffff,
513 nvc0
->sample_mask
& 0xffff,
514 nvc0
->sample_mask
& 0xffff,
515 nvc0
->sample_mask
& 0xffff
518 BEGIN_NVC0(push
, NVC0_3D(MSAA_MASK(0)), 4);
519 PUSH_DATA (push
, mask
[0]);
520 PUSH_DATA (push
, mask
[1]);
521 PUSH_DATA (push
, mask
[2]);
522 PUSH_DATA (push
, mask
[3]);
526 nvc0_validate_min_samples(struct nvc0_context
*nvc0
)
528 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
531 samples
= util_next_power_of_two(nvc0
->min_samples
);
533 samples
|= NVC0_3D_SAMPLE_SHADING_ENABLE
;
535 IMMED_NVC0(push
, NVC0_3D(SAMPLE_SHADING
), samples
);
539 nvc0_validate_global_residents(struct nvc0_context
*nvc0
,
540 struct nouveau_bufctx
*bctx
, int bin
)
544 for (i
= 0; i
< nvc0
->global_residents
.size
/ sizeof(struct pipe_resource
*);
546 struct pipe_resource
*res
= *util_dynarray_element(
547 &nvc0
->global_residents
, struct pipe_resource
*, i
);
549 nvc0_add_resident(bctx
, bin
, nv04_resource(res
), NOUVEAU_BO_RDWR
);
554 nvc0_validate_derived_1(struct nvc0_context
*nvc0
)
556 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
557 bool rasterizer_discard
;
559 if (nvc0
->rast
&& nvc0
->rast
->pipe
.rasterizer_discard
) {
560 rasterizer_discard
= true;
562 bool zs
= nvc0
->zsa
&&
563 (nvc0
->zsa
->pipe
.depth
.enabled
|| nvc0
->zsa
->pipe
.stencil
[0].enabled
);
564 rasterizer_discard
= !zs
&&
565 (!nvc0
->fragprog
|| !nvc0
->fragprog
->hdr
[18]);
568 if (rasterizer_discard
!= nvc0
->state
.rasterizer_discard
) {
569 nvc0
->state
.rasterizer_discard
= rasterizer_discard
;
570 IMMED_NVC0(push
, NVC0_3D(RASTERIZE_ENABLE
), !rasterizer_discard
);
574 /* alpha test is disabled if there are no color RTs, so make sure we have at
575 * least one if alpha test is enabled. Note that this must run after
576 * nvc0_validate_fb, otherwise that will override the RT count setting.
579 nvc0_validate_derived_2(struct nvc0_context
*nvc0
)
581 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
583 if (nvc0
->zsa
&& nvc0
->zsa
->pipe
.alpha
.enabled
&&
584 nvc0
->framebuffer
.nr_cbufs
== 0) {
585 nvc0_fb_set_null_rt(push
, 0);
586 BEGIN_NVC0(push
, NVC0_3D(RT_CONTROL
), 1);
587 PUSH_DATA (push
, (076543210 << 4) | 1);
592 nvc0_validate_derived_3(struct nvc0_context
*nvc0
)
594 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
595 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
598 if ((!fb
->nr_cbufs
|| !fb
->cbufs
[0] ||
599 !util_format_is_pure_integer(fb
->cbufs
[0]->format
)) && nvc0
->blend
) {
600 if (nvc0
->blend
->pipe
.alpha_to_coverage
)
601 ms
|= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE
;
602 if (nvc0
->blend
->pipe
.alpha_to_one
)
603 ms
|= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE
;
606 BEGIN_NVC0(push
, NVC0_3D(MULTISAMPLE_CTRL
), 1);
607 PUSH_DATA (push
, ms
);
611 nvc0_validate_tess_state(struct nvc0_context
*nvc0
)
613 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
615 BEGIN_NVC0(push
, NVC0_3D(TESS_LEVEL_OUTER(0)), 6);
616 PUSH_DATAp(push
, nvc0
->default_tess_outer
, 4);
617 PUSH_DATAp(push
, nvc0
->default_tess_inner
, 2);
621 nvc0_switch_pipe_context(struct nvc0_context
*ctx_to
)
623 struct nvc0_context
*ctx_from
= ctx_to
->screen
->cur_ctx
;
627 ctx_to
->state
= ctx_from
->state
;
629 ctx_to
->state
= ctx_to
->screen
->save_state
;
632 ctx_to
->viewports_dirty
= ~0;
633 ctx_to
->scissors_dirty
= ~0;
635 for (s
= 0; s
< 5; ++s
) {
636 ctx_to
->samplers_dirty
[s
] = ~0;
637 ctx_to
->textures_dirty
[s
] = ~0;
638 ctx_to
->constbuf_dirty
[s
] = (1 << NVC0_MAX_PIPE_CONSTBUFS
) - 1;
641 /* Reset tfb as the shader that owns it may have been deleted. */
642 ctx_to
->state
.tfb
= NULL
;
645 ctx_to
->dirty
&= ~(NVC0_NEW_VERTEX
| NVC0_NEW_ARRAYS
);
646 if (!ctx_to
->idxbuf
.buffer
)
647 ctx_to
->dirty
&= ~NVC0_NEW_IDXBUF
;
649 if (!ctx_to
->vertprog
)
650 ctx_to
->dirty
&= ~NVC0_NEW_VERTPROG
;
651 if (!ctx_to
->fragprog
)
652 ctx_to
->dirty
&= ~NVC0_NEW_FRAGPROG
;
655 ctx_to
->dirty
&= ~NVC0_NEW_BLEND
;
657 ctx_to
->dirty
&= ~(NVC0_NEW_RASTERIZER
| NVC0_NEW_SCISSOR
);
659 ctx_to
->dirty
&= ~NVC0_NEW_ZSA
;
661 ctx_to
->screen
->cur_ctx
= ctx_to
;
664 static struct state_validate
{
665 void (*func
)(struct nvc0_context
*);
667 } validate_list
[] = {
668 { nvc0_validate_fb
, NVC0_NEW_FRAMEBUFFER
},
669 { nvc0_validate_blend
, NVC0_NEW_BLEND
},
670 { nvc0_validate_zsa
, NVC0_NEW_ZSA
},
671 { nvc0_validate_sample_mask
, NVC0_NEW_SAMPLE_MASK
},
672 { nvc0_validate_rasterizer
, NVC0_NEW_RASTERIZER
},
673 { nvc0_validate_blend_colour
, NVC0_NEW_BLEND_COLOUR
},
674 { nvc0_validate_stencil_ref
, NVC0_NEW_STENCIL_REF
},
675 { nvc0_validate_stipple
, NVC0_NEW_STIPPLE
},
676 { nvc0_validate_scissor
, NVC0_NEW_SCISSOR
| NVC0_NEW_RASTERIZER
},
677 { nvc0_validate_viewport
, NVC0_NEW_VIEWPORT
},
678 { nvc0_vertprog_validate
, NVC0_NEW_VERTPROG
},
679 { nvc0_tctlprog_validate
, NVC0_NEW_TCTLPROG
},
680 { nvc0_tevlprog_validate
, NVC0_NEW_TEVLPROG
},
681 { nvc0_validate_tess_state
, NVC0_NEW_TESSFACTOR
},
682 { nvc0_gmtyprog_validate
, NVC0_NEW_GMTYPROG
},
683 { nvc0_fragprog_validate
, NVC0_NEW_FRAGPROG
| NVC0_NEW_RASTERIZER
},
684 { nvc0_validate_derived_1
, NVC0_NEW_FRAGPROG
| NVC0_NEW_ZSA
|
685 NVC0_NEW_RASTERIZER
},
686 { nvc0_validate_derived_2
, NVC0_NEW_ZSA
| NVC0_NEW_FRAMEBUFFER
},
687 { nvc0_validate_derived_3
, NVC0_NEW_BLEND
| NVC0_NEW_FRAMEBUFFER
},
688 { nvc0_validate_clip
, NVC0_NEW_CLIP
| NVC0_NEW_RASTERIZER
|
692 { nvc0_constbufs_validate
, NVC0_NEW_CONSTBUF
},
693 { nvc0_validate_textures
, NVC0_NEW_TEXTURES
},
694 { nvc0_validate_samplers
, NVC0_NEW_SAMPLERS
},
695 { nve4_set_tex_handles
, NVC0_NEW_TEXTURES
| NVC0_NEW_SAMPLERS
},
696 { nvc0_vertex_arrays_validate
, NVC0_NEW_VERTEX
| NVC0_NEW_ARRAYS
},
697 { nvc0_validate_surfaces
, NVC0_NEW_SURFACES
},
698 { nvc0_validate_buffers
, NVC0_NEW_BUFFERS
},
699 { nvc0_idxbuf_validate
, NVC0_NEW_IDXBUF
},
700 { nvc0_tfb_validate
, NVC0_NEW_TFB_TARGETS
| NVC0_NEW_GMTYPROG
},
701 { nvc0_validate_min_samples
, NVC0_NEW_MIN_SAMPLES
},
705 nvc0_state_validate(struct nvc0_context
*nvc0
, uint32_t mask
)
711 if (nvc0
->screen
->cur_ctx
!= nvc0
)
712 nvc0_switch_pipe_context(nvc0
);
714 state_mask
= nvc0
->dirty
& mask
;
717 for (i
= 0; i
< ARRAY_SIZE(validate_list
); ++i
) {
718 struct state_validate
*validate
= &validate_list
[i
];
720 if (state_mask
& validate
->states
)
721 validate
->func(nvc0
);
723 nvc0
->dirty
&= ~state_mask
;
725 nvc0_bufctx_fence(nvc0
, nvc0
->bufctx_3d
, false);
728 nouveau_pushbuf_bufctx(nvc0
->base
.pushbuf
, nvc0
->bufctx_3d
);
729 ret
= nouveau_pushbuf_validate(nvc0
->base
.pushbuf
);
731 if (unlikely(nvc0
->state
.flushed
)) {
732 nvc0
->state
.flushed
= false;
733 nvc0_bufctx_fence(nvc0
, nvc0
->bufctx_3d
, true);