1 #include "nvfx_context.h"
2 #include "nvfx_state.h"
3 #include "nvfx_resource.h"
4 #include "draw/draw_context.h"
7 nvfx_state_viewport_validate(struct nvfx_context
*nvfx
)
9 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
10 struct pipe_viewport_state
*vpt
= &nvfx
->viewport
;
13 if(nvfx
->render_mode
== HW
) {
14 OUT_RING(chan
, RING_3D(NV34TCL_VIEWPORT_TRANSLATE_X
, 8));
15 OUT_RINGf(chan
, vpt
->translate
[0]);
16 OUT_RINGf(chan
, vpt
->translate
[1]);
17 OUT_RINGf(chan
, vpt
->translate
[2]);
18 OUT_RINGf(chan
, vpt
->translate
[3]);
19 OUT_RINGf(chan
, vpt
->scale
[0]);
20 OUT_RINGf(chan
, vpt
->scale
[1]);
21 OUT_RINGf(chan
, vpt
->scale
[2]);
22 OUT_RINGf(chan
, vpt
->scale
[3]);
23 OUT_RING(chan
, RING_3D(0x1d78, 1));
26 OUT_RING(chan
, RING_3D(NV34TCL_VIEWPORT_TRANSLATE_X
, 8));
27 OUT_RINGf(chan
, 0.0f
);
28 OUT_RINGf(chan
, 0.0f
);
29 OUT_RINGf(chan
, 0.0f
);
30 OUT_RINGf(chan
, 0.0f
);
31 OUT_RINGf(chan
, 1.0f
);
32 OUT_RINGf(chan
, 1.0f
);
33 OUT_RINGf(chan
, 1.0f
);
34 OUT_RINGf(chan
, 1.0f
);
35 OUT_RING(chan
, RING_3D(0x1d78, 1));
36 OUT_RING(chan
, nvfx
->is_nv4x
? 0x110 : 1);
41 nvfx_state_scissor_validate(struct nvfx_context
*nvfx
)
43 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
44 struct pipe_rasterizer_state
*rast
= &nvfx
->rasterizer
->pipe
;
45 struct pipe_scissor_state
*s
= &nvfx
->scissor
;
47 if ((rast
->scissor
== 0 && nvfx
->state
.scissor_enabled
== 0))
49 nvfx
->state
.scissor_enabled
= rast
->scissor
;
52 OUT_RING(chan
, RING_3D(NV34TCL_SCISSOR_HORIZ
, 2));
53 if (nvfx
->state
.scissor_enabled
) {
54 OUT_RING(chan
, ((s
->maxx
- s
->minx
) << 16) | s
->minx
);
55 OUT_RING(chan
, ((s
->maxy
- s
->miny
) << 16) | s
->miny
);
57 OUT_RING(chan
, 4096 << 16);
58 OUT_RING(chan
, 4096 << 16);
63 nvfx_state_sr_validate(struct nvfx_context
*nvfx
)
65 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
66 struct pipe_stencil_ref
*sr
= &nvfx
->stencil_ref
;
69 OUT_RING(chan
, RING_3D(NV34TCL_STENCIL_FRONT_FUNC_REF
, 1));
70 OUT_RING(chan
, sr
->ref_value
[0]);
71 OUT_RING(chan
, RING_3D(NV34TCL_STENCIL_BACK_FUNC_REF
, 1));
72 OUT_RING(chan
, sr
->ref_value
[1]);
76 nvfx_state_blend_colour_validate(struct nvfx_context
*nvfx
)
78 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
79 struct pipe_blend_color
*bcol
= &nvfx
->blend_colour
;
82 OUT_RING(chan
, RING_3D(NV34TCL_BLEND_COLOR
, 1));
83 OUT_RING(chan
, ((float_to_ubyte(bcol
->color
[3]) << 24) |
84 (float_to_ubyte(bcol
->color
[0]) << 16) |
85 (float_to_ubyte(bcol
->color
[1]) << 8) |
86 (float_to_ubyte(bcol
->color
[2]) << 0)));
90 nvfx_state_stipple_validate(struct nvfx_context
*nvfx
)
92 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
95 OUT_RING(chan
, RING_3D(NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32));
96 OUT_RINGp(chan
, nvfx
->stipple
, 32);
100 nvfx_coord_conventions_validate(struct nvfx_context
* nvfx
)
102 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
103 unsigned value
= nvfx
->hw_fragprog
->coord_conventions
;
104 if(value
& NV34TCL_COORD_CONVENTIONS_ORIGIN_INVERTED
)
105 value
|= nvfx
->framebuffer
.height
<< NV34TCL_COORD_CONVENTIONS_HEIGHT_SHIFT
;
108 OUT_RING(chan
, RING_3D(NV34TCL_COORD_CONVENTIONS
, 1));
109 OUT_RING(chan
, value
);
113 nvfx_ucp_validate(struct nvfx_context
* nvfx
)
115 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
116 unsigned enables
[7] =
119 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
,
120 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1
,
121 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2
,
122 NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2
| NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3
,
123 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
,
124 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
,
127 if(!nvfx
->use_vp_clipping
)
130 OUT_RING(chan
, RING_3D(NV34TCL_VP_CLIP_PLANES_ENABLE
, 1));
133 WAIT_RING(chan
, 6 * 4 + 1);
134 OUT_RING(chan
, RING_3D(NV34TCL_VP_CLIP_PLANE_A(0), nvfx
->clip
.nr
* 4));
135 OUT_RINGp(chan
, &nvfx
->clip
.ucp
[0][0], nvfx
->clip
.nr
* 4);
139 OUT_RING(chan
, RING_3D(NV34TCL_VP_CLIP_PLANES_ENABLE
, 1));
140 OUT_RING(chan
, enables
[nvfx
->clip
.nr
]);
144 nvfx_vertprog_ucp_validate(struct nvfx_context
* nvfx
)
146 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
148 struct nvfx_vertex_program
* vp
= nvfx
->vertprog
;
149 if(nvfx
->clip
.nr
!= vp
->clip_nr
)
154 /* remove last instruction bit */
157 idx
= vp
->nr_insns
- 7 + vp
->clip_nr
;
158 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_FROM_ID
, 1));
159 OUT_RING(chan
, vp
->exec
->start
+ idx
);
160 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_INST(0), 4));
161 OUT_RINGp (chan
, vp
->insns
[idx
].data
, 4);
164 /* set last instruction bit */
165 idx
= vp
->nr_insns
- 7 + nvfx
->clip
.nr
;
166 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_FROM_ID
, 1));
167 OUT_RING(chan
, vp
->exec
->start
+ idx
);
168 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_INST(0), 4));
169 OUT_RINGp(chan
, vp
->insns
[idx
].data
, 3);
170 OUT_RING(chan
, vp
->insns
[idx
].data
[3] | 1);
171 vp
->clip_nr
= nvfx
->clip
.nr
;
174 // TODO: only do this for the ones changed
175 WAIT_RING(chan
, 6 * 6);
176 for(i
= 0; i
< nvfx
->clip
.nr
; ++i
)
178 OUT_RING(chan
, RING_3D(NV34TCL_VP_UPLOAD_CONST_ID
, 5));
179 OUT_RING(chan
, vp
->data
->start
+ i
);
180 OUT_RINGp (chan
, nvfx
->clip
.ucp
[i
], 4);
185 nvfx_state_validate_common(struct nvfx_context
*nvfx
)
187 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
189 unsigned still_dirty
= 0;
190 int new_fb_mode
= -1; /* 1 = all swizzled, 0 = make all linear */
191 boolean flush_tex_cache
= FALSE
;
192 unsigned render_temps
;
194 if(nvfx
!= nvfx
->screen
->cur_ctx
)
197 nvfx
->hw_vtxelt_nr
= 16;
198 nvfx
->hw_pointsprite_control
= -1;
199 nvfx
->hw_vp_output
= -1;
200 nvfx
->screen
->cur_ctx
= nvfx
;
201 nvfx
->relocs_needed
= NVFX_RELOCATE_ALL
;
204 /* These can trigger use the of 3D engine to copy temporaries.
205 * That will recurse here and thus dirty all 3D state, so we need to this before anything else, and in a loop..
206 * This converges to having clean temps, then binding both fragtexes and framebuffers.
208 while(nvfx
->dirty
& (NVFX_NEW_FB
| NVFX_NEW_SAMPLER
))
210 if(nvfx
->dirty
& NVFX_NEW_SAMPLER
)
212 nvfx
->dirty
&=~ NVFX_NEW_SAMPLER
;
213 nvfx_fragtex_validate(nvfx
);
215 // TODO: only set this if really necessary
216 flush_tex_cache
= TRUE
;
219 if(nvfx
->dirty
& NVFX_NEW_FB
)
221 nvfx
->dirty
&=~ NVFX_NEW_FB
;
222 new_fb_mode
= nvfx_framebuffer_prepare(nvfx
);
224 // TODO: make sure this doesn't happen, i.e. fbs have matching formats
225 assert(new_fb_mode
>= 0);
231 if(nvfx
->render_mode
== HW
)
233 if(dirty
& (NVFX_NEW_VERTPROG
| NVFX_NEW_VERTCONST
| NVFX_NEW_UCP
))
235 if(!nvfx_vertprog_validate(nvfx
))
239 if(dirty
& NVFX_NEW_ARRAYS
)
241 if(!nvfx_vbo_validate(nvfx
))
245 if(dirty
& NVFX_NEW_INDEX
)
247 if(nvfx
->use_index_buffer
)
248 nvfx_idxbuf_validate(nvfx
);
250 still_dirty
= NVFX_NEW_INDEX
;
255 /* TODO: this looks a bit misdesigned */
256 if(dirty
& (NVFX_NEW_VERTPROG
| NVFX_NEW_UCP
))
257 nvfx_vertprog_validate(nvfx
);
259 if(dirty
& (NVFX_NEW_ARRAYS
| NVFX_NEW_INDEX
| NVFX_NEW_FRAGPROG
))
260 nvfx_vtxfmt_validate(nvfx
);
263 if(dirty
& NVFX_NEW_RAST
)
264 sb_emit(chan
, nvfx
->rasterizer
->sb
, nvfx
->rasterizer
->sb_len
);
266 if(dirty
& NVFX_NEW_SCISSOR
)
267 nvfx_state_scissor_validate(nvfx
);
269 if(dirty
& NVFX_NEW_STIPPLE
)
270 nvfx_state_stipple_validate(nvfx
);
272 if(nvfx
->dirty
& NVFX_NEW_UCP
)
273 nvfx_ucp_validate(nvfx
);
275 if(nvfx
->use_vp_clipping
&& (nvfx
->dirty
& (NVFX_NEW_UCP
| NVFX_NEW_VERTPROG
)))
276 nvfx_vertprog_ucp_validate(nvfx
);
278 if(dirty
& (NVFX_NEW_FRAGPROG
| NVFX_NEW_FRAGCONST
| NVFX_NEW_VERTPROG
| NVFX_NEW_SPRITE
))
280 nvfx_fragprog_validate(nvfx
);
281 if(dirty
& NVFX_NEW_FRAGPROG
)
282 flush_tex_cache
= TRUE
; // TODO: do we need this?
287 unsigned vp_output
= nvfx
->vertprog
->or | nvfx
->hw_fragprog
->or;
288 vp_output
|= (1 << (nvfx
->clip
.nr
+ 6)) - (1 << 6);
290 if(vp_output
!= nvfx
->hw_vp_output
)
293 OUT_RING(chan
, RING_3D(NV40TCL_VP_RESULT_EN
, 1));
294 OUT_RING(chan
, vp_output
);
295 nvfx
->hw_vp_output
= vp_output
;
300 nvfx_framebuffer_validate(nvfx
, new_fb_mode
);
302 if(dirty
& NVFX_NEW_BLEND
)
303 sb_emit(chan
, nvfx
->blend
->sb
, nvfx
->blend
->sb_len
);
305 if(dirty
& NVFX_NEW_BCOL
)
306 nvfx_state_blend_colour_validate(nvfx
);
308 if(dirty
& NVFX_NEW_ZSA
)
309 sb_emit(chan
, nvfx
->zsa
->sb
, nvfx
->zsa
->sb_len
);
311 if(dirty
& NVFX_NEW_SR
)
312 nvfx_state_sr_validate(nvfx
);
314 /* All these dependencies are wrong, but otherwise
315 etracer, neverball, foobillard, glest totally misrender
316 TODO: find the right fix
318 if(dirty
& (NVFX_NEW_VIEWPORT
| NVFX_NEW_RAST
| NVFX_NEW_ZSA
) || (new_fb_mode
>= 0))
320 nvfx_state_viewport_validate(nvfx
);
323 if(dirty
& NVFX_NEW_ZSA
|| (new_fb_mode
>= 0))
326 OUT_RING(chan
, RING_3D(NV34TCL_DEPTH_WRITE_ENABLE
, 2));
327 OUT_RING(chan
, nvfx
->framebuffer
.zsbuf
&& nvfx
->zsa
->pipe
.depth
.writemask
);
328 OUT_RING(chan
, nvfx
->framebuffer
.zsbuf
&& nvfx
->zsa
->pipe
.depth
.enabled
);
331 if((new_fb_mode
>= 0) || (dirty
& NVFX_NEW_FRAGPROG
))
332 nvfx_coord_conventions_validate(nvfx
);
336 // TODO: what about nv30?
340 OUT_RING(chan
, RING_3D(NV40TCL_TEX_CACHE_CTL
, 1));
342 OUT_RING(chan
, RING_3D(NV40TCL_TEX_CACHE_CTL
, 1));
347 nvfx
->dirty
= dirty
& still_dirty
;
349 render_temps
= nvfx
->state
.render_temps
;
352 for(int i
= 0; i
< nvfx
->framebuffer
.nr_cbufs
; ++i
)
354 if(render_temps
& (1 << i
)) {
355 assert(((struct nvfx_surface
*)nvfx
->framebuffer
.cbufs
[i
])->temp
);
356 util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(nvfx
->framebuffer
.cbufs
[i
]),
357 (struct util_dirty_surface
*)nvfx
->framebuffer
.cbufs
[i
]);
361 if(render_temps
& 0x80) {
362 assert(((struct nvfx_surface
*)nvfx
->framebuffer
.zsbuf
)->temp
);
363 util_dirty_surface_set_dirty(nvfx_surface_get_dirty_surfaces(nvfx
->framebuffer
.zsbuf
),
364 (struct util_dirty_surface
*)nvfx
->framebuffer
.zsbuf
);
372 nvfx_state_relocate(struct nvfx_context
*nvfx
, unsigned relocs
)
374 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
375 /* we need to ensure there is enough space to output relocations in one go */
376 const unsigned max_relocs
= 0
377 + 16 /* vertex buffers, incl. dma flag */
378 + 2 /* index buffer plus format+dma flag */
379 + 2 * 5 /* 4 cbufs + zsbuf, plus dma objects */
380 + 2 * 16 /* fragment textures plus format+dma flag */
381 + 2 * 4 /* vertex textures plus format+dma flag */
382 + 1 /* fragprog incl dma flag */
385 MARK_RING(chan
, max_relocs
* 2, max_relocs
* 2);
387 if(relocs
& NVFX_RELOCATE_FRAMEBUFFER
)
388 nvfx_framebuffer_relocate(nvfx
);
389 if(relocs
& NVFX_RELOCATE_FRAGTEX
)
390 nvfx_fragtex_relocate(nvfx
);
391 if(relocs
& NVFX_RELOCATE_FRAGPROG
)
392 nvfx_fragprog_relocate(nvfx
);
393 if(relocs
& NVFX_RELOCATE_VTXBUF
)
394 nvfx_vbo_relocate(nvfx
);
395 if(relocs
& NVFX_RELOCATE_IDXBUF
)
396 nvfx_idxbuf_relocate(nvfx
);
400 nvfx_state_validate(struct nvfx_context
*nvfx
)
402 boolean was_sw
= nvfx
->fallback_swtnl
? TRUE
: FALSE
;
404 if (nvfx
->render_mode
!= HW
) {
405 /* Don't even bother trying to go back to hw if none
406 * of the states that caused swtnl previously have changed.
408 if ((nvfx
->fallback_swtnl
& nvfx
->dirty
)
409 != nvfx
->fallback_swtnl
)
412 /* Attempt to go to hwtnl again */
413 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
416 nvfx
->render_mode
= HW
;
419 if(!nvfx_state_validate_common(nvfx
))
426 nvfx_state_validate_swtnl(struct nvfx_context
*nvfx
)
428 struct draw_context
*draw
= nvfx
->draw
;
430 /* Setup for swtnl */
431 if (nvfx
->render_mode
== HW
) {
432 NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx
->fallback_swtnl
);
433 nvfx
->pipe
.flush(&nvfx
->pipe
, 0, NULL
);
434 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
437 nvfx
->render_mode
= SWTNL
;
440 if (nvfx
->draw_dirty
& NVFX_NEW_VERTPROG
)
441 draw_bind_vertex_shader(draw
, nvfx
->vertprog
->draw
);
443 if (nvfx
->draw_dirty
& NVFX_NEW_RAST
)
444 draw_set_rasterizer_state(draw
, &nvfx
->rasterizer
->pipe
,
447 if (nvfx
->draw_dirty
& NVFX_NEW_UCP
)
448 draw_set_clip_state(draw
, &nvfx
->clip
);
450 if (nvfx
->draw_dirty
& NVFX_NEW_VIEWPORT
)
451 draw_set_viewport_state(draw
, &nvfx
->viewport
);
453 if (nvfx
->draw_dirty
& NVFX_NEW_ARRAYS
) {
454 draw_set_vertex_buffers(draw
, nvfx
->vtxbuf_nr
, nvfx
->vtxbuf
);
455 draw_set_vertex_elements(draw
, nvfx
->vtxelt
->num_elements
, nvfx
->vtxelt
->pipe
);
458 if (nvfx
->draw_dirty
& NVFX_NEW_INDEX
)
459 draw_set_index_buffer(draw
, &nvfx
->idxbuf
);
461 nvfx_state_validate_common(nvfx
);
463 nvfx
->draw_dirty
= 0;