nv30, nv40: unify identical nv[34]0_state_rasterizer.c
[mesa.git] / src / gallium / drivers / nvfx / nvfx_state_emit.c
1 #include "nv30/nv30_context.h"
2 #include "nv40/nv40_context.h"
3 #include "nvfx_state.h"
4 #include "draw/draw_context.h"
5
6 #define RENDER_STATES(name, nvxx, vbo) \
7 static struct nvfx_state_entry *name##_render_states[] = { \
8 &nvxx##_state_framebuffer, \
9 &nvfx_state_rasterizer, \
10 &nvxx##_state_scissor, \
11 &nvxx##_state_stipple, \
12 &nvxx##_state_fragprog, \
13 &nvxx##_state_fragtex, \
14 &nvxx##_state_vertprog, \
15 &nvfx_state_blend, \
16 &nvfx_state_blend_colour, \
17 &nvxx##_state_zsa, \
18 &nvxx##_state_sr, \
19 &nvxx##_state_viewport, \
20 &nvxx##_state_##vbo, \
21 NULL \
22 }
23
24 RENDER_STATES(nv30, nv30, vbo);
25 RENDER_STATES(nv30_swtnl, nv30, vbo); /* TODO: replace with vtxfmt once draw is unified */
26 RENDER_STATES(nv40, nv40, vbo);
27 RENDER_STATES(nv40_swtnl, nv40, vtxfmt);
28
29 static void
30 nvfx_state_do_validate(struct nvfx_context *nvfx,
31 struct nvfx_state_entry **states)
32 {
33 while (*states) {
34 struct nvfx_state_entry *e = *states;
35
36 if (nvfx->dirty & e->dirty.pipe) {
37 if (e->validate(nvfx))
38 nvfx->state.dirty |= (1ULL << e->dirty.hw);
39 }
40
41 states++;
42 }
43 nvfx->dirty = 0;
44 }
45
46 void
47 nvfx_state_emit(struct nvfx_context *nvfx)
48 {
49 struct nvfx_state *state = &nvfx->state;
50 struct nvfx_screen *screen = nvfx->screen;
51 struct nouveau_channel *chan = screen->base.channel;
52 struct nouveau_grobj *eng3d = screen->eng3d;
53 unsigned i;
54 uint64_t states;
55
56 /* XXX: race conditions
57 */
58 if (nvfx != screen->cur_ctx) {
59 for (i = 0; i < NVFX_STATE_MAX; i++) {
60 if (state->hw[i] && screen->state[i] != state->hw[i])
61 state->dirty |= (1ULL << i);
62 }
63
64 screen->cur_ctx = nvfx;
65 }
66
67 for (i = 0, states = state->dirty; states; i++) {
68 if (!(states & (1ULL << i)))
69 continue;
70 so_ref (state->hw[i], &nvfx->screen->state[i]);
71 if (state->hw[i])
72 so_emit(chan, nvfx->screen->state[i]);
73 states &= ~(1ULL << i);
74 }
75
76 /* TODO: could nv30 need this or something similar too? */
77 if(nvfx->is_nv4x) {
78 if (state->dirty & ((1ULL << NVFX_STATE_FRAGPROG) |
79 (1ULL << NVFX_STATE_FRAGTEX0))) {
80 BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
81 OUT_RING (chan, 2);
82 BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
83 OUT_RING (chan, 1);
84 }
85 }
86 state->dirty = 0;
87 }
88
89 void
90 nvfx_state_flush_notify(struct nouveau_channel *chan)
91 {
92 struct nvfx_context *nvfx = chan->user_private;
93 struct nvfx_state *state = &nvfx->state;
94 unsigned i, samplers;
95
96 so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FB]);
97 for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
98 if (!(samplers & (1 << i)))
99 continue;
100 so_emit_reloc_markers(chan,
101 state->hw[NVFX_STATE_FRAGTEX0+i]);
102 samplers &= ~(1ULL << i);
103 }
104 so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FRAGPROG]);
105 if (state->hw[NVFX_STATE_VTXBUF] && nvfx->render_mode == HW)
106 so_emit_reloc_markers(chan, state->hw[NVFX_STATE_VTXBUF]);
107 }
108
109 boolean
110 nvfx_state_validate(struct nvfx_context *nvfx)
111 {
112 boolean was_sw = nvfx->fallback_swtnl ? TRUE : FALSE;
113
114 if (nvfx->render_mode != HW) {
115 /* Don't even bother trying to go back to hw if none
116 * of the states that caused swtnl previously have changed.
117 */
118 if ((nvfx->fallback_swtnl & nvfx->dirty)
119 != nvfx->fallback_swtnl)
120 return FALSE;
121
122 /* Attempt to go to hwtnl again */
123 nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
124 nvfx->dirty |= (NVFX_NEW_VIEWPORT |
125 NVFX_NEW_VERTPROG |
126 NVFX_NEW_ARRAYS);
127 nvfx->render_mode = HW;
128 }
129
130 if(!nvfx->is_nv4x)
131 nvfx_state_do_validate(nvfx, nv30_render_states);
132 else
133 nvfx_state_do_validate(nvfx, nv40_render_states);
134
135 if (nvfx->fallback_swtnl || nvfx->fallback_swrast)
136 return FALSE;
137
138 if (was_sw)
139 NOUVEAU_ERR("swtnl->hw\n");
140
141 return TRUE;
142 }
143
144 boolean
145 nvfx_state_validate_swtnl(struct nvfx_context *nvfx)
146 {
147 struct draw_context *draw = nvfx->draw;
148
149 /* Setup for swtnl */
150 if (nvfx->render_mode == HW) {
151 NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx->fallback_swtnl);
152 nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
153 nvfx->dirty |= (NVFX_NEW_VIEWPORT |
154 NVFX_NEW_VERTPROG |
155 NVFX_NEW_ARRAYS);
156 nvfx->render_mode = SWTNL;
157 }
158
159 if (nvfx->draw_dirty & NVFX_NEW_VERTPROG)
160 draw_bind_vertex_shader(draw, nvfx->vertprog->draw);
161
162 if (nvfx->draw_dirty & NVFX_NEW_RAST)
163 draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe);
164
165 if (nvfx->draw_dirty & NVFX_NEW_UCP)
166 draw_set_clip_state(draw, &nvfx->clip);
167
168 if (nvfx->draw_dirty & NVFX_NEW_VIEWPORT)
169 draw_set_viewport_state(draw, &nvfx->viewport);
170
171 if (nvfx->draw_dirty & NVFX_NEW_ARRAYS) {
172 draw_set_vertex_buffers(draw, nvfx->vtxbuf_nr, nvfx->vtxbuf);
173 draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe);
174 }
175
176 if(!nvfx->is_nv4x)
177 nvfx_state_do_validate(nvfx, nv30_swtnl_render_states);
178 else
179 nvfx_state_do_validate(nvfx, nv40_swtnl_render_states);
180
181 if (nvfx->fallback_swrast) {
182 NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx->fallback_swrast);
183 return FALSE;
184 }
185
186 nvfx->draw_dirty = 0;
187 return TRUE;
188 }