r300g: Remove is_r3xx
[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 if (nv50->vertprog && nv50->clip.nr > nv50->vertprog->vp.clpd_nr)
230 nv50->dirty |= NV50_NEW_VERTPROG;
231 }
232
233 static void
234 nv50_validate_blend(struct nv50_context *nv50)
235 {
236 struct nouveau_channel *chan = nv50->screen->base.channel;
237
238 WAIT_RING(chan, nv50->blend->size);
239 OUT_RINGp(chan, nv50->blend->state, nv50->blend->size);
240 }
241
242 static void
243 nv50_validate_zsa(struct nv50_context *nv50)
244 {
245 struct nouveau_channel *chan = nv50->screen->base.channel;
246
247 WAIT_RING(chan, nv50->zsa->size);
248 OUT_RINGp(chan, nv50->zsa->state, nv50->zsa->size);
249 }
250
251 static void
252 nv50_validate_rasterizer(struct nv50_context *nv50)
253 {
254 struct nouveau_channel *chan = nv50->screen->base.channel;
255
256 WAIT_RING(chan, nv50->rast->size);
257 OUT_RINGp(chan, nv50->rast->state, nv50->rast->size);
258 }
259
260 static void
261 nv50_switch_pipe_context(struct nv50_context *ctx_to)
262 {
263 struct nv50_context *ctx_from = ctx_to->screen->cur_ctx;
264
265 if (ctx_from)
266 ctx_to->state = ctx_from->state;
267
268 ctx_to->dirty = ~0;
269
270 if (!ctx_to->vertex)
271 ctx_to->dirty &= ~(NV50_NEW_VERTEX | NV50_NEW_ARRAYS);
272
273 if (!ctx_to->vertprog)
274 ctx_to->dirty &= ~NV50_NEW_VERTPROG;
275 if (!ctx_to->fragprog)
276 ctx_to->dirty &= ~NV50_NEW_FRAGPROG;
277
278 if (!ctx_to->blend)
279 ctx_to->dirty &= ~NV50_NEW_BLEND;
280 if (!ctx_to->rast)
281 ctx_to->dirty &= ~NV50_NEW_RASTERIZER;
282 if (!ctx_to->zsa)
283 ctx_to->dirty &= ~NV50_NEW_ZSA;
284
285 ctx_to->screen->base.channel->user_private = ctx_to->screen->cur_ctx =
286 ctx_to;
287 }
288
289 static struct state_validate {
290 void (*func)(struct nv50_context *);
291 uint32_t states;
292 } validate_list[] = {
293 { nv50_validate_fb, NV50_NEW_FRAMEBUFFER },
294 { nv50_validate_blend, NV50_NEW_BLEND },
295 { nv50_validate_zsa, NV50_NEW_ZSA },
296 { nv50_validate_rasterizer, NV50_NEW_RASTERIZER },
297 { nv50_validate_blend_colour, NV50_NEW_BLEND_COLOUR },
298 { nv50_validate_stencil_ref, NV50_NEW_STENCIL_REF },
299 { nv50_validate_stipple, NV50_NEW_STIPPLE },
300 #ifdef NV50_SCISSORS_CLIPPING
301 { nv50_validate_scissor, NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT |
302 NV50_NEW_RASTERIZER |
303 NV50_NEW_FRAMEBUFFER },
304 #else
305 { nv50_validate_scissor, NV50_NEW_SCISSOR },
306 #endif
307 { nv50_validate_viewport, NV50_NEW_VIEWPORT },
308 { nv50_validate_clip, NV50_NEW_CLIP },
309 { nv50_vertprog_validate, NV50_NEW_VERTPROG },
310 { nv50_gmtyprog_validate, NV50_NEW_GMTYPROG },
311 { nv50_fragprog_validate, NV50_NEW_FRAGPROG },
312 { nv50_fp_linkage_validate, NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
313 NV50_NEW_GMTYPROG },
314 { nv50_gp_linkage_validate, NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG },
315 { nv50_validate_derived_rs, NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER |
316 NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
317 { nv50_constbufs_validate, NV50_NEW_CONSTBUF },
318 { nv50_validate_textures, NV50_NEW_TEXTURES },
319 { nv50_validate_samplers, NV50_NEW_SAMPLERS },
320 { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS }
321 };
322 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
323
324 boolean
325 nv50_state_validate(struct nv50_context *nv50)
326 {
327 unsigned i;
328
329 if (nv50->screen->cur_ctx != nv50)
330 nv50_switch_pipe_context(nv50);
331
332 if (nv50->dirty) {
333 for (i = 0; i < validate_list_len; ++i) {
334 struct state_validate *validate = &validate_list[i];
335
336 if (nv50->dirty & validate->states)
337 validate->func(nv50);
338 }
339 nv50->dirty = 0;
340 }
341
342 nv50_bufctx_emit_relocs(nv50);
343
344 return TRUE;
345 }