nvfx: so->RING_3D: fb
[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 /* we need to ensure there is enough space to output relocations in one go */
86 unsigned max_relocs = 0
87 + 16 /* vertex buffers, incl. dma flag */
88 + 2 /* index buffer plus format+dma flag */
89 + 2 * 5 /* 4 cbufs + zsbuf, plus dma objects */
90 + 2 * 16 /* fragment textures plus format+dma flag */
91 + 2 * 4 /* vertex textures plus format+dma flag */
92 + 1 /* fragprog incl dma flag */
93 ;
94 MARK_RING(chan, max_relocs * 2, max_relocs * 2);
95 nvfx_state_relocate(nvfx);
96 }
97
98 void
99 nvfx_state_relocate(struct nvfx_context *nvfx)
100 {
101 nvfx_framebuffer_relocate(nvfx);
102 nvfx_fragtex_relocate(nvfx);
103 nvfx_fragprog_relocate(nvfx);
104 if (nvfx->render_mode == HW)
105 nvfx_vbo_relocate(nvfx);
106 }
107
108 boolean
109 nvfx_state_validate(struct nvfx_context *nvfx)
110 {
111 boolean was_sw = nvfx->fallback_swtnl ? TRUE : FALSE;
112
113 if (nvfx->render_mode != HW) {
114 /* Don't even bother trying to go back to hw if none
115 * of the states that caused swtnl previously have changed.
116 */
117 if ((nvfx->fallback_swtnl & nvfx->dirty)
118 != nvfx->fallback_swtnl)
119 return FALSE;
120
121 /* Attempt to go to hwtnl again */
122 nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
123 nvfx->dirty |= (NVFX_NEW_VIEWPORT |
124 NVFX_NEW_VERTPROG |
125 NVFX_NEW_ARRAYS);
126 nvfx->render_mode = HW;
127 }
128
129 nvfx_state_do_validate(nvfx, render_states);
130
131 if (nvfx->fallback_swtnl || nvfx->fallback_swrast)
132 return FALSE;
133
134 if (was_sw)
135 NOUVEAU_ERR("swtnl->hw\n");
136
137 return TRUE;
138 }
139
140 boolean
141 nvfx_state_validate_swtnl(struct nvfx_context *nvfx)
142 {
143 struct draw_context *draw = nvfx->draw;
144
145 /* Setup for swtnl */
146 if (nvfx->render_mode == HW) {
147 NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx->fallback_swtnl);
148 nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
149 nvfx->dirty |= (NVFX_NEW_VIEWPORT |
150 NVFX_NEW_VERTPROG |
151 NVFX_NEW_ARRAYS);
152 nvfx->render_mode = SWTNL;
153 }
154
155 if (nvfx->draw_dirty & NVFX_NEW_VERTPROG)
156 draw_bind_vertex_shader(draw, nvfx->vertprog->draw);
157
158 if (nvfx->draw_dirty & NVFX_NEW_RAST)
159 draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe);
160
161 if (nvfx->draw_dirty & NVFX_NEW_UCP)
162 draw_set_clip_state(draw, &nvfx->clip);
163
164 if (nvfx->draw_dirty & NVFX_NEW_VIEWPORT)
165 draw_set_viewport_state(draw, &nvfx->viewport);
166
167 if (nvfx->draw_dirty & NVFX_NEW_ARRAYS) {
168 draw_set_vertex_buffers(draw, nvfx->vtxbuf_nr, nvfx->vtxbuf);
169 draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe);
170 }
171
172 nvfx_state_do_validate(nvfx, swtnl_render_states);
173
174 if (nvfx->fallback_swrast) {
175 NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx->fallback_swrast);
176 return FALSE;
177 }
178
179 nvfx->draw_dirty = 0;
180 return TRUE;
181 }