2 #include "nvc0_context.h"
3 #include "os/os_time.h"
6 nvc0_validate_zcull(struct nvc0_context
*nvc0
)
8 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
9 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
10 struct nvc0_surface
*sf
= nvc0_surface(fb
->zsbuf
);
11 struct nvc0_miptree
*mt
= nvc0_miptree(sf
->base
.texture
);
12 struct nouveau_bo
*bo
= mt
->base
.bo
;
14 uint32_t offset
= align(mt
->total_size
, 1 << 17);
15 unsigned width
, height
;
17 assert(mt
->base
.base
.depth0
== 1 && mt
->base
.base
.array_size
< 2);
19 size
= mt
->total_size
* 2;
21 height
= align(fb
->height
, 32);
22 width
= fb
->width
% 224;
24 width
= fb
->width
+ (224 - width
);
28 MARK_RING (chan
, 23, 4);
29 BEGIN_RING(chan
, RING_3D_(0x1590), 1); /* ZCULL_REGION_INDEX (bits 0x3f) */
31 BEGIN_RING(chan
, RING_3D_(0x07e8), 2); /* ZCULL_ADDRESS_A_HIGH */
32 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
33 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
35 BEGIN_RING(chan
, RING_3D_(0x07f0), 2); /* ZCULL_ADDRESS_B_HIGH */
36 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
37 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
38 BEGIN_RING(chan
, RING_3D_(0x07e0), 2);
39 OUT_RING (chan
, size
);
40 OUT_RING (chan
, size
>> 16);
41 BEGIN_RING(chan
, RING_3D_(0x15c8), 1); /* bits 0x3 */
43 BEGIN_RING(chan
, RING_3D_(0x07c0), 4); /* ZCULL dimensions */
44 OUT_RING (chan
, width
);
45 OUT_RING (chan
, height
);
48 BEGIN_RING(chan
, RING_3D_(0x15fc), 2);
49 OUT_RING (chan
, 0); /* bits 0xffff */
50 OUT_RING (chan
, 0); /* bits 0xffff */
51 BEGIN_RING(chan
, RING_3D_(0x1958), 1);
52 OUT_RING (chan
, 0); /* bits ~0 */
56 nvc0_validate_fb(struct nvc0_context
*nvc0
)
58 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
59 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
62 nvc0_bufctx_reset(nvc0
, NVC0_BUFCTX_FRAME
);
64 BEGIN_RING(chan
, RING_3D(RT_CONTROL
), 1);
65 OUT_RING (chan
, (076543210 << 4) | fb
->nr_cbufs
);
66 BEGIN_RING(chan
, RING_3D(SCREEN_SCISSOR_HORIZ
), 2);
67 OUT_RING (chan
, fb
->width
<< 16);
68 OUT_RING (chan
, fb
->height
<< 16);
70 MARK_RING(chan
, 9 * fb
->nr_cbufs
, 2 * fb
->nr_cbufs
);
72 for (i
= 0; i
< fb
->nr_cbufs
; ++i
) {
73 struct nvc0_miptree
*mt
= nvc0_miptree(fb
->cbufs
[i
]->texture
);
74 struct nvc0_surface
*sf
= nvc0_surface(fb
->cbufs
[i
]);
75 struct nouveau_bo
*bo
= mt
->base
.bo
;
76 uint32_t offset
= sf
->offset
;
78 BEGIN_RING(chan
, RING_3D(RT_ADDRESS_HIGH(i
)), 8);
79 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
80 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
81 OUT_RING (chan
, sf
->width
);
82 OUT_RING (chan
, sf
->height
);
83 OUT_RING (chan
, nvc0_format_table
[sf
->base
.format
].rt
);
84 OUT_RING (chan
, (mt
->layout_3d
<< 16) |
85 mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
86 OUT_RING (chan
, sf
->depth
);
87 OUT_RING (chan
, mt
->layer_stride
>> 2);
89 nvc0_bufctx_add_resident(nvc0
, NVC0_BUFCTX_FRAME
, &mt
->base
,
90 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
94 struct nvc0_miptree
*mt
= nvc0_miptree(fb
->zsbuf
->texture
);
95 struct nvc0_surface
*sf
= nvc0_surface(fb
->zsbuf
);
96 struct nouveau_bo
*bo
= mt
->base
.bo
;
97 int unk
= mt
->base
.base
.target
== PIPE_TEXTURE_2D
;
98 uint32_t offset
= sf
->offset
;
100 MARK_RING (chan
, 12, 2);
101 BEGIN_RING(chan
, RING_3D(ZETA_ADDRESS_HIGH
), 5);
102 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
103 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
104 OUT_RING (chan
, nvc0_format_table
[fb
->zsbuf
->format
].rt
);
105 OUT_RING (chan
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
106 OUT_RING (chan
, mt
->layer_stride
>> 2);
107 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
109 BEGIN_RING(chan
, RING_3D(ZETA_HORIZ
), 3);
110 OUT_RING (chan
, sf
->width
);
111 OUT_RING (chan
, sf
->height
);
112 OUT_RING (chan
, (unk
<< 16) | sf
->depth
);
114 nvc0_bufctx_add_resident(nvc0
, NVC0_BUFCTX_FRAME
, &mt
->base
,
115 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
117 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
121 #ifndef NVC0_SCISSORS_CLIPPING
122 BEGIN_RING(chan
, RING_3D(VIEWPORT_HORIZ(0)), 2);
123 OUT_RING (chan
, fb
->width
<< 16);
124 OUT_RING (chan
, fb
->height
<< 16);
129 nvc0_validate_blend_colour(struct nvc0_context
*nvc0
)
131 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
133 BEGIN_RING(chan
, RING_3D(BLEND_COLOR(0)), 4);
134 OUT_RINGf (chan
, nvc0
->blend_colour
.color
[0]);
135 OUT_RINGf (chan
, nvc0
->blend_colour
.color
[1]);
136 OUT_RINGf (chan
, nvc0
->blend_colour
.color
[2]);
137 OUT_RINGf (chan
, nvc0
->blend_colour
.color
[3]);
141 nvc0_validate_stencil_ref(struct nvc0_context
*nvc0
)
143 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
145 BEGIN_RING(chan
, RING_3D(STENCIL_FRONT_FUNC_REF
), 1);
146 OUT_RING (chan
, nvc0
->stencil_ref
.ref_value
[0]);
147 BEGIN_RING(chan
, RING_3D(STENCIL_BACK_FUNC_REF
), 1);
148 OUT_RING (chan
, nvc0
->stencil_ref
.ref_value
[1]);
152 nvc0_validate_stipple(struct nvc0_context
*nvc0
)
154 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
157 BEGIN_RING(chan
, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
158 for (i
= 0; i
< 32; ++i
)
159 OUT_RING(chan
, util_bswap32(nvc0
->stipple
.stipple
[i
]));
163 nvc0_validate_scissor(struct nvc0_context
*nvc0
)
165 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
166 struct pipe_scissor_state
*s
= &nvc0
->scissor
;
167 #ifdef NVC0_SCISSORS_CLIPPING
168 struct pipe_viewport_state
*vp
= &nvc0
->viewport
;
169 int minx
, maxx
, miny
, maxy
;
172 (NVC0_NEW_SCISSOR
| NVC0_NEW_VIEWPORT
| NVC0_NEW_FRAMEBUFFER
)) &&
173 nvc0
->state
.scissor
== nvc0
->rast
->pipe
.scissor
)
175 nvc0
->state
.scissor
= nvc0
->rast
->pipe
.scissor
;
177 if (nvc0
->state
.scissor
) {
184 maxx
= nvc0
->framebuffer
.width
;
186 maxy
= nvc0
->framebuffer
.height
;
189 minx
= MAX2(minx
, (int)(vp
->translate
[0] - fabsf(vp
->scale
[0])));
190 maxx
= MIN2(maxx
, (int)(vp
->translate
[0] + fabsf(vp
->scale
[0])));
191 miny
= MAX2(miny
, (int)(vp
->translate
[1] - fabsf(vp
->scale
[1])));
192 maxy
= MIN2(maxy
, (int)(vp
->translate
[1] + fabsf(vp
->scale
[1])));
194 BEGIN_RING(chan
, RING_3D(SCISSOR_HORIZ(0)), 2);
195 OUT_RING (chan
, (maxx
<< 16) | minx
);
196 OUT_RING (chan
, (maxy
<< 16) | miny
);
197 BEGIN_RING(chan
, RING_3D(VIEWPORT_HORIZ(0)), 2);
198 OUT_RING (chan
, ((maxx
- minx
) << 16) | minx
);
199 OUT_RING (chan
, ((maxy
- miny
) << 16) | miny
);
201 BEGIN_RING(chan
, RING_3D(SCISSOR_HORIZ(0)), 2);
202 OUT_RING (chan
, (s
->maxx
<< 16) | s
->minx
);
203 OUT_RING (chan
, (s
->maxy
<< 16) | s
->miny
);
208 nvc0_validate_viewport(struct nvc0_context
*nvc0
)
210 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
212 BEGIN_RING(chan
, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
213 OUT_RINGf (chan
, nvc0
->viewport
.translate
[0]);
214 OUT_RINGf (chan
, nvc0
->viewport
.translate
[1]);
215 OUT_RINGf (chan
, nvc0
->viewport
.translate
[2]);
216 BEGIN_RING(chan
, RING_3D(VIEWPORT_SCALE_X(0)), 3);
217 OUT_RINGf (chan
, nvc0
->viewport
.scale
[0]);
218 OUT_RINGf (chan
, nvc0
->viewport
.scale
[1]);
219 OUT_RINGf (chan
, nvc0
->viewport
.scale
[2]);
221 #ifdef NVC0_SCISSORS_CLIPPING
222 BEGIN_RING(chan
, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
223 OUT_RINGf (chan
, nvc0
->viewport
.translate
[2] - nvc0
->viewport
.scale
[2]);
224 OUT_RINGf (chan
, nvc0
->viewport
.translate
[2] + nvc0
->viewport
.scale
[2]);
229 nvc0_validate_clip(struct nvc0_context
*nvc0
)
231 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
234 clip
= nvc0
->clip
.depth_clamp
? 0x201a : 0x0002;
235 #ifndef NVC0_SCISSORS_CLIPPING
239 BEGIN_RING(chan
, RING_3D(VIEW_VOLUME_CLIP_CTRL
), 1);
240 OUT_RING (chan
, clip
);
243 struct nouveau_bo
*bo
= nvc0
->screen
->uniforms
;
245 MARK_RING (chan
, 6 + nvc0
->clip
.nr
* 4, 2);
246 BEGIN_RING(chan
, RING_3D(CB_SIZE
), 3);
247 OUT_RING (chan
, 256);
248 OUT_RELOCh(chan
, bo
, 5 << 16, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
249 OUT_RELOCl(chan
, bo
, 5 << 16, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
250 BEGIN_RING_1I(chan
, RING_3D(CB_POS
), nvc0
->clip
.nr
* 4 + 1);
252 OUT_RINGp (chan
, &nvc0
->clip
.ucp
[0][0], nvc0
->clip
.nr
* 4);
254 BEGIN_RING(chan
, RING_3D(VP_CLIP_DISTANCE_ENABLE
), 1);
255 OUT_RING (chan
, (1 << nvc0
->clip
.nr
) - 1);
257 IMMED_RING(chan
, RING_3D(VP_CLIP_DISTANCE_ENABLE
), 0);
262 nvc0_validate_blend(struct nvc0_context
*nvc0
)
264 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
266 WAIT_RING(chan
, nvc0
->blend
->size
);
267 OUT_RINGp(chan
, nvc0
->blend
->state
, nvc0
->blend
->size
);
271 nvc0_validate_zsa(struct nvc0_context
*nvc0
)
273 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
275 WAIT_RING(chan
, nvc0
->zsa
->size
);
276 OUT_RINGp(chan
, nvc0
->zsa
->state
, nvc0
->zsa
->size
);
280 nvc0_validate_rasterizer(struct nvc0_context
*nvc0
)
282 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
284 WAIT_RING(chan
, nvc0
->rast
->size
);
285 OUT_RINGp(chan
, nvc0
->rast
->state
, nvc0
->rast
->size
);
289 nvc0_validate_sprite_coords(struct nvc0_context
*nvc0
)
291 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
294 if (nvc0
->rast
->pipe
.sprite_coord_mode
== PIPE_SPRITE_COORD_UPPER_LEFT
)
295 reg
= NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT
;
297 reg
= NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT
;
299 if (nvc0
->rast
->pipe
.point_quad_rasterization
) {
300 uint32_t en
= nvc0
->rast
->pipe
.sprite_coord_enable
;
302 struct nvc0_program
*prog
= nvc0
->fragprog
;
307 if (prog
->fp
.in_pos
[i
] >= 0xc0 && prog
->fp
.in_pos
[i
] < 0xe0)
308 reg
|= 8 << ((prog
->fp
.in_pos
[i
] - 0xc0) / 4);
312 BEGIN_RING(chan
, RING_3D(POINT_COORD_REPLACE
), 1);
313 OUT_RING (chan
, reg
);
317 nvc0_constbufs_validate(struct nvc0_context
*nvc0
)
319 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
320 struct nouveau_bo
*bo
;
323 for (s
= 0; s
< 5; ++s
) {
324 struct nvc0_resource
*res
;
327 while (nvc0
->constbuf_dirty
[s
]) {
329 unsigned offset
= 0, words
= 0;
330 boolean rebind
= TRUE
;
332 i
= ffs(nvc0
->constbuf_dirty
[s
]) - 1;
333 nvc0
->constbuf_dirty
[s
] &= ~(1 << i
);
335 res
= nvc0_resource(nvc0
->constbuf
[s
][i
]);
337 BEGIN_RING(chan
, RING_3D(CB_BIND(s
)), 1);
338 OUT_RING (chan
, (i
<< 4) | 0);
340 nvc0
->state
.uniform_buffer_bound
[s
] = 0;
344 if (!nvc0_resource_mapped_by_gpu(&res
->base
)) {
347 bo
= nvc0
->screen
->uniforms
;
349 if (nvc0
->state
.uniform_buffer_bound
[s
] >= res
->base
.width0
)
352 nvc0
->state
.uniform_buffer_bound
[s
] =
353 align(res
->base
.width0
, 0x100);
358 nvc0_m2mf_push_linear(nvc0
, bo
, NOUVEAU_BO_VRAM
,
359 base
, res
->base
.width0
, res
->data
);
360 BEGIN_RING(chan
, RING_3D_(0x021c), 1);
361 OUT_RING (chan
, 0x1111);
363 words
= res
->base
.width0
/ 4;
368 nvc0
->state
.uniform_buffer_bound
[s
] = 0;
371 if (bo
!= nvc0
->screen
->uniforms
)
372 nvc0_bufctx_add_resident(nvc0
, NVC0_BUFCTX_CONSTANT
, res
,
373 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
376 MARK_RING (chan
, 4, 2);
377 BEGIN_RING(chan
, RING_3D(CB_SIZE
), 3);
378 OUT_RING (chan
, align(res
->base
.width0
, 0x100));
379 OUT_RELOCh(chan
, bo
, base
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
380 OUT_RELOCl(chan
, bo
, base
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
381 BEGIN_RING(chan
, RING_3D(CB_BIND(s
)), 1);
382 OUT_RING (chan
, (i
<< 4) | 1);
386 unsigned nr
= AVAIL_RING(chan
);
392 nr
= MIN2(MIN2(nr
- 6, words
), NV04_PFIFO_MAX_PACKET_LEN
- 1);
394 MARK_RING (chan
, nr
+ 5, 2);
395 BEGIN_RING(chan
, RING_3D(CB_SIZE
), 3);
396 OUT_RING (chan
, align(res
->base
.width0
, 0x100));
397 OUT_RELOCh(chan
, bo
, base
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
398 OUT_RELOCl(chan
, bo
, base
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
399 BEGIN_RING_1I(chan
, RING_3D(CB_POS
), nr
+ 1);
400 OUT_RING (chan
, offset
);
401 OUT_RINGp (chan
, &res
->data
[offset
], nr
);
410 static struct state_validate
{
411 void (*func
)(struct nvc0_context
*);
413 } validate_list
[] = {
414 { nvc0_validate_fb
, NVC0_NEW_FRAMEBUFFER
},
415 { nvc0_validate_blend
, NVC0_NEW_BLEND
},
416 { nvc0_validate_zsa
, NVC0_NEW_ZSA
},
417 { nvc0_validate_rasterizer
, NVC0_NEW_RASTERIZER
},
418 { nvc0_validate_blend_colour
, NVC0_NEW_BLEND_COLOUR
},
419 { nvc0_validate_stencil_ref
, NVC0_NEW_STENCIL_REF
},
420 { nvc0_validate_stipple
, NVC0_NEW_STIPPLE
},
421 #ifdef NVC0_SCISSORS_CLIPPING
422 { nvc0_validate_scissor
, NVC0_NEW_SCISSOR
| NVC0_NEW_VIEWPORT
|
423 NVC0_NEW_RASTERIZER
|
424 NVC0_NEW_FRAMEBUFFER
},
426 { nvc0_validate_scissor
, NVC0_NEW_SCISSOR
},
428 { nvc0_validate_viewport
, NVC0_NEW_VIEWPORT
},
429 { nvc0_validate_clip
, NVC0_NEW_CLIP
},
430 { nvc0_vertprog_validate
, NVC0_NEW_VERTPROG
},
431 { nvc0_tctlprog_validate
, NVC0_NEW_TCTLPROG
},
432 { nvc0_tevlprog_validate
, NVC0_NEW_TEVLPROG
},
433 { nvc0_gmtyprog_validate
, NVC0_NEW_GMTYPROG
},
434 { nvc0_fragprog_validate
, NVC0_NEW_FRAGPROG
},
435 { nvc0_validate_sprite_coords
, NVC0_NEW_RASTERIZER
| NVC0_NEW_FRAGPROG
},
436 { nvc0_constbufs_validate
, NVC0_NEW_CONSTBUF
},
437 { nvc0_validate_textures
, NVC0_NEW_TEXTURES
},
438 { nvc0_validate_samplers
, NVC0_NEW_SAMPLERS
},
439 { nvc0_vertex_arrays_validate
, NVC0_NEW_VERTEX
| NVC0_NEW_ARRAYS
}
441 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
444 nvc0_state_validate(struct nvc0_context
*nvc0
)
448 if (nvc0
->screen
->cur_ctx
!= nvc0
) /* FIXME: not everything is valid */
449 nvc0
->dirty
= 0xffffffff;
451 nvc0
->screen
->cur_ctx
= nvc0
;
454 for (i
= 0; i
< validate_list_len
; ++i
) {
455 struct state_validate
*validate
= &validate_list
[i
];
457 if (nvc0
->dirty
& validate
->states
)
458 validate
->func(nvc0
);
463 nvc0_bufctx_emit_relocs(nvc0
);