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