Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c
4574 views
1
2
#include "util/u_viewport.h"
3
4
#include "nv50/nv50_context.h"
5
6
static inline void
7
nv50_fb_set_null_rt(struct nouveau_pushbuf *push, unsigned i)
8
{
9
BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(i)), 4);
10
PUSH_DATA (push, 0);
11
PUSH_DATA (push, 0);
12
PUSH_DATA (push, 0);
13
PUSH_DATA (push, 0);
14
BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);
15
PUSH_DATA (push, 64);
16
PUSH_DATA (push, 0);
17
}
18
19
static void
20
nv50_validate_fb(struct nv50_context *nv50)
21
{
22
struct nouveau_pushbuf *push = nv50->base.pushbuf;
23
struct pipe_framebuffer_state *fb = &nv50->framebuffer;
24
unsigned i;
25
unsigned ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1;
26
uint32_t array_size = 0xffff, array_mode = 0;
27
28
nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_FB);
29
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);
35
36
for (i = 0; i < fb->nr_cbufs; ++i) {
37
struct nv50_miptree *mt;
38
struct nv50_surface *sf;
39
struct nouveau_bo *bo;
40
41
if (!fb->cbufs[i]) {
42
nv50_fb_set_null_rt(push, i);
43
continue;
44
}
45
46
mt = nv50_miptree(fb->cbufs[i]->texture);
47
sf = nv50_surface(fb->cbufs[i]);
48
bo = mt->base.bo;
49
50
array_size = MIN2(array_size, sf->depth);
51
if (mt->layout_3d)
52
array_mode = NV50_3D_RT_ARRAY_MODE_MODE_3D; /* 1 << 16 */
53
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);
56
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);
63
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;
72
} else {
73
PUSH_DATA (push, 0);
74
PUSH_DATA (push, 0);
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);
79
PUSH_DATA (push, 0);
80
81
assert(!fb->zsbuf);
82
assert(!mt->ms_mode);
83
}
84
85
ms_mode = mt->ms_mode;
86
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;
91
92
/* only register for writing, otherwise we'd always serialize here */
93
BCTX_REFN(nv50->bufctx_3d, 3D_FB, &mt->base, WR);
94
}
95
96
if (fb->zsbuf) {
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;
100
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);
108
PUSH_DATA (push, 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);
113
114
ms_mode = mt->ms_mode;
115
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;
120
121
BCTX_REFN(nv50->bufctx_3d, 3D_FB, &mt->base, WR);
122
} else {
123
BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
124
PUSH_DATA (push, 0);
125
}
126
127
BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);
128
PUSH_DATA (push, ms_mode);
129
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);
134
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++) {
141
float xy[2];
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]);
145
}
146
}
147
}
148
149
static void
150
nv50_validate_blend_colour(struct nv50_context *nv50)
151
{
152
struct nouveau_pushbuf *push = nv50->base.pushbuf;
153
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]);
159
}
160
161
static void
162
nv50_validate_stencil_ref(struct nv50_context *nv50)
163
{
164
struct nouveau_pushbuf *push = nv50->base.pushbuf;
165
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]);
170
}
171
172
static void
173
nv50_validate_stipple(struct nv50_context *nv50)
174
{
175
struct nouveau_pushbuf *push = nv50->base.pushbuf;
176
unsigned i;
177
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]));
181
}
182
183
static void
184
nv50_validate_scissor(struct nv50_context *nv50)
185
{
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;
190
191
if (!(nv50->dirty_3d &
192
(NV50_NEW_3D_SCISSOR | NV50_NEW_3D_VIEWPORT | NV50_NEW_3D_FRAMEBUFFER)) &&
193
nv50->state.scissor == rast_scissor)
194
return;
195
196
if (nv50->state.scissor != rast_scissor)
197
nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;
198
199
nv50->state.scissor = rast_scissor;
200
201
if ((nv50->dirty_3d & NV50_NEW_3D_FRAMEBUFFER) && !nv50->state.scissor)
202
nv50->scissors_dirty = (1 << NV50_MAX_VIEWPORTS) - 1;
203
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];
207
208
if (!(nv50->scissors_dirty & (1 << i)) &&
209
!(nv50->viewports_dirty & (1 << i)))
210
continue;
211
212
if (nv50->state.scissor) {
213
minx = s->minx;
214
maxx = s->maxx;
215
miny = s->miny;
216
maxy = s->maxy;
217
} else {
218
minx = 0;
219
maxx = nv50->framebuffer.width;
220
miny = 0;
221
maxy = nv50->framebuffer.height;
222
}
223
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])));
228
229
minx = MIN2(minx, 8192);
230
maxx = MAX2(maxx, 0);
231
miny = MIN2(miny, 8192);
232
maxy = MAX2(maxy, 0);
233
234
BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(i)), 2);
235
PUSH_DATA (push, (maxx << 16) | minx);
236
PUSH_DATA (push, (maxy << 16) | miny);
237
#else
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);
241
#endif
242
}
243
244
nv50->scissors_dirty = 0;
245
}
246
247
static void
248
nv50_validate_viewport(struct nv50_context *nv50)
249
{
250
struct nouveau_pushbuf *push = nv50->base.pushbuf;
251
float zmin, zmax;
252
int i;
253
254
for (i = 0; i < NV50_MAX_VIEWPORTS; i++) {
255
struct pipe_viewport_state *vpt = &nv50->viewports[i];
256
257
if (!(nv50->viewports_dirty & (1 << i)))
258
continue;
259
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]);
268
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
272
* dependency.
273
*/
274
util_viewport_zmin_zmax(vpt, nv50->rast->pipe.clip_halfz, &zmin, &zmax);
275
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);
280
#endif
281
}
282
283
nv50->viewports_dirty = 0;
284
}
285
286
static void
287
nv50_validate_window_rects(struct nv50_context *nv50)
288
{
289
struct nouveau_pushbuf *push = nv50->base.pushbuf;
290
bool enable = nv50->window_rect.rects > 0 || nv50->window_rect.inclusive;
291
int i;
292
293
BEGIN_NV04(push, NV50_3D(CLIP_RECTS_EN), 1);
294
PUSH_DATA (push, enable);
295
if (!enable)
296
return;
297
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);
305
}
306
for (; i < NV50_MAX_WINDOW_RECTANGLES; i++) {
307
PUSH_DATA(push, 0);
308
PUSH_DATA(push, 0);
309
}
310
}
311
312
static inline void
313
nv50_check_program_ucps(struct nv50_context *nv50,
314
struct nv50_program *vp, uint8_t mask)
315
{
316
const unsigned n = util_logbase2(mask) + 1;
317
318
if (vp->vp.clpd_nr >= n)
319
return;
320
nv50_program_destroy(nv50, vp);
321
322
vp->vp.clpd_nr = n;
323
if (likely(vp == nv50->vertprog)) {
324
nv50->dirty_3d |= NV50_NEW_3D_VERTPROG;
325
nv50_vertprog_validate(nv50);
326
} else {
327
nv50->dirty_3d |= NV50_NEW_3D_GMTYPROG;
328
nv50_gmtyprog_validate(nv50);
329
}
330
nv50_fp_linkage_validate(nv50);
331
}
332
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.
336
*/
337
static void
338
nv50_validate_derived_2(struct nv50_context *nv50)
339
{
340
struct nouveau_pushbuf *push = nv50->base.pushbuf;
341
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);
347
}
348
}
349
350
static void
351
nv50_validate_clip(struct nv50_context *nv50)
352
{
353
struct nouveau_pushbuf *push = nv50->base.pushbuf;
354
struct nv50_program *vp;
355
uint8_t clip_enable = nv50->rast->pipe.clip_plane_enable;
356
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 - 2) | 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);
362
}
363
364
vp = nv50->gmtyprog;
365
if (likely(!vp))
366
vp = nv50->vertprog;
367
368
if (clip_enable)
369
nv50_check_program_ucps(nv50, vp, clip_enable);
370
371
clip_enable &= vp->vp.clip_enable;
372
clip_enable |= vp->vp.cull_enable;
373
374
BEGIN_NV04(push, NV50_3D(CLIP_DISTANCE_ENABLE), 1);
375
PUSH_DATA (push, clip_enable);
376
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);
381
}
382
}
383
384
static void
385
nv50_validate_blend(struct nv50_context *nv50)
386
{
387
struct nouveau_pushbuf *push = nv50->base.pushbuf;
388
389
PUSH_SPACE(push, nv50->blend->size);
390
PUSH_DATAp(push, nv50->blend->state, nv50->blend->size);
391
}
392
393
static void
394
nv50_validate_zsa(struct nv50_context *nv50)
395
{
396
struct nouveau_pushbuf *push = nv50->base.pushbuf;
397
398
PUSH_SPACE(push, nv50->zsa->size);
399
PUSH_DATAp(push, nv50->zsa->state, nv50->zsa->size);
400
}
401
402
static void
403
nv50_validate_rasterizer(struct nv50_context *nv50)
404
{
405
struct nouveau_pushbuf *push = nv50->base.pushbuf;
406
407
PUSH_SPACE(push, nv50->rast->size);
408
PUSH_DATAp(push, nv50->rast->state, nv50->rast->size);
409
}
410
411
static void
412
nv50_validate_sample_mask(struct nv50_context *nv50)
413
{
414
struct nouveau_pushbuf *push = nv50->base.pushbuf;
415
416
unsigned mask[4] =
417
{
418
nv50->sample_mask & 0xffff,
419
nv50->sample_mask & 0xffff,
420
nv50->sample_mask & 0xffff,
421
nv50->sample_mask & 0xffff
422
};
423
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]);
429
}
430
431
static void
432
nv50_validate_min_samples(struct nv50_context *nv50)
433
{
434
struct nouveau_pushbuf *push = nv50->base.pushbuf;
435
int samples;
436
437
if (nv50->screen->tesla->oclass < NVA3_3D_CLASS)
438
return;
439
440
samples = util_next_power_of_two(nv50->min_samples);
441
if (samples > 1)
442
samples |= NVA3_3D_SAMPLE_SHADING_ENABLE;
443
444
BEGIN_NV04(push, SUBC_3D(NVA3_3D_SAMPLE_SHADING), 1);
445
PUSH_DATA (push, samples);
446
}
447
448
static void
449
nv50_switch_pipe_context(struct nv50_context *ctx_to)
450
{
451
struct nv50_context *ctx_from = ctx_to->screen->cur_ctx;
452
453
if (ctx_from)
454
ctx_to->state = ctx_from->state;
455
else
456
ctx_to->state = ctx_to->screen->save_state;
457
458
ctx_to->dirty_3d = ~0;
459
ctx_to->dirty_cp = ~0;
460
ctx_to->viewports_dirty = ~0;
461
ctx_to->scissors_dirty = ~0;
462
463
ctx_to->constbuf_dirty[NV50_SHADER_STAGE_VERTEX] =
464
ctx_to->constbuf_dirty[NV50_SHADER_STAGE_GEOMETRY] =
465
ctx_to->constbuf_dirty[NV50_SHADER_STAGE_FRAGMENT] = (1 << NV50_MAX_PIPE_CONSTBUFS) - 1;
466
467
if (!ctx_to->vertex)
468
ctx_to->dirty_3d &= ~(NV50_NEW_3D_VERTEX | NV50_NEW_3D_ARRAYS);
469
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;
474
475
if (!ctx_to->blend)
476
ctx_to->dirty_3d &= ~NV50_NEW_3D_BLEND;
477
if (!ctx_to->rast)
478
#ifdef NV50_SCISSORS_CLIPPING
479
ctx_to->dirty_3d &= ~(NV50_NEW_3D_RASTERIZER | NV50_NEW_3D_SCISSOR);
480
#else
481
ctx_to->dirty_3d &= ~NV50_NEW_3D_RASTERIZER;
482
#endif
483
if (!ctx_to->zsa)
484
ctx_to->dirty_3d &= ~NV50_NEW_3D_ZSA;
485
486
ctx_to->screen->cur_ctx = ctx_to;
487
}
488
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 },
503
#else
504
{ nv50_validate_scissor, NV50_NEW_3D_SCISSOR },
505
#endif
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 },
528
};
529
530
bool
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)
534
{
535
uint32_t state_mask;
536
int ret;
537
unsigned i;
538
539
if (nv50->screen->cur_ctx != nv50)
540
nv50_switch_pipe_context(nv50);
541
542
state_mask = *dirty & mask;
543
544
if (state_mask) {
545
for (i = 0; i < size; i++) {
546
struct nv50_state_validate *validate = &validate_list[i];
547
548
if (state_mask & validate->states)
549
validate->func(nv50);
550
}
551
*dirty &= ~state_mask;
552
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);
557
}
558
559
nv50_bufctx_fence(bufctx, false);
560
}
561
nouveau_pushbuf_bufctx(nv50->base.pushbuf, bufctx);
562
ret = nouveau_pushbuf_validate(nv50->base.pushbuf);
563
564
return !ret;
565
}
566
567
bool
568
nv50_state_validate_3d(struct nv50_context *nv50, uint32_t mask)
569
{
570
bool ret;
571
572
ret = nv50_state_validate(nv50, mask, validate_list_3d,
573
ARRAY_SIZE(validate_list_3d), &nv50->dirty_3d,
574
nv50->bufctx_3d);
575
576
if (unlikely(nv50->state.flushed)) {
577
nv50->state.flushed = false;
578
nv50_bufctx_fence(nv50->bufctx_3d, true);
579
}
580
return ret;
581
}
582
583