ce52a3863e7ff869c07d92c7af9e4d2e51910f76
[mesa.git] / src / gallium / drivers / nv40 / nv40_state_emit.c
1 #include "nv40_context.h"
2 #include "nv40_state.h"
3
4 /* Emit relocs for every referenced buffer.
5 *
6 * This is to ensure the bufmgr has an accurate idea of how
7 * the buffer is used. These relocs appear in the push buffer as
8 * NOPs, and will only be turned into state changes if a buffer
9 * actually moves.
10 */
11 static void
12 nv40_state_emit_dummy_relocs(struct nv40_context *nv40)
13 {
14 unsigned i;
15
16 so_emit_reloc_markers(nv40->nvws, nv40->so_framebuffer);
17 for (i = 0; i < 16; i++) {
18 if (!(nv40->fp_samplers & (1 << i)))
19 continue;
20 so_emit_reloc_markers(nv40->nvws, nv40->so_fragtex[i]);
21 }
22 so_emit_reloc_markers(nv40->nvws, nv40->fragprog.active->so);
23 }
24
25 static boolean
26 nv40_state_scissor_validate(struct nv40_context *nv40)
27 {
28 struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
29 struct pipe_scissor_state *s = &nv40->pipe_state.scissor;
30 struct nouveau_stateobj *so;
31
32 if (nv40->state.scissor.so &&
33 (rast->scissor == 0 && nv40->state.scissor.enabled == 0))
34 return FALSE;
35
36 so = so_new(3, 0);
37 so_method(so, nv40->hw->curie, NV40TCL_SCISSOR_HORIZ, 2);
38 if (rast->scissor) {
39 so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
40 so_data (so, ((s->maxy - s->miny) << 16) | s->miny);
41 } else {
42 so_data (so, 4096 << 16);
43 so_data (so, 4096 << 16);
44 }
45
46 so_ref(so, &nv40->state.scissor.so);
47 so_ref(NULL, &so);
48 return TRUE;
49 }
50
51 static boolean
52 nv40_state_stipple_validate(struct nv40_context *nv40)
53 {
54 struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
55 struct nouveau_grobj *curie = nv40->hw->curie;
56 struct nouveau_stateobj *so;
57
58 if (nv40->state.stipple.so && (rast->poly_stipple_enable == 0 &&
59 nv40->state.stipple.enabled == 0))
60 return FALSE;
61
62 if (rast->poly_stipple_enable) {
63 unsigned i;
64
65 so = so_new(35, 0);
66 so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
67 so_data (so, 1);
68 so_method(so, curie, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 32);
69 for (i = 0; i < 32; i++)
70 so_data(so, nv40->pipe_state.stipple[i]);
71 } else {
72 so = so_new(2, 0);
73 so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1);
74 so_data (so, 0);
75 }
76
77 so_ref(so, &nv40->state.stipple.so);
78 so_ref(NULL, &so);
79 return TRUE;
80 }
81
82 static boolean
83 nv40_state_clip_validate(struct nv40_context *nv40)
84 {
85 if (nv40->pipe_state.clip.nr)
86 nv40->fallback |= NV40_FALLBACK_TNL;
87 return FALSE;
88 }
89
90 static struct nv40_state_entry states[] = {
91 {
92 .validate = nv40_state_scissor_validate,
93 .dirty = {
94 .pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST,
95 .hw = NV40_NEW_SCISSOR,
96 }
97 },
98 {
99 .validate = nv40_state_stipple_validate,
100 .dirty = {
101 .pipe = NV40_NEW_STIPPLE | NV40_NEW_RAST,
102 .hw = NV40_NEW_STIPPLE,
103 }
104 },
105 {
106 .validate = nv40_state_clip_validate,
107 .dirty = {
108 .pipe = NV40_NEW_UCP,
109 .hw = 0,
110 }
111 }
112 };
113
114 static void
115 nv40_state_validate(struct nv40_context *nv40)
116 {
117 unsigned i, last_fallback;
118
119 last_fallback = nv40->fallback;
120 nv40->fallback = 0;
121
122 for (i = 0; i < sizeof(states) / sizeof(states[0]); i++) {
123 if (nv40->dirty & states[i].dirty.pipe) {
124 if (states[i].validate(nv40))
125 nv40->hw_dirty |= states[i].dirty.hw;
126 }
127 }
128
129 if (nv40->fallback & NV40_FALLBACK_TNL &&
130 !(last_fallback & NV40_FALLBACK_TNL)) {
131 NOUVEAU_ERR("XXX: hwtnl->swtnl\n");
132 } else
133 if (last_fallback & NV40_FALLBACK_TNL &&
134 !(nv40->fallback & NV40_FALLBACK_TNL)) {
135 NOUVEAU_ERR("XXX: swtnl->hwtnl\n");
136 }
137 }
138
139 void
140 nv40_emit_hw_state(struct nv40_context *nv40)
141 {
142 nv40_state_validate(nv40);
143
144 if (nv40->dirty & NV40_NEW_FB)
145 so_emit(nv40->nvws, nv40->so_framebuffer);
146
147 if (nv40->dirty & NV40_NEW_BLEND)
148 so_emit(nv40->nvws, nv40->so_blend);
149
150 if (nv40->dirty & NV40_NEW_RAST)
151 so_emit(nv40->nvws, nv40->so_rast);
152
153 if (nv40->dirty & NV40_NEW_ZSA)
154 so_emit(nv40->nvws, nv40->so_zsa);
155
156 if (nv40->dirty & NV40_NEW_BCOL)
157 so_emit(nv40->nvws, nv40->so_bcol);
158
159 if (nv40->hw_dirty & NV40_NEW_SCISSOR) {
160 so_emit(nv40->nvws, nv40->state.scissor.so);
161 nv40->hw_dirty &= ~NV40_NEW_SCISSOR;
162 }
163
164 if (nv40->dirty & NV40_NEW_VIEWPORT)
165 so_emit(nv40->nvws, nv40->so_viewport);
166
167 if (nv40->hw_dirty & NV40_NEW_STIPPLE) {
168 so_emit(nv40->nvws, nv40->state.stipple.so);
169 nv40->hw_dirty &= ~NV40_NEW_STIPPLE;
170 }
171
172 if (nv40->dirty & NV40_NEW_FRAGPROG) {
173 nv40_fragprog_bind(nv40, nv40->fragprog.current);
174 /*XXX: clear NV40_NEW_FRAGPROG if no new program uploaded */
175 }
176
177 if (nv40->dirty_samplers || (nv40->dirty & NV40_NEW_FRAGPROG)) {
178 nv40_fragtex_bind(nv40);
179
180 BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
181 OUT_RING (2);
182 BEGIN_RING(curie, NV40TCL_TEX_CACHE_CTL, 1);
183 OUT_RING (1);
184 nv40->dirty &= ~NV40_NEW_FRAGPROG;
185 }
186
187 if (nv40->dirty & NV40_NEW_VERTPROG) {
188 nv40_vertprog_bind(nv40, nv40->vertprog.current);
189 nv40->dirty &= ~NV40_NEW_VERTPROG;
190 }
191
192 nv40->dirty_samplers = 0;
193 nv40->dirty = 0;
194
195 nv40_state_emit_dummy_relocs(nv40);
196 }
197