1 #include "nvfx_context.h"
2 #include "nvfx_state.h"
3 #include "draw/draw_context.h"
5 #define RENDER_STATES(name, vbo) \
6 static struct nvfx_state_entry *name##render_states[] = { \
7 &nvfx_state_framebuffer, \
8 &nvfx_state_rasterizer, \
10 &nvfx_state_stipple, \
11 &nvfx_state_fragprog, \
12 &nvfx_state_fragtex, \
13 &nvfx_state_vertprog, \
15 &nvfx_state_blend_colour, \
18 &nvfx_state_viewport, \
24 RENDER_STATES(swtnl_
, vtxfmt
);
27 nvfx_state_do_validate(struct nvfx_context
*nvfx
,
28 struct nvfx_state_entry
**states
)
31 struct nvfx_state_entry
*e
= *states
;
33 if (nvfx
->dirty
& e
->dirty
.pipe
) {
34 if (e
->validate(nvfx
))
35 nvfx
->state
.dirty
|= (1ULL << e
->dirty
.hw
);
44 nvfx_state_emit(struct nvfx_context
*nvfx
)
46 struct nvfx_state
*state
= &nvfx
->state
;
47 struct nvfx_screen
*screen
= nvfx
->screen
;
48 struct nouveau_channel
*chan
= screen
->base
.channel
;
49 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
53 /* XXX: race conditions
55 if (nvfx
!= screen
->cur_ctx
) {
56 for (i
= 0; i
< NVFX_STATE_MAX
; i
++) {
57 if (state
->hw
[i
] && screen
->state
[i
] != state
->hw
[i
])
58 state
->dirty
|= (1ULL << i
);
61 screen
->cur_ctx
= nvfx
;
64 for (i
= 0, states
= state
->dirty
; states
; i
++) {
65 if (!(states
& (1ULL << i
)))
67 so_ref (state
->hw
[i
], &nvfx
->screen
->state
[i
]);
69 so_emit(chan
, nvfx
->screen
->state
[i
]);
70 states
&= ~(1ULL << i
);
73 /* TODO: could nv30 need this or something similar too? */
75 if (state
->dirty
& ((1ULL << NVFX_STATE_FRAGPROG
) |
76 (1ULL << NVFX_STATE_FRAGTEX0
))) {
77 BEGIN_RING(chan
, eng3d
, NV40TCL_TEX_CACHE_CTL
, 1);
79 BEGIN_RING(chan
, eng3d
, NV40TCL_TEX_CACHE_CTL
, 1);
87 nvfx_state_flush_notify(struct nouveau_channel
*chan
)
89 struct nvfx_context
*nvfx
= chan
->user_private
;
90 struct nvfx_state
*state
= &nvfx
->state
;
93 so_emit_reloc_markers(chan
, state
->hw
[NVFX_STATE_FB
]);
94 for (i
= 0, samplers
= state
->fp_samplers
; i
< 16 && samplers
; i
++) {
95 if (!(samplers
& (1 << i
)))
97 so_emit_reloc_markers(chan
,
98 state
->hw
[NVFX_STATE_FRAGTEX0
+i
]);
99 samplers
&= ~(1ULL << i
);
101 so_emit_reloc_markers(chan
, state
->hw
[NVFX_STATE_FRAGPROG
]);
102 if (state
->hw
[NVFX_STATE_VTXBUF
] && nvfx
->render_mode
== HW
)
103 so_emit_reloc_markers(chan
, state
->hw
[NVFX_STATE_VTXBUF
]);
107 nvfx_state_validate(struct nvfx_context
*nvfx
)
109 boolean was_sw
= nvfx
->fallback_swtnl
? TRUE
: FALSE
;
111 if (nvfx
->render_mode
!= HW
) {
112 /* Don't even bother trying to go back to hw if none
113 * of the states that caused swtnl previously have changed.
115 if ((nvfx
->fallback_swtnl
& nvfx
->dirty
)
116 != nvfx
->fallback_swtnl
)
119 /* Attempt to go to hwtnl again */
120 nvfx
->pipe
.flush(&nvfx
->pipe
, 0, NULL
);
121 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
124 nvfx
->render_mode
= HW
;
127 nvfx_state_do_validate(nvfx
, render_states
);
129 if (nvfx
->fallback_swtnl
|| nvfx
->fallback_swrast
)
133 NOUVEAU_ERR("swtnl->hw\n");
139 nvfx_state_validate_swtnl(struct nvfx_context
*nvfx
)
141 struct draw_context
*draw
= nvfx
->draw
;
143 /* Setup for swtnl */
144 if (nvfx
->render_mode
== HW
) {
145 NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx
->fallback_swtnl
);
146 nvfx
->pipe
.flush(&nvfx
->pipe
, 0, NULL
);
147 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
150 nvfx
->render_mode
= SWTNL
;
153 if (nvfx
->draw_dirty
& NVFX_NEW_VERTPROG
)
154 draw_bind_vertex_shader(draw
, nvfx
->vertprog
->draw
);
156 if (nvfx
->draw_dirty
& NVFX_NEW_RAST
)
157 draw_set_rasterizer_state(draw
, &nvfx
->rasterizer
->pipe
);
159 if (nvfx
->draw_dirty
& NVFX_NEW_UCP
)
160 draw_set_clip_state(draw
, &nvfx
->clip
);
162 if (nvfx
->draw_dirty
& NVFX_NEW_VIEWPORT
)
163 draw_set_viewport_state(draw
, &nvfx
->viewport
);
165 if (nvfx
->draw_dirty
& NVFX_NEW_ARRAYS
) {
166 draw_set_vertex_buffers(draw
, nvfx
->vtxbuf_nr
, nvfx
->vtxbuf
);
167 draw_set_vertex_elements(draw
, nvfx
->vtxelt
->num_elements
, nvfx
->vtxelt
->pipe
);
170 nvfx_state_do_validate(nvfx
, swtnl_render_states
);
172 if (nvfx
->fallback_swrast
) {
173 NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx
->fallback_swrast
);
177 nvfx
->draw_dirty
= 0;