Merge branch '7.8'
[mesa.git] / src / gallium / drivers / nvfx / nvfx_state_emit.c
1 #include "nvfx_context.h"
2 #include "nvfx_state.h"
3 #include "draw/draw_context.h"
4
5 #define RENDER_STATES(name, vbo) \
6 static struct nvfx_state_entry *name##render_states[] = { \
7 &nvfx_state_framebuffer, \
8 &nvfx_state_rasterizer, \
9 &nvfx_state_scissor, \
10 &nvfx_state_stipple, \
11 &nvfx_state_fragprog, \
12 &nvfx_state_fragtex, \
13 &nvfx_state_vertprog, \
14 &nvfx_state_blend, \
15 &nvfx_state_blend_colour, \
16 &nvfx_state_zsa, \
17 &nvfx_state_sr, \
18 &nvfx_state_viewport, \
19 &nvfx_state_##vbo, \
20 NULL \
21 }
22
23 RENDER_STATES(, vbo);
24 RENDER_STATES(swtnl_, vtxfmt);
25
26 static void
27 nvfx_state_do_validate(struct nvfx_context *nvfx,
28 struct nvfx_state_entry **states)
29 {
30 while (*states) {
31 struct nvfx_state_entry *e = *states;
32
33 if (nvfx->dirty & e->dirty.pipe) {
34 if (e->validate(nvfx))
35 nvfx->state.dirty |= (1ULL << e->dirty.hw);
36 }
37
38 states++;
39 }
40 nvfx->dirty = 0;
41 }
42
43 void
44 nvfx_state_emit(struct nvfx_context *nvfx)
45 {
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;
50 unsigned i;
51 uint64_t states;
52
53 /* XXX: race conditions
54 */
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);
59 }
60
61 screen->cur_ctx = nvfx;
62 }
63
64 for (i = 0, states = state->dirty; states; i++) {
65 if (!(states & (1ULL << i)))
66 continue;
67 so_ref (state->hw[i], &nvfx->screen->state[i]);
68 if (state->hw[i])
69 so_emit(chan, nvfx->screen->state[i]);
70 states &= ~(1ULL << i);
71 }
72
73 /* TODO: could nv30 need this or something similar too? */
74 if(nvfx->is_nv4x) {
75 if (state->dirty & ((1ULL << NVFX_STATE_FRAGPROG) |
76 (1ULL << NVFX_STATE_FRAGTEX0))) {
77 BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
78 OUT_RING (chan, 2);
79 BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
80 OUT_RING (chan, 1);
81 }
82 }
83 state->dirty = 0;
84 }
85
86 void
87 nvfx_state_flush_notify(struct nouveau_channel *chan)
88 {
89 struct nvfx_context *nvfx = chan->user_private;
90 struct nvfx_state *state = &nvfx->state;
91 unsigned i, samplers;
92
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)))
96 continue;
97 so_emit_reloc_markers(chan,
98 state->hw[NVFX_STATE_FRAGTEX0+i]);
99 samplers &= ~(1ULL << i);
100 }
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]);
104 }
105
106 boolean
107 nvfx_state_validate(struct nvfx_context *nvfx)
108 {
109 boolean was_sw = nvfx->fallback_swtnl ? TRUE : FALSE;
110
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.
114 */
115 if ((nvfx->fallback_swtnl & nvfx->dirty)
116 != nvfx->fallback_swtnl)
117 return FALSE;
118
119 /* Attempt to go to hwtnl again */
120 nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
121 nvfx->dirty |= (NVFX_NEW_VIEWPORT |
122 NVFX_NEW_VERTPROG |
123 NVFX_NEW_ARRAYS);
124 nvfx->render_mode = HW;
125 }
126
127 nvfx_state_do_validate(nvfx, render_states);
128
129 if (nvfx->fallback_swtnl || nvfx->fallback_swrast)
130 return FALSE;
131
132 if (was_sw)
133 NOUVEAU_ERR("swtnl->hw\n");
134
135 return TRUE;
136 }
137
138 boolean
139 nvfx_state_validate_swtnl(struct nvfx_context *nvfx)
140 {
141 struct draw_context *draw = nvfx->draw;
142
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 |
148 NVFX_NEW_VERTPROG |
149 NVFX_NEW_ARRAYS);
150 nvfx->render_mode = SWTNL;
151 }
152
153 if (nvfx->draw_dirty & NVFX_NEW_VERTPROG)
154 draw_bind_vertex_shader(draw, nvfx->vertprog->draw);
155
156 if (nvfx->draw_dirty & NVFX_NEW_RAST)
157 draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe);
158
159 if (nvfx->draw_dirty & NVFX_NEW_UCP)
160 draw_set_clip_state(draw, &nvfx->clip);
161
162 if (nvfx->draw_dirty & NVFX_NEW_VIEWPORT)
163 draw_set_viewport_state(draw, &nvfx->viewport);
164
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);
168 }
169
170 nvfx_state_do_validate(nvfx, swtnl_render_states);
171
172 if (nvfx->fallback_swrast) {
173 NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx->fallback_swrast);
174 return FALSE;
175 }
176
177 nvfx->draw_dirty = 0;
178 return TRUE;
179 }