4ae58b156b6647bf6550d4a237fb8294e23892c2
[mesa.git] / src / gallium / drivers / nv50 / nv50_state_validate.c
1
2 #include "nv50_context.h"
3 #include "os/os_time.h"
4
5 static void
6 nv50_validate_fb(struct nv50_context *nv50)
7 {
8 struct nouveau_channel *chan = nv50->screen->base.channel;
9 struct pipe_framebuffer_state *fb = &nv50->framebuffer;
10 unsigned i;
11 boolean serialize = FALSE;
12
13 nv50_bufctx_reset(nv50, NV50_BUFCTX_FRAME);
14
15 BEGIN_RING(chan, RING_3D(RT_CONTROL), 1);
16 OUT_RING (chan, (076543210 << 4) | fb->nr_cbufs);
17 BEGIN_RING(chan, RING_3D(SCREEN_SCISSOR_HORIZ), 2);
18 OUT_RING (chan, fb->width << 16);
19 OUT_RING (chan, fb->height << 16);
20
21 MARK_RING(chan, 9 * fb->nr_cbufs, 2 * fb->nr_cbufs);
22
23 for (i = 0; i < fb->nr_cbufs; ++i) {
24 struct nv50_miptree *mt = nv50_miptree(fb->cbufs[i]->texture);
25 struct nv50_surface *sf = nv50_surface(fb->cbufs[i]);
26 struct nouveau_bo *bo = mt->base.bo;
27 uint32_t offset = sf->offset;
28
29 BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(i)), 5);
30 OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
31 OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
32 OUT_RING (chan, nv50_format_table[sf->base.format].rt);
33 OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
34 OUT_RING (chan, mt->layer_stride >> 2);
35 BEGIN_RING(chan, RING_3D(RT_HORIZ(i)), 2);
36 OUT_RING (chan, sf->width);
37 OUT_RING (chan, sf->height);
38 BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1);
39 OUT_RING (chan, sf->depth);
40
41 if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
42 serialize = TRUE;
43 mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
44 mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING;
45
46 /* only register for writing, otherwise we'd always serialize here */
47 nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base,
48 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
49 }
50
51 if (fb->zsbuf) {
52 struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
53 struct nv50_surface *sf = nv50_surface(fb->zsbuf);
54 struct nouveau_bo *bo = mt->base.bo;
55 int unk = mt->base.base.target == PIPE_TEXTURE_2D;
56 uint32_t offset = sf->offset;
57
58 MARK_RING (chan, 12, 2);
59 BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5);
60 OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
61 OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
62 OUT_RING (chan, nv50_format_table[fb->zsbuf->format].rt);
63 OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4);
64 OUT_RING (chan, mt->layer_stride >> 2);
65 BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
66 OUT_RING (chan, 1);
67 BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3);
68 OUT_RING (chan, sf->width);
69 OUT_RING (chan, sf->height);
70 OUT_RING (chan, (unk << 16) | sf->depth);
71
72 if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
73 serialize = TRUE;
74 mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
75 mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING;
76
77 nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base,
78 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
79 } else {
80 BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1);
81 OUT_RING (chan, 0);
82 }
83
84 BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2);
85 OUT_RING (chan, fb->width << 16);
86 OUT_RING (chan, fb->height << 16);
87
88 if (serialize) {
89 BEGIN_RING(chan, RING_3D(SERIALIZE), 1);
90 OUT_RING (chan, 0);
91 }
92 }
93
94 static void
95 nv50_validate_blend_colour(struct nv50_context *nv50)
96 {
97 struct nouveau_channel *chan = nv50->screen->base.channel;
98
99 BEGIN_RING(chan, RING_3D(BLEND_COLOR(0)), 4);
100 OUT_RINGf (chan, nv50->blend_colour.color[0]);
101 OUT_RINGf (chan, nv50->blend_colour.color[1]);
102 OUT_RINGf (chan, nv50->blend_colour.color[2]);
103 OUT_RINGf (chan, nv50->blend_colour.color[3]);
104 }
105
106 static void
107 nv50_validate_stencil_ref(struct nv50_context *nv50)
108 {
109 struct nouveau_channel *chan = nv50->screen->base.channel;
110
111 BEGIN_RING(chan, RING_3D(STENCIL_FRONT_FUNC_REF), 1);
112 OUT_RING (chan, nv50->stencil_ref.ref_value[0]);
113 BEGIN_RING(chan, RING_3D(STENCIL_BACK_FUNC_REF), 1);
114 OUT_RING (chan, nv50->stencil_ref.ref_value[1]);
115 }
116
117 static void
118 nv50_validate_stipple(struct nv50_context *nv50)
119 {
120 struct nouveau_channel *chan = nv50->screen->base.channel;
121 unsigned i;
122
123 BEGIN_RING(chan, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
124 for (i = 0; i < 32; ++i)
125 OUT_RING(chan, util_bswap32(nv50->stipple.stipple[i]));
126 }
127
128 static void
129 nv50_validate_scissor(struct nv50_context *nv50)
130 {
131 struct nouveau_channel *chan = nv50->screen->base.channel;
132 struct pipe_scissor_state *s = &nv50->scissor;
133 #ifdef NV50_SCISSORS_CLIPPING
134 struct pipe_viewport_state *vp = &nv50->viewport;
135 int minx, maxx, miny, maxy;
136
137 if (!(nv50->dirty &
138 (NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | NV50_NEW_FRAMEBUFFER)) &&
139 nv50->state.scissor == nv50->rast->pipe.scissor)
140 return;
141 nv50->state.scissor = nv50->rast->pipe.scissor;
142
143 if (nv50->state.scissor) {
144 minx = s->minx;
145 maxx = s->maxx;
146 miny = s->miny;
147 maxy = s->maxy;
148 } else {
149 minx = 0;
150 maxx = nv50->framebuffer.width;
151 miny = 0;
152 maxy = nv50->framebuffer.height;
153 }
154
155 minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
156 maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
157 miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
158 maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
159
160 BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
161 OUT_RING (chan, (maxx << 16) | minx);
162 OUT_RING (chan, (maxy << 16) | miny);
163 #else
164 BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2);
165 OUT_RING (chan, (s->maxx << 16) | s->minx);
166 OUT_RING (chan, (s->maxy << 16) | s->miny);
167 #endif
168 }
169
170 static void
171 nv50_validate_viewport(struct nv50_context *nv50)
172 {
173 struct nouveau_channel *chan = nv50->screen->base.channel;
174 float zmin, zmax;
175
176 BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
177 OUT_RINGf (chan, nv50->viewport.translate[0]);
178 OUT_RINGf (chan, nv50->viewport.translate[1]);
179 OUT_RINGf (chan, nv50->viewport.translate[2]);
180 BEGIN_RING(chan, RING_3D(VIEWPORT_SCALE_X(0)), 3);
181 OUT_RINGf (chan, nv50->viewport.scale[0]);
182 OUT_RINGf (chan, nv50->viewport.scale[1]);
183 OUT_RINGf (chan, nv50->viewport.scale[2]);
184
185 zmin = nv50->viewport.translate[2] - fabsf(nv50->viewport.scale[2]);
186 zmax = nv50->viewport.translate[2] + fabsf(nv50->viewport.scale[2]);
187
188 #ifdef NV50_SCISSORS_CLIPPING
189 BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
190 OUT_RINGf (chan, zmin);
191 OUT_RINGf (chan, zmax);
192 #endif
193 }
194
195 static void
196 nv50_validate_clip(struct nv50_context *nv50)
197 {
198 struct nouveau_channel *chan = nv50->screen->base.channel;
199 uint32_t clip;
200
201 if (nv50->clip.depth_clamp) {
202 clip =
203 NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR |
204 NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR |
205 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1;
206 } else {
207 clip = 0;
208 }
209
210 #ifndef NV50_SCISSORS_CLIPPING
211 clip |=
212 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK7 |
213 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1;
214 #endif
215
216 BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1);
217 OUT_RING (chan, clip);
218
219 if (nv50->clip.nr) {
220 BEGIN_RING(chan, RING_3D(CB_ADDR), 1);
221 OUT_RING (chan, (0 << 8) | NV50_CB_AUX);
222 BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nv50->clip.nr * 4);
223 OUT_RINGp (chan, &nv50->clip.ucp[0][0], nv50->clip.nr * 4);
224 }
225
226 BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1);
227 OUT_RING (chan, (1 << nv50->clip.nr) - 1);
228 }
229
230 static void
231 nv50_validate_blend(struct nv50_context *nv50)
232 {
233 struct nouveau_channel *chan = nv50->screen->base.channel;
234
235 WAIT_RING(chan, nv50->blend->size);
236 OUT_RINGp(chan, nv50->blend->state, nv50->blend->size);
237 }
238
239 static void
240 nv50_validate_zsa(struct nv50_context *nv50)
241 {
242 struct nouveau_channel *chan = nv50->screen->base.channel;
243
244 WAIT_RING(chan, nv50->zsa->size);
245 OUT_RINGp(chan, nv50->zsa->state, nv50->zsa->size);
246 }
247
248 static void
249 nv50_validate_rasterizer(struct nv50_context *nv50)
250 {
251 struct nouveau_channel *chan = nv50->screen->base.channel;
252
253 WAIT_RING(chan, nv50->rast->size);
254 OUT_RINGp(chan, nv50->rast->state, nv50->rast->size);
255 }
256
257 static struct state_validate {
258 void (*func)(struct nv50_context *);
259 uint32_t states;
260 } validate_list[] = {
261 { nv50_validate_fb, NV50_NEW_FRAMEBUFFER },
262 { nv50_validate_blend, NV50_NEW_BLEND },
263 { nv50_validate_zsa, NV50_NEW_ZSA },
264 { nv50_validate_rasterizer, NV50_NEW_RASTERIZER },
265 { nv50_validate_blend_colour, NV50_NEW_BLEND_COLOUR },
266 { nv50_validate_stencil_ref, NV50_NEW_STENCIL_REF },
267 { nv50_validate_stipple, NV50_NEW_STIPPLE },
268 #ifdef NV50_SCISSORS_CLIPPING
269 { nv50_validate_scissor, NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT |
270 NV50_NEW_RASTERIZER |
271 NV50_NEW_FRAMEBUFFER },
272 #else
273 { nv50_validate_scissor, NV50_NEW_SCISSOR },
274 #endif
275 { nv50_validate_viewport, NV50_NEW_VIEWPORT },
276 { nv50_validate_clip, NV50_NEW_CLIP },
277 { nv50_vertprog_validate, NV50_NEW_VERTPROG },
278 { nv50_gmtyprog_validate, NV50_NEW_GMTYPROG },
279 { nv50_fragprog_validate, NV50_NEW_FRAGPROG },
280 { nv50_fp_linkage_validate, NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
281 NV50_NEW_GMTYPROG },
282 { nv50_gp_linkage_validate, NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG },
283 { nv50_sprite_coords_validate, NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER |
284 NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
285 { nv50_constbufs_validate, NV50_NEW_CONSTBUF },
286 { nv50_validate_textures, NV50_NEW_TEXTURES },
287 { nv50_validate_samplers, NV50_NEW_SAMPLERS },
288 { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS }
289 };
290 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
291
292 boolean
293 nv50_state_validate(struct nv50_context *nv50)
294 {
295 unsigned i;
296 #if 0
297 if (nv50->screen->cur_ctx != nv50) /* FIXME: not everything is valid */
298 nv50->dirty = 0xffffffff;
299 #endif
300 nv50->screen->cur_ctx = nv50;
301
302 if (nv50->dirty) {
303 for (i = 0; i < validate_list_len; ++i) {
304 struct state_validate *validate = &validate_list[i];
305
306 if (nv50->dirty & validate->states)
307 validate->func(nv50);
308 }
309 nv50->dirty = 0;
310 }
311
312 nv50_bufctx_emit_relocs(nv50);
313
314 return TRUE;
315 }