2 #include "util/u_math.h"
4 #include "nvc0_context.h"
7 nvc0_validate_zcull(struct nvc0_context
*nvc0
)
9 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
10 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
11 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
12 struct nv50_miptree
*mt
= nv50_miptree(sf
->base
.texture
);
13 struct nouveau_bo
*bo
= mt
->base
.bo
;
15 uint32_t offset
= align(mt
->total_size
, 1 << 17);
16 unsigned width
, height
;
18 assert(mt
->base
.base
.depth0
== 1 && mt
->base
.base
.array_size
< 2);
20 size
= mt
->total_size
* 2;
22 height
= align(fb
->height
, 32);
23 width
= fb
->width
% 224;
25 width
= fb
->width
+ (224 - width
);
29 MARK_RING (chan
, 23, 4);
30 BEGIN_RING(chan
, RING_3D_(0x1590), 1); /* ZCULL_REGION_INDEX (bits 0x3f) */
32 BEGIN_RING(chan
, RING_3D_(0x07e8), 2); /* ZCULL_ADDRESS_A_HIGH */
33 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
34 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
36 BEGIN_RING(chan
, RING_3D_(0x07f0), 2); /* ZCULL_ADDRESS_B_HIGH */
37 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
38 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
39 BEGIN_RING(chan
, RING_3D_(0x07e0), 2);
40 OUT_RING (chan
, size
);
41 OUT_RING (chan
, size
>> 16);
42 BEGIN_RING(chan
, RING_3D_(0x15c8), 1); /* bits 0x3 */
44 BEGIN_RING(chan
, RING_3D_(0x07c0), 4); /* ZCULL dimensions */
45 OUT_RING (chan
, width
);
46 OUT_RING (chan
, height
);
49 BEGIN_RING(chan
, RING_3D_(0x15fc), 2);
50 OUT_RING (chan
, 0); /* bits 0xffff */
51 OUT_RING (chan
, 0); /* bits 0xffff */
52 BEGIN_RING(chan
, RING_3D_(0x1958), 1);
53 OUT_RING (chan
, 0); /* bits ~0 */
57 nvc0_validate_fb(struct nvc0_context
*nvc0
)
59 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
60 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
62 unsigned ms_mode
= NVC0_3D_MULTISAMPLE_MODE_MS1
;
63 boolean serialize
= FALSE
;
65 nvc0_bufctx_reset(nvc0
, NVC0_BUFCTX_FRAME
);
67 BEGIN_RING(chan
, RING_3D(RT_CONTROL
), 1);
68 OUT_RING (chan
, (076543210 << 4) | fb
->nr_cbufs
);
69 BEGIN_RING(chan
, RING_3D(SCREEN_SCISSOR_HORIZ
), 2);
70 OUT_RING (chan
, fb
->width
<< 16);
71 OUT_RING (chan
, fb
->height
<< 16);
73 MARK_RING(chan
, 9 * fb
->nr_cbufs
, 2 * fb
->nr_cbufs
);
75 for (i
= 0; i
< fb
->nr_cbufs
; ++i
) {
76 struct nv50_surface
*sf
= nv50_surface(fb
->cbufs
[i
]);
77 struct nv04_resource
*res
= nv04_resource(sf
->base
.texture
);
78 struct nouveau_bo
*bo
= res
->bo
;
79 uint32_t offset
= sf
->offset
+ res
->offset
;
81 BEGIN_RING(chan
, RING_3D(RT_ADDRESS_HIGH(i
)), 9);
82 OUT_RELOCh(chan
, res
->bo
, offset
, res
->domain
| NOUVEAU_BO_RDWR
);
83 OUT_RELOCl(chan
, res
->bo
, offset
, res
->domain
| NOUVEAU_BO_RDWR
);
84 if (likely(nouveau_bo_tile_layout(bo
))) {
85 struct nv50_miptree
*mt
= nv50_miptree(sf
->base
.texture
);
87 assert(sf
->base
.texture
->target
!= PIPE_BUFFER
);
89 OUT_RING(chan
, sf
->width
);
90 OUT_RING(chan
, sf
->height
);
91 OUT_RING(chan
, nvc0_format_table
[sf
->base
.format
].rt
);
92 OUT_RING(chan
, (mt
->layout_3d
<< 16) |
93 mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
94 OUT_RING(chan
, sf
->base
.u
.tex
.first_layer
+ sf
->depth
);
95 OUT_RING(chan
, mt
->layer_stride
>> 2);
96 OUT_RING(chan
, sf
->base
.u
.tex
.first_layer
);
98 ms_mode
= mt
->ms_mode
;
100 if (res
->base
.target
== PIPE_BUFFER
) {
101 OUT_RING(chan
, 262144);
104 OUT_RING(chan
, nv50_miptree(sf
->base
.texture
)->level
[0].pitch
);
105 OUT_RING(chan
, sf
->height
);
107 OUT_RING(chan
, nvc0_format_table
[sf
->base
.format
].rt
);
108 OUT_RING(chan
, 1 << 12);
113 nvc0_resource_fence(res
, NOUVEAU_BO_WR
);
118 if (res
->status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
120 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
121 res
->status
&= ~NOUVEAU_BUFFER_STATUS_GPU_READING
;
123 /* only register for writing, otherwise we'd always serialize here */
124 nvc0_bufctx_add_resident(nvc0
, NVC0_BUFCTX_FRAME
, res
,
125 res
->domain
| NOUVEAU_BO_WR
);
129 struct nv50_miptree
*mt
= nv50_miptree(fb
->zsbuf
->texture
);
130 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
131 struct nouveau_bo
*bo
= mt
->base
.bo
;
132 int unk
= mt
->base
.base
.target
== PIPE_TEXTURE_2D
;
133 uint32_t offset
= sf
->offset
;
135 MARK_RING (chan
, 12, 2);
136 BEGIN_RING(chan
, RING_3D(ZETA_ADDRESS_HIGH
), 5);
137 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
138 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
139 OUT_RING (chan
, nvc0_format_table
[fb
->zsbuf
->format
].rt
);
140 OUT_RING (chan
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
141 OUT_RING (chan
, mt
->layer_stride
>> 2);
142 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
144 BEGIN_RING(chan
, RING_3D(ZETA_HORIZ
), 3);
145 OUT_RING (chan
, sf
->width
);
146 OUT_RING (chan
, sf
->height
);
147 OUT_RING (chan
, (unk
<< 16) |
148 (sf
->base
.u
.tex
.first_layer
+ sf
->depth
));
149 BEGIN_RING(chan
, RING_3D(ZETA_BASE_LAYER
), 1);
150 OUT_RING (chan
, sf
->base
.u
.tex
.first_layer
);
152 ms_mode
= mt
->ms_mode
;
154 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
156 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
157 mt
->base
.status
&= ~NOUVEAU_BUFFER_STATUS_GPU_READING
;
159 nvc0_bufctx_add_resident(nvc0
, NVC0_BUFCTX_FRAME
, &mt
->base
,
160 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
162 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
166 IMMED_RING(chan
, RING_3D(MULTISAMPLE_MODE
), ms_mode
);
169 BEGIN_RING(chan
, RING_3D(SERIALIZE
), 1);
175 nvc0_validate_blend_colour(struct nvc0_context
*nvc0
)
177 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
179 BEGIN_RING(chan
, RING_3D(BLEND_COLOR(0)), 4);
180 OUT_RINGf (chan
, nvc0
->blend_colour
.color
[0]);
181 OUT_RINGf (chan
, nvc0
->blend_colour
.color
[1]);
182 OUT_RINGf (chan
, nvc0
->blend_colour
.color
[2]);
183 OUT_RINGf (chan
, nvc0
->blend_colour
.color
[3]);
187 nvc0_validate_stencil_ref(struct nvc0_context
*nvc0
)
189 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
190 const ubyte
*ref
= &nvc0
->stencil_ref
.ref_value
[0];
192 IMMED_RING(chan
, RING_3D(STENCIL_FRONT_FUNC_REF
), ref
[0]);
193 IMMED_RING(chan
, RING_3D(STENCIL_BACK_FUNC_REF
), ref
[1]);
197 nvc0_validate_stipple(struct nvc0_context
*nvc0
)
199 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
202 BEGIN_RING(chan
, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
203 for (i
= 0; i
< 32; ++i
)
204 OUT_RING(chan
, util_bswap32(nvc0
->stipple
.stipple
[i
]));
208 nvc0_validate_scissor(struct nvc0_context
*nvc0
)
210 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
211 struct pipe_scissor_state
*s
= &nvc0
->scissor
;
213 if (!(nvc0
->dirty
& NVC0_NEW_SCISSOR
) &&
214 nvc0
->rast
->pipe
.scissor
== nvc0
->state
.scissor
)
216 nvc0
->state
.scissor
= nvc0
->rast
->pipe
.scissor
;
218 BEGIN_RING(chan
, RING_3D(SCISSOR_HORIZ(0)), 2);
219 if (nvc0
->rast
->pipe
.scissor
) {
220 OUT_RING(chan
, (s
->maxx
<< 16) | s
->minx
);
221 OUT_RING(chan
, (s
->maxy
<< 16) | s
->miny
);
223 OUT_RING(chan
, (0xffff << 16) | 0);
224 OUT_RING(chan
, (0xffff << 16) | 0);
229 nvc0_validate_viewport(struct nvc0_context
*nvc0
)
231 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
232 struct pipe_viewport_state
*vp
= &nvc0
->viewport
;
236 BEGIN_RING(chan
, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
237 OUT_RINGf (chan
, vp
->translate
[0]);
238 OUT_RINGf (chan
, vp
->translate
[1]);
239 OUT_RINGf (chan
, vp
->translate
[2]);
240 BEGIN_RING(chan
, RING_3D(VIEWPORT_SCALE_X(0)), 3);
241 OUT_RINGf (chan
, vp
->scale
[0]);
242 OUT_RINGf (chan
, vp
->scale
[1]);
243 OUT_RINGf (chan
, vp
->scale
[2]);
245 /* now set the viewport rectangle to viewport dimensions for clipping */
247 x
= util_iround(MAX2(0.0f
, vp
->translate
[0] - fabsf(vp
->scale
[0])));
248 y
= util_iround(MAX2(0.0f
, vp
->translate
[1] - fabsf(vp
->scale
[1])));
249 w
= util_iround(vp
->translate
[0] + fabsf(vp
->scale
[0])) - x
;
250 h
= util_iround(vp
->translate
[1] + fabsf(vp
->scale
[1])) - y
;
252 zmin
= vp
->translate
[2] - fabsf(vp
->scale
[2]);
253 zmax
= vp
->translate
[2] + fabsf(vp
->scale
[2]);
255 BEGIN_RING(chan
, RING_3D(VIEWPORT_HORIZ(0)), 2);
256 OUT_RING (chan
, (w
<< 16) | x
);
257 OUT_RING (chan
, (h
<< 16) | y
);
258 BEGIN_RING(chan
, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
259 OUT_RINGf (chan
, zmin
);
260 OUT_RINGf (chan
, zmax
);
264 nvc0_validate_clip(struct nvc0_context
*nvc0
)
266 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
269 if (nvc0
->clip
.depth_clamp
) {
271 NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1
|
272 NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR
|
273 NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR
|
274 NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2
;
276 clip
= NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1
;
279 BEGIN_RING(chan
, RING_3D(VIEW_VOLUME_CLIP_CTRL
), 1);
280 OUT_RING (chan
, clip
);
283 struct nouveau_bo
*bo
= nvc0
->screen
->uniforms
;
285 MARK_RING (chan
, 6 + nvc0
->clip
.nr
* 4, 2);
286 BEGIN_RING(chan
, RING_3D(CB_SIZE
), 3);
287 OUT_RING (chan
, 256);
288 OUT_RELOCh(chan
, bo
, 5 << 16, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
289 OUT_RELOCl(chan
, bo
, 5 << 16, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
290 BEGIN_RING_1I(chan
, RING_3D(CB_POS
), nvc0
->clip
.nr
* 4 + 1);
292 OUT_RINGp (chan
, &nvc0
->clip
.ucp
[0][0], nvc0
->clip
.nr
* 4);
295 if (nvc0
->vertprog
->vp
.num_ucps
) {
296 nvc0
->state
.clip_mode
= 0;
297 nvc0
->state
.clip_enable
= (1 << nvc0
->clip
.nr
) - 1;
298 IMMED_RING(chan
, RING_3D(CLIP_DISTANCE_ENABLE
), nvc0
->state
.clip_enable
);
299 IMMED_RING(chan
, RING_3D(CLIP_DISTANCE_MODE
), 0);
304 nvc0_validate_blend(struct nvc0_context
*nvc0
)
306 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
308 WAIT_RING(chan
, nvc0
->blend
->size
);
309 OUT_RINGp(chan
, nvc0
->blend
->state
, nvc0
->blend
->size
);
313 nvc0_validate_zsa(struct nvc0_context
*nvc0
)
315 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
317 WAIT_RING(chan
, nvc0
->zsa
->size
);
318 OUT_RINGp(chan
, nvc0
->zsa
->state
, nvc0
->zsa
->size
);
322 nvc0_validate_rasterizer(struct nvc0_context
*nvc0
)
324 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
326 WAIT_RING(chan
, nvc0
->rast
->size
);
327 OUT_RINGp(chan
, nvc0
->rast
->state
, nvc0
->rast
->size
);
331 nvc0_constbufs_validate(struct nvc0_context
*nvc0
)
333 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
334 struct nouveau_bo
*bo
;
337 for (s
= 0; s
< 5; ++s
) {
338 struct nv04_resource
*res
;
341 while (nvc0
->constbuf_dirty
[s
]) {
344 boolean rebind
= TRUE
;
346 i
= ffs(nvc0
->constbuf_dirty
[s
]) - 1;
347 nvc0
->constbuf_dirty
[s
] &= ~(1 << i
);
349 res
= nv04_resource(nvc0
->constbuf
[s
][i
]);
351 BEGIN_RING(chan
, RING_3D(CB_BIND(s
)), 1);
352 OUT_RING (chan
, (i
<< 4) | 0);
354 nvc0
->state
.uniform_buffer_bound
[s
] = 0;
358 if (!nouveau_resource_mapped_by_gpu(&res
->base
)) {
359 if (i
== 0 && (res
->status
& NOUVEAU_BUFFER_STATUS_USER_MEMORY
)) {
361 bo
= nvc0
->screen
->uniforms
;
363 if (nvc0
->state
.uniform_buffer_bound
[s
] >= res
->base
.width0
)
366 nvc0
->state
.uniform_buffer_bound
[s
] =
367 align(res
->base
.width0
, 0x100);
369 words
= res
->base
.width0
/ 4;
371 nouveau_buffer_migrate(&nvc0
->base
, res
, NOUVEAU_BO_VRAM
);
379 nvc0
->state
.uniform_buffer_bound
[s
] = 0;
382 if (bo
!= nvc0
->screen
->uniforms
)
383 nvc0_bufctx_add_resident(nvc0
, NVC0_BUFCTX_CONSTANT
, res
,
384 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
387 MARK_RING (chan
, 4, 2);
388 BEGIN_RING(chan
, RING_3D(CB_SIZE
), 3);
389 OUT_RING (chan
, align(res
->base
.width0
, 0x100));
390 OUT_RELOCh(chan
, bo
, base
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
391 OUT_RELOCl(chan
, bo
, base
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
392 BEGIN_RING(chan
, RING_3D(CB_BIND(s
)), 1);
393 OUT_RING (chan
, (i
<< 4) | 1);
397 nvc0_cb_push(&nvc0
->base
,
398 bo
, NOUVEAU_BO_VRAM
, base
, res
->base
.width0
,
399 0, words
, (const uint32_t *)res
->data
);
405 nvc0_validate_sample_mask(struct nvc0_context
*nvc0
)
407 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
411 nvc0
->sample_mask
& 0xffff,
412 nvc0
->sample_mask
& 0xffff,
413 nvc0
->sample_mask
& 0xffff,
414 nvc0
->sample_mask
& 0xffff
417 BEGIN_RING(chan
, RING_3D(MSAA_MASK(0)), 4);
418 OUT_RING (chan
, mask
[0]);
419 OUT_RING (chan
, mask
[1]);
420 OUT_RING (chan
, mask
[2]);
421 OUT_RING (chan
, mask
[3]);
422 BEGIN_RING(chan
, RING_3D(SAMPLE_SHADING
), 1);
423 OUT_RING (chan
, 0x01);
427 nvc0_validate_derived_1(struct nvc0_context
*nvc0
)
429 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
432 early_z
= nvc0
->fragprog
->fp
.early_z
&& !nvc0
->zsa
->pipe
.alpha
.enabled
;
434 if (early_z
!= nvc0
->state
.early_z
) {
435 nvc0
->state
.early_z
= early_z
;
436 IMMED_RING(chan
, RING_3D(EARLY_FRAGMENT_TESTS
), early_z
);
441 nvc0_switch_pipe_context(struct nvc0_context
*ctx_to
)
443 struct nvc0_context
*ctx_from
= ctx_to
->screen
->cur_ctx
;
446 ctx_to
->state
= ctx_from
->state
;
451 ctx_to
->dirty
&= ~(NVC0_NEW_VERTEX
| NVC0_NEW_ARRAYS
);
453 if (!ctx_to
->vertprog
)
454 ctx_to
->dirty
&= ~NVC0_NEW_VERTPROG
;
455 if (!ctx_to
->fragprog
)
456 ctx_to
->dirty
&= ~NVC0_NEW_FRAGPROG
;
459 ctx_to
->dirty
&= ~NVC0_NEW_BLEND
;
461 ctx_to
->dirty
&= ~(NVC0_NEW_RASTERIZER
| NVC0_NEW_SCISSOR
);
463 ctx_to
->dirty
&= ~NVC0_NEW_ZSA
;
465 ctx_to
->screen
->cur_ctx
= ctx_to
;
468 static struct state_validate
{
469 void (*func
)(struct nvc0_context
*);
471 } validate_list
[] = {
472 { nvc0_validate_fb
, NVC0_NEW_FRAMEBUFFER
},
473 { nvc0_validate_blend
, NVC0_NEW_BLEND
},
474 { nvc0_validate_zsa
, NVC0_NEW_ZSA
},
475 { nvc0_validate_sample_mask
, NVC0_NEW_SAMPLE_MASK
},
476 { nvc0_validate_rasterizer
, NVC0_NEW_RASTERIZER
},
477 { nvc0_validate_blend_colour
, NVC0_NEW_BLEND_COLOUR
},
478 { nvc0_validate_stencil_ref
, NVC0_NEW_STENCIL_REF
},
479 { nvc0_validate_stipple
, NVC0_NEW_STIPPLE
},
480 { nvc0_validate_scissor
, NVC0_NEW_SCISSOR
| NVC0_NEW_RASTERIZER
},
481 { nvc0_validate_viewport
, NVC0_NEW_VIEWPORT
},
482 { nvc0_vertprog_validate
, NVC0_NEW_VERTPROG
},
483 { nvc0_tctlprog_validate
, NVC0_NEW_TCTLPROG
},
484 { nvc0_tevlprog_validate
, NVC0_NEW_TEVLPROG
},
485 { nvc0_gmtyprog_validate
, NVC0_NEW_GMTYPROG
},
486 { nvc0_fragprog_validate
, NVC0_NEW_FRAGPROG
},
487 { nvc0_validate_derived_1
, NVC0_NEW_FRAGPROG
| NVC0_NEW_ZSA
},
488 { nvc0_validate_clip
, NVC0_NEW_CLIP
},
489 { nvc0_constbufs_validate
, NVC0_NEW_CONSTBUF
},
490 { nvc0_validate_textures
, NVC0_NEW_TEXTURES
},
491 { nvc0_validate_samplers
, NVC0_NEW_SAMPLERS
},
492 { nvc0_vertex_arrays_validate
, NVC0_NEW_VERTEX
| NVC0_NEW_ARRAYS
},
493 { nvc0_tfb_validate
, NVC0_NEW_TFB
| NVC0_NEW_TFB_BUFFERS
}
495 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
498 nvc0_state_validate(struct nvc0_context
*nvc0
, uint32_t mask
, unsigned words
)
503 if (nvc0
->screen
->cur_ctx
!= nvc0
)
504 nvc0_switch_pipe_context(nvc0
);
506 state_mask
= nvc0
->dirty
& mask
;
509 for (i
= 0; i
< validate_list_len
; ++i
) {
510 struct state_validate
*validate
= &validate_list
[i
];
512 if (state_mask
& validate
->states
)
513 validate
->func(nvc0
);
515 nvc0
->dirty
&= ~state_mask
;
518 MARK_RING(nvc0
->screen
->base
.channel
, words
, 0);
520 nvc0_bufctx_emit_relocs(nvc0
);