1 #include "nvfx_context.h"
2 #include "nvfx_state.h"
3 #include "nvfx_resource.h"
4 #include "draw/draw_context.h"
7 nvfx_state_validate_common(struct nvfx_context
*nvfx
)
9 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
11 unsigned still_dirty
= 0;
12 int all_swizzled
= -1;
13 boolean flush_tex_cache
= FALSE
;
14 unsigned render_temps
;
16 if(nvfx
!= nvfx
->screen
->cur_ctx
)
19 nvfx
->hw_vtxelt_nr
= 16;
20 nvfx
->hw_pointsprite_control
= -1;
21 nvfx
->hw_vp_output
= -1;
22 nvfx
->screen
->cur_ctx
= nvfx
;
23 nvfx
->relocs_needed
= NVFX_RELOCATE_ALL
;
26 /* These can trigger use the of 3D engine to copy temporaries.
27 * That will recurse here and thus dirty all 3D state, so we need to this before anything else, and in a loop..
28 * This converges to having clean temps, then binding both fragtexes and framebuffers.
30 while(nvfx
->dirty
& (NVFX_NEW_FB
| NVFX_NEW_SAMPLER
))
32 if(nvfx
->dirty
& NVFX_NEW_SAMPLER
)
34 nvfx
->dirty
&=~ NVFX_NEW_SAMPLER
;
35 nvfx_fragtex_validate(nvfx
);
37 // TODO: only set this if really necessary
38 flush_tex_cache
= TRUE
;
41 if(nvfx
->dirty
& NVFX_NEW_FB
)
43 nvfx
->dirty
&=~ NVFX_NEW_FB
;
44 all_swizzled
= nvfx_framebuffer_prepare(nvfx
);
46 // TODO: make sure this doesn't happen, i.e. fbs have matching formats
47 assert(all_swizzled
>= 0);
53 if(nvfx
->render_mode
== HW
)
55 if(dirty
& (NVFX_NEW_VERTPROG
| NVFX_NEW_VERTCONST
| NVFX_NEW_UCP
))
57 if(!nvfx_vertprog_validate(nvfx
))
61 if(dirty
& NVFX_NEW_ARRAYS
)
63 if(!nvfx_vbo_validate(nvfx
))
67 if(dirty
& NVFX_NEW_INDEX
)
69 if(nvfx
->use_index_buffer
)
70 nvfx_idxbuf_validate(nvfx
);
72 still_dirty
= NVFX_NEW_INDEX
;
77 /* TODO: this looks a bit misdesigned */
78 if(dirty
& (NVFX_NEW_VERTPROG
| NVFX_NEW_UCP
))
79 nvfx_vertprog_validate(nvfx
);
81 if(dirty
& (NVFX_NEW_ARRAYS
| NVFX_NEW_INDEX
| NVFX_NEW_FRAGPROG
))
82 nvfx_vtxfmt_validate(nvfx
);
85 if(dirty
& NVFX_NEW_RAST
)
86 sb_emit(chan
, nvfx
->rasterizer
->sb
, nvfx
->rasterizer
->sb_len
);
88 if(dirty
& NVFX_NEW_SCISSOR
)
89 nvfx_state_scissor_validate(nvfx
);
91 if(dirty
& NVFX_NEW_STIPPLE
)
92 nvfx_state_stipple_validate(nvfx
);
94 if(nvfx
->dirty
& NVFX_NEW_UCP
)
99 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
,
100 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1
,
101 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2
,
102 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3
,
103 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4
,
104 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE5
,
107 if(!nvfx
->use_vp_clipping
)
110 OUT_RING(chan
, RING_3D(NV34TCL_VP_CLIP_PLANES_ENABLE
, 1));
113 WAIT_RING(chan
, 6 * 4 + 1);
114 OUT_RING(chan
, RING_3D(NV34TCL_VP_CLIP_PLANE_A(0), nvfx
->clip
.nr
* 4));
115 OUT_RINGp(chan
, &nvfx
->clip
.ucp
[0][0], nvfx
->clip
.nr
* 4);
119 OUT_RING(chan
, RING_3D(NV34TCL_VP_CLIP_PLANES_ENABLE
, 1));
120 OUT_RING(chan
, enables
[nvfx
->clip
.nr
]);
123 if(nvfx
->use_vp_clipping
&& (nvfx
->dirty
& (NVFX_NEW_UCP
| NVFX_NEW_VERTPROG
)))
126 struct nvfx_vertex_program
* vp
= nvfx
->vertprog
;
127 if(nvfx
->clip
.nr
!= vp
->clip_nr
)
132 /* remove last instruction bit */
135 idx
= vp
->nr_insns
- 7 + vp
->clip_nr
;
136 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_FROM_ID
, 1));
137 OUT_RING(chan
, vp
->exec
->start
+ idx
);
138 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_INST(0), 4));
139 OUT_RINGp (chan
, vp
->insns
[idx
].data
, 4);
142 /* set last instruction bit */
143 idx
= vp
->nr_insns
- 7 + nvfx
->clip
.nr
;
144 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_FROM_ID
, 1));
145 OUT_RING(chan
, vp
->exec
->start
+ idx
);
146 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_INST(0), 4));
147 OUT_RINGp(chan
, vp
->insns
[idx
].data
, 3);
148 OUT_RING(chan
, vp
->insns
[idx
].data
[3] | 1);
149 vp
->clip_nr
= nvfx
->clip
.nr
;
152 // TODO: only do this for the ones changed
153 WAIT_RING(chan
, 6 * 6);
154 for(i
= 0; i
< nvfx
->clip
.nr
; ++i
)
156 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_CONST_ID
, 5));
157 OUT_RING(chan
, vp
->data
->start
+ i
);
158 OUT_RINGp (chan
, nvfx
->clip
.ucp
[i
], 4);
162 if(dirty
& (NVFX_NEW_FRAGPROG
| NVFX_NEW_FRAGCONST
| NVFX_NEW_VERTPROG
| NVFX_NEW_SPRITE
))
164 nvfx_fragprog_validate(nvfx
);
165 if(dirty
& NVFX_NEW_FRAGPROG
)
166 flush_tex_cache
= TRUE
; // TODO: do we need this?
171 unsigned vp_output
= nvfx
->vertprog
->or | nvfx
->hw_fragprog
->or;
172 vp_output
|= (1 << (nvfx
->clip
.nr
+ 6)) - (1 << 6);
174 if(vp_output
!= nvfx
->hw_vp_output
)
177 OUT_RING(chan
, RING_3D(NV40TCL_VP_RESULT_EN
, 1));
178 OUT_RING(chan
, vp_output
);
179 nvfx
->hw_vp_output
= vp_output
;
183 if(all_swizzled
>= 0)
184 nvfx_framebuffer_validate(nvfx
, all_swizzled
);
186 if(dirty
& NVFX_NEW_BLEND
)
187 sb_emit(chan
, nvfx
->blend
->sb
, nvfx
->blend
->sb_len
);
189 if(dirty
& NVFX_NEW_BCOL
)
190 nvfx_state_blend_colour_validate(nvfx
);
192 if(dirty
& NVFX_NEW_ZSA
)
193 sb_emit(chan
, nvfx
->zsa
->sb
, nvfx
->zsa
->sb_len
);
195 if(dirty
& NVFX_NEW_SR
)
196 nvfx_state_sr_validate(nvfx
);
198 /* All these dependencies are wrong, but otherwise
199 etracer, neverball, foobillard, glest totally misrender
200 TODO: find the right fix
202 if(dirty
& (NVFX_NEW_VIEWPORT
| NVFX_NEW_RAST
| NVFX_NEW_ZSA
) || (all_swizzled
>= 0))
204 nvfx_state_viewport_validate(nvfx
);
207 if(dirty
& NVFX_NEW_ZSA
|| (all_swizzled
>= 0))
210 OUT_RING(chan
, RING_3D(NV34TCL_DEPTH_WRITE_ENABLE
, 2));
211 OUT_RING(chan
, nvfx
->framebuffer
.zsbuf
&& nvfx
->zsa
->pipe
.depth
.writemask
);
212 OUT_RING(chan
, nvfx
->framebuffer
.zsbuf
&& nvfx
->zsa
->pipe
.depth
.enabled
);
217 // TODO: what about nv30?
221 OUT_RING(chan
, RING_3D(NV40TCL_TEX_CACHE_CTL
, 1));
223 OUT_RING(chan
, RING_3D(NV40TCL_TEX_CACHE_CTL
, 1));
228 nvfx
->dirty
= dirty
& still_dirty
;
230 render_temps
= nvfx
->state
.render_temps
;
233 for(int i
= 0; i
< nvfx
->framebuffer
.nr_cbufs
; ++i
)
235 if(render_temps
& (1 << i
))
236 util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(nvfx
->framebuffer
.cbufs
[i
]),
237 (struct util_dirty_surface
*)nvfx
->framebuffer
.cbufs
[i
]);
240 if(render_temps
& 0x80)
241 util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(nvfx
->framebuffer
.zsbuf
),
242 (struct util_dirty_surface
*)nvfx
->framebuffer
.zsbuf
);
249 nvfx_state_relocate(struct nvfx_context
*nvfx
, unsigned relocs
)
251 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
252 /* we need to ensure there is enough space to output relocations in one go */
253 const unsigned max_relocs
= 0
254 + 16 /* vertex buffers, incl. dma flag */
255 + 2 /* index buffer plus format+dma flag */
256 + 2 * 5 /* 4 cbufs + zsbuf, plus dma objects */
257 + 2 * 16 /* fragment textures plus format+dma flag */
258 + 2 * 4 /* vertex textures plus format+dma flag */
259 + 1 /* fragprog incl dma flag */
262 MARK_RING(chan
, max_relocs
* 2, max_relocs
* 2);
264 if(relocs
& NVFX_RELOCATE_FRAMEBUFFER
)
265 nvfx_framebuffer_relocate(nvfx
);
266 if(relocs
& NVFX_RELOCATE_FRAGTEX
)
267 nvfx_fragtex_relocate(nvfx
);
268 if(relocs
& NVFX_RELOCATE_FRAGPROG
)
269 nvfx_fragprog_relocate(nvfx
);
270 if(relocs
& NVFX_RELOCATE_VTXBUF
)
271 nvfx_vbo_relocate(nvfx
);
272 if(relocs
& NVFX_RELOCATE_IDXBUF
)
273 nvfx_idxbuf_relocate(nvfx
);
277 nvfx_state_validate(struct nvfx_context
*nvfx
)
279 boolean was_sw
= nvfx
->fallback_swtnl
? TRUE
: FALSE
;
281 if (nvfx
->render_mode
!= HW
) {
282 /* Don't even bother trying to go back to hw if none
283 * of the states that caused swtnl previously have changed.
285 if ((nvfx
->fallback_swtnl
& nvfx
->dirty
)
286 != nvfx
->fallback_swtnl
)
289 /* Attempt to go to hwtnl again */
290 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
293 nvfx
->render_mode
= HW
;
296 if(!nvfx_state_validate_common(nvfx
))
300 NOUVEAU_ERR("swtnl->hw\n");
306 nvfx_state_validate_swtnl(struct nvfx_context
*nvfx
)
308 struct draw_context
*draw
= nvfx
->draw
;
310 /* Setup for swtnl */
311 if (nvfx
->render_mode
== HW
) {
312 NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx
->fallback_swtnl
);
313 nvfx
->pipe
.flush(&nvfx
->pipe
, 0, NULL
);
314 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
317 nvfx
->render_mode
= SWTNL
;
320 if (nvfx
->draw_dirty
& NVFX_NEW_VERTPROG
)
321 draw_bind_vertex_shader(draw
, nvfx
->vertprog
->draw
);
323 if (nvfx
->draw_dirty
& NVFX_NEW_RAST
)
324 draw_set_rasterizer_state(draw
, &nvfx
->rasterizer
->pipe
,
327 if (nvfx
->draw_dirty
& NVFX_NEW_UCP
)
328 draw_set_clip_state(draw
, &nvfx
->clip
);
330 if (nvfx
->draw_dirty
& NVFX_NEW_VIEWPORT
)
331 draw_set_viewport_state(draw
, &nvfx
->viewport
);
333 if (nvfx
->draw_dirty
& NVFX_NEW_ARRAYS
) {
334 draw_set_vertex_buffers(draw
, nvfx
->vtxbuf_nr
, nvfx
->vtxbuf
);
335 draw_set_vertex_elements(draw
, nvfx
->vtxelt
->num_elements
, nvfx
->vtxelt
->pipe
);
338 if (nvfx
->draw_dirty
& NVFX_NEW_INDEX
)
339 draw_set_index_buffer(draw
, &nvfx
->idxbuf
);
341 nvfx_state_validate_common(nvfx
);
343 nvfx
->draw_dirty
= 0;