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
;
25 /* These can trigger use the of 3D engine to copy temporaries.
26 * That will recurse here and thus dirty all 3D state, so we need to this before anything else, and in a loop..
27 * This converges to having clean temps, then binding both fragtexes and framebuffers.
29 while(nvfx
->dirty
& (NVFX_NEW_FB
| NVFX_NEW_SAMPLER
))
31 if(nvfx
->dirty
& NVFX_NEW_SAMPLER
)
33 nvfx
->dirty
&=~ NVFX_NEW_SAMPLER
;
34 nvfx_fragtex_validate(nvfx
);
36 // TODO: only set this if really necessary
37 flush_tex_cache
= TRUE
;
40 if(nvfx
->dirty
& NVFX_NEW_FB
)
42 nvfx
->dirty
&=~ NVFX_NEW_FB
;
43 all_swizzled
= nvfx_framebuffer_prepare(nvfx
);
45 // TODO: make sure this doesn't happen, i.e. fbs have matching formats
46 assert(all_swizzled
>= 0);
52 if(nvfx
->render_mode
== HW
)
54 if(dirty
& (NVFX_NEW_VERTPROG
| NVFX_NEW_VERTCONST
| NVFX_NEW_UCP
))
56 if(!nvfx_vertprog_validate(nvfx
))
60 if(dirty
& NVFX_NEW_ARRAYS
)
62 if(!nvfx_vbo_validate(nvfx
))
66 if(dirty
& NVFX_NEW_INDEX
)
68 if(nvfx
->use_index_buffer
)
69 nvfx_idxbuf_validate(nvfx
);
71 still_dirty
= NVFX_NEW_INDEX
;
76 /* TODO: this looks a bit misdesigned */
77 if(dirty
& (NVFX_NEW_VERTPROG
| NVFX_NEW_UCP
))
78 nvfx_vertprog_validate(nvfx
);
80 if(dirty
& (NVFX_NEW_ARRAYS
| NVFX_NEW_INDEX
| NVFX_NEW_FRAGPROG
))
81 nvfx_vtxfmt_validate(nvfx
);
84 if(dirty
& NVFX_NEW_RAST
)
85 sb_emit(chan
, nvfx
->rasterizer
->sb
, nvfx
->rasterizer
->sb_len
);
87 if(dirty
& NVFX_NEW_SCISSOR
)
88 nvfx_state_scissor_validate(nvfx
);
90 if(dirty
& NVFX_NEW_STIPPLE
)
91 nvfx_state_stipple_validate(nvfx
);
93 if(dirty
& (NVFX_NEW_FRAGPROG
| NVFX_NEW_FRAGCONST
| NVFX_NEW_VERTPROG
| NVFX_NEW_SPRITE
))
95 nvfx_fragprog_validate(nvfx
);
96 if(dirty
& NVFX_NEW_FRAGPROG
)
97 flush_tex_cache
= TRUE
; // TODO: do we need this?
100 if(all_swizzled
>= 0)
101 nvfx_framebuffer_validate(nvfx
, all_swizzled
);
103 if(dirty
& NVFX_NEW_BLEND
)
104 sb_emit(chan
, nvfx
->blend
->sb
, nvfx
->blend
->sb_len
);
106 if(dirty
& NVFX_NEW_BCOL
)
107 nvfx_state_blend_colour_validate(nvfx
);
109 if(dirty
& NVFX_NEW_ZSA
)
110 sb_emit(chan
, nvfx
->zsa
->sb
, nvfx
->zsa
->sb_len
);
112 if(dirty
& NVFX_NEW_SR
)
113 nvfx_state_sr_validate(nvfx
);
115 /* All these dependencies are wrong, but otherwise
116 etracer, neverball, foobillard, glest totally misrender
117 TODO: find the right fix
119 if(dirty
& (NVFX_NEW_VIEWPORT
| NVFX_NEW_RAST
| NVFX_NEW_ZSA
) || (all_swizzled
>= 0))
121 nvfx_state_viewport_validate(nvfx
);
124 if(dirty
& NVFX_NEW_ZSA
|| (all_swizzled
>= 0))
127 OUT_RING(chan
, RING_3D(NV34TCL_DEPTH_WRITE_ENABLE
, 2));
128 OUT_RING(chan
, nvfx
->framebuffer
.zsbuf
&& nvfx
->zsa
->pipe
.depth
.writemask
);
129 OUT_RING(chan
, nvfx
->framebuffer
.zsbuf
&& nvfx
->zsa
->pipe
.depth
.enabled
);
134 // TODO: what about nv30?
138 OUT_RING(chan
, RING_3D(NV40TCL_TEX_CACHE_CTL
, 1));
140 OUT_RING(chan
, RING_3D(NV40TCL_TEX_CACHE_CTL
, 1));
145 nvfx
->dirty
= dirty
& still_dirty
;
147 render_temps
= nvfx
->state
.render_temps
;
150 for(int i
= 0; i
< nvfx
->framebuffer
.nr_cbufs
; ++i
)
152 if(render_temps
& (1 << i
))
153 util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(nvfx
->framebuffer
.cbufs
[i
]),
154 (struct util_dirty_surface
*)nvfx
->framebuffer
.cbufs
[i
]);
157 if(render_temps
& 0x80)
158 util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(nvfx
->framebuffer
.zsbuf
),
159 (struct util_dirty_surface
*)nvfx
->framebuffer
.zsbuf
);
166 nvfx_state_emit(struct nvfx_context
*nvfx
)
168 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
169 /* we need to ensure there is enough space to output relocations in one go */
170 unsigned max_relocs
= 0
171 + 16 /* vertex buffers, incl. dma flag */
172 + 2 /* index buffer plus format+dma flag */
173 + 2 * 5 /* 4 cbufs + zsbuf, plus dma objects */
174 + 2 * 16 /* fragment textures plus format+dma flag */
175 + 2 * 4 /* vertex textures plus format+dma flag */
176 + 1 /* fragprog incl dma flag */
178 MARK_RING(chan
, max_relocs
* 2, max_relocs
* 2);
179 nvfx_state_relocate(nvfx
);
183 nvfx_state_relocate(struct nvfx_context
*nvfx
)
185 nvfx_framebuffer_relocate(nvfx
);
186 nvfx_fragtex_relocate(nvfx
);
187 nvfx_fragprog_relocate(nvfx
);
188 if (nvfx
->render_mode
== HW
)
190 nvfx_vbo_relocate(nvfx
);
191 if(nvfx
->use_index_buffer
)
192 nvfx_idxbuf_relocate(nvfx
);
197 nvfx_state_validate(struct nvfx_context
*nvfx
)
199 boolean was_sw
= nvfx
->fallback_swtnl
? TRUE
: FALSE
;
201 if (nvfx
->render_mode
!= HW
) {
202 /* Don't even bother trying to go back to hw if none
203 * of the states that caused swtnl previously have changed.
205 if ((nvfx
->fallback_swtnl
& nvfx
->dirty
)
206 != nvfx
->fallback_swtnl
)
209 /* Attempt to go to hwtnl again */
210 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
213 nvfx
->render_mode
= HW
;
216 if(!nvfx_state_validate_common(nvfx
))
220 NOUVEAU_ERR("swtnl->hw\n");
226 nvfx_state_validate_swtnl(struct nvfx_context
*nvfx
)
228 struct draw_context
*draw
= nvfx
->draw
;
230 /* Setup for swtnl */
231 if (nvfx
->render_mode
== HW
) {
232 NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx
->fallback_swtnl
);
233 nvfx
->pipe
.flush(&nvfx
->pipe
, 0, NULL
);
234 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
237 nvfx
->render_mode
= SWTNL
;
240 if (nvfx
->draw_dirty
& NVFX_NEW_VERTPROG
)
241 draw_bind_vertex_shader(draw
, nvfx
->vertprog
->draw
);
243 if (nvfx
->draw_dirty
& NVFX_NEW_RAST
)
244 draw_set_rasterizer_state(draw
, &nvfx
->rasterizer
->pipe
,
247 if (nvfx
->draw_dirty
& NVFX_NEW_UCP
)
248 draw_set_clip_state(draw
, &nvfx
->clip
);
250 if (nvfx
->draw_dirty
& NVFX_NEW_VIEWPORT
)
251 draw_set_viewport_state(draw
, &nvfx
->viewport
);
253 if (nvfx
->draw_dirty
& NVFX_NEW_ARRAYS
) {
254 draw_set_vertex_buffers(draw
, nvfx
->vtxbuf_nr
, nvfx
->vtxbuf
);
255 draw_set_vertex_elements(draw
, nvfx
->vtxelt
->num_elements
, nvfx
->vtxelt
->pipe
);
258 nvfx_state_validate_common(nvfx
);
260 nvfx
->draw_dirty
= 0;