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 static boolean
6 nvfx_state_validate_common(struct nvfx_context *nvfx)
7 {
8 struct nouveau_channel* chan = nvfx->screen->base.channel;
9 unsigned dirty = nvfx->dirty;
10
11 if(nvfx != nvfx->screen->cur_ctx)
12 dirty = ~0;
13
14 if(nvfx->render_mode == HW)
15 {
16 if(dirty & (NVFX_NEW_VERTPROG | NVFX_NEW_VERTCONST | NVFX_NEW_UCP))
17 {
18 if(!nvfx_vertprog_validate(nvfx))
19 return FALSE;
20 }
21
22 if(dirty & (NVFX_NEW_ARRAYS))
23 {
24 if(!nvfx_vbo_validate(nvfx))
25 return FALSE;
26 }
27 }
28 else
29 {
30 /* TODO: this looks a bit misdesigned */
31 if(dirty & (NVFX_NEW_VERTPROG | NVFX_NEW_UCP))
32 nvfx_vertprog_validate(nvfx);
33
34 if(dirty & (NVFX_NEW_ARRAYS | NVFX_NEW_FRAGPROG))
35 nvfx_vtxfmt_validate(nvfx);
36 }
37
38 if(dirty & NVFX_NEW_FB)
39 nvfx_state_framebuffer_validate(nvfx);
40
41 if(dirty & NVFX_NEW_RAST)
42 sb_emit(chan, nvfx->rasterizer->sb, nvfx->rasterizer->sb_len);
43
44 if(dirty & NVFX_NEW_SCISSOR)
45 nvfx_state_scissor_validate(nvfx);
46
47 if(dirty & NVFX_NEW_STIPPLE)
48 nvfx_state_stipple_validate(nvfx);
49
50 if(dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST))
51 nvfx_fragprog_validate(nvfx);
52
53 if(dirty & NVFX_NEW_SAMPLER)
54 nvfx_fragtex_validate(nvfx);
55
56 if(dirty & NVFX_NEW_BLEND)
57 sb_emit(chan, nvfx->blend->sb, nvfx->blend->sb_len);
58
59 if(dirty & NVFX_NEW_BCOL)
60 nvfx_state_blend_colour_validate(nvfx);
61
62 if(dirty & NVFX_NEW_ZSA)
63 sb_emit(chan, nvfx->zsa->sb, nvfx->zsa->sb_len);
64
65 if(dirty & NVFX_NEW_SR)
66 nvfx_state_sr_validate(nvfx);
67
68 /* Having this depend on FB looks wrong, but it seems
69 necessary to make this work on nv3x
70 TODO: find the right fix
71 */
72 if(dirty & (NVFX_NEW_VIEWPORT | NVFX_NEW_FB))
73 nvfx_state_viewport_validate(nvfx);
74
75 /* TODO: could nv30 need this or something similar too? */
76 if((dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_SAMPLER)) && nvfx->is_nv4x) {
77 WAIT_RING(chan, 4);
78 OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
79 OUT_RING(chan, 2);
80 OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
81 OUT_RING(chan, 1);
82 }
83 nvfx->dirty = 0;
84 return TRUE;
85 }
86
87 void
88 nvfx_state_emit(struct nvfx_context *nvfx)
89 {
90 struct nouveau_channel* chan = nvfx->screen->base.channel;
91 /* we need to ensure there is enough space to output relocations in one go */
92 unsigned max_relocs = 0
93 + 16 /* vertex buffers, incl. dma flag */
94 + 2 /* index buffer plus format+dma flag */
95 + 2 * 5 /* 4 cbufs + zsbuf, plus dma objects */
96 + 2 * 16 /* fragment textures plus format+dma flag */
97 + 2 * 4 /* vertex textures plus format+dma flag */
98 + 1 /* fragprog incl dma flag */
99 ;
100 MARK_RING(chan, max_relocs * 2, max_relocs * 2);
101 nvfx_state_relocate(nvfx);
102 }
103
104 void
105 nvfx_state_relocate(struct nvfx_context *nvfx)
106 {
107 nvfx_framebuffer_relocate(nvfx);
108 nvfx_fragtex_relocate(nvfx);
109 nvfx_fragprog_relocate(nvfx);
110 if (nvfx->render_mode == HW)
111 nvfx_vbo_relocate(nvfx);
112 }
113
114 boolean
115 nvfx_state_validate(struct nvfx_context *nvfx)
116 {
117 boolean was_sw = nvfx->fallback_swtnl ? TRUE : FALSE;
118
119 if (nvfx->render_mode != HW) {
120 /* Don't even bother trying to go back to hw if none
121 * of the states that caused swtnl previously have changed.
122 */
123 if ((nvfx->fallback_swtnl & nvfx->dirty)
124 != nvfx->fallback_swtnl)
125 return FALSE;
126
127 /* Attempt to go to hwtnl again */
128 nvfx->dirty |= (NVFX_NEW_VIEWPORT |
129 NVFX_NEW_VERTPROG |
130 NVFX_NEW_ARRAYS);
131 nvfx->render_mode = HW;
132 }
133
134 if(!nvfx_state_validate_common(nvfx))
135 return FALSE;
136
137 if (was_sw)
138 NOUVEAU_ERR("swtnl->hw\n");
139
140 return TRUE;
141 }
142
143 boolean
144 nvfx_state_validate_swtnl(struct nvfx_context *nvfx)
145 {
146 struct draw_context *draw = nvfx->draw;
147
148 /* Setup for swtnl */
149 if (nvfx->render_mode == HW) {
150 NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx->fallback_swtnl);
151 nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
152 nvfx->dirty |= (NVFX_NEW_VIEWPORT |
153 NVFX_NEW_VERTPROG |
154 NVFX_NEW_ARRAYS);
155 nvfx->render_mode = SWTNL;
156 }
157
158 if (nvfx->draw_dirty & NVFX_NEW_VERTPROG)
159 draw_bind_vertex_shader(draw, nvfx->vertprog->draw);
160
161 if (nvfx->draw_dirty & NVFX_NEW_RAST)
162 draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe,
163 nvfx->rasterizer);
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 nvfx_state_validate_common(nvfx);
177
178 nvfx->draw_dirty = 0;
179 return TRUE;
180 }