nv50_state_validate.c revision 857a3294a959015bf893241199f7fd7f7882a6ab
1/*
2 * Copyright 2008 Ben Skeggs
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include "nv50_context.h"
24#include "nouveau/nouveau_stateobj.h"
25
26static void
27nv50_state_validate_fb(struct nv50_context *nv50)
28{
29	struct nouveau_grobj *tesla = nv50->screen->tesla;
30	struct nouveau_stateobj *so = so_new(128, 18);
31	struct pipe_framebuffer_state *fb = &nv50->framebuffer;
32	unsigned i, w, h, gw = 0;
33
34	for (i = 0; i < fb->num_cbufs; i++) {
35		if (!gw) {
36			w = fb->cbufs[i]->width;
37			h = fb->cbufs[i]->height;
38			gw = 1;
39		} else {
40			assert(w == fb->cbufs[i]->width);
41			assert(h == fb->cbufs[i]->height);
42		}
43
44		so_method(so, tesla, NV50TCL_RT_HORIZ(i), 2);
45		so_data  (so, fb->cbufs[i]->width);
46		so_data  (so, fb->cbufs[i]->height);
47
48		so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5);
49		so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset,
50			  NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0);
51		so_reloc (so, fb->cbufs[i]->buffer, fb->cbufs[i]->offset,
52			  NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0);
53		switch (fb->cbufs[i]->format) {
54		case PIPE_FORMAT_A8R8G8B8_UNORM:
55			so_data(so, 0xcf);
56			break;
57		case PIPE_FORMAT_R5G6B5_UNORM:
58			so_data(so, 0xe8);
59			break;
60		default:
61			{
62				char fmt[128];
63				pf_sprint_name(fmt, fb->cbufs[i]->format);
64				NOUVEAU_ERR("AIIII unknown format %s\n", fmt);
65			}
66			so_data(so, 0xe6);
67			break;
68		}
69		so_data(so, 0x00000000);
70		so_data(so, 0x00000000);
71
72		so_method(so, tesla, 0x1224, 1);
73		so_data  (so, 1);
74	}
75
76	if (fb->zsbuf) {
77		if (!gw) {
78			w = fb->zsbuf->width;
79			h = fb->zsbuf->height;
80			gw = 1;
81		} else {
82			assert(w == fb->zsbuf->width);
83			assert(h == fb->zsbuf->height);
84		}
85
86		so_method(so, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5);
87		so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset,
88			  NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH, 0, 0);
89		so_reloc (so, fb->zsbuf->buffer, fb->zsbuf->offset,
90			  NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW, 0, 0);
91		switch (fb->zsbuf->format) {
92		case PIPE_FORMAT_Z24S8_UNORM:
93			so_data(so, 0x16);
94			break;
95		case PIPE_FORMAT_Z16_UNORM:
96			so_data(so, 0x15);
97			break;
98		default:
99			{
100				char fmt[128];
101				pf_sprint_name(fmt, fb->zsbuf->format);
102				NOUVEAU_ERR("AIIII unknown format %s\n", fmt);
103			}
104			so_data(so, 0x16);
105			break;
106		}
107		so_data(so, 0x00000000);
108		so_data(so, 0x00000000);
109
110		so_method(so, tesla, 0x1538, 1);
111		so_data  (so, 1);
112		so_method(so, tesla, 0x1228, 3);
113		so_data  (so, fb->zsbuf->width);
114		so_data  (so, fb->zsbuf->height);
115		so_data  (so, 0x00010001);
116	}
117
118	so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ, 2);
119	so_data  (so, w << 16);
120	so_data  (so, h << 16);
121	so_method(so, tesla, 0x0e04, 2);
122	so_data  (so, w << 16);
123	so_data  (so, h << 16);
124	so_method(so, tesla, 0xdf8, 2);
125	so_data  (so, 0);
126	so_data  (so, h);
127
128	so_ref(so, &nv50->state.fb);
129}
130
131static void
132nv50_state_emit(struct nv50_context *nv50)
133{
134	struct nv50_screen *screen = nv50->screen;
135	struct nouveau_winsys *nvws = screen->nvws;
136
137	if (nv50->pctx_id != screen->cur_pctx) {
138		nv50->state.dirty |= 0xffffffff;
139		screen->cur_pctx = nv50->pctx_id;
140	}
141
142	if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER)
143		so_emit(nvws, nv50->state.fb);
144	if (nv50->state.dirty & NV50_NEW_BLEND)
145		so_emit(nvws, nv50->state.blend);
146	if (nv50->state.dirty & NV50_NEW_ZSA)
147		so_emit(nvws, nv50->state.zsa);
148	if (nv50->state.dirty & NV50_NEW_VERTPROG)
149		so_emit(nvws, nv50->state.vertprog);
150	if (nv50->state.dirty & NV50_NEW_FRAGPROG)
151		so_emit(nvws, nv50->state.fragprog);
152	if (nv50->state.dirty & NV50_NEW_RASTERIZER)
153		so_emit(nvws, nv50->state.rast);
154	if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR)
155		so_emit(nvws, nv50->state.blend_colour);
156	if (nv50->state.dirty & NV50_NEW_STIPPLE)
157		so_emit(nvws, nv50->state.stipple);
158	if (nv50->state.dirty & NV50_NEW_SCISSOR)
159		so_emit(nvws, nv50->state.scissor);
160	if (nv50->state.dirty & NV50_NEW_VIEWPORT)
161		so_emit(nvws, nv50->state.viewport);
162	if (nv50->state.dirty & NV50_NEW_SAMPLER)
163		so_emit(nvws, nv50->state.tsc_upload);
164	if (nv50->state.dirty & NV50_NEW_TEXTURE)
165		so_emit(nvws, nv50->state.tic_upload);
166	if (nv50->state.dirty & NV50_NEW_ARRAYS) {
167		so_emit(nvws, nv50->state.vtxfmt);
168		so_emit(nvws, nv50->state.vtxbuf);
169	}
170	nv50->state.dirty = 0;
171
172	so_emit_reloc_markers(nvws, nv50->state.fb);
173	so_emit_reloc_markers(nvws, nv50->state.vertprog);
174	so_emit_reloc_markers(nvws, nv50->state.fragprog);
175	so_emit_reloc_markers(nvws, nv50->state.vtxbuf);
176	so_emit_reloc_markers(nvws, nv50->screen->static_init);
177}
178
179boolean
180nv50_state_validate(struct nv50_context *nv50)
181{
182	const struct pipe_framebuffer_state *fb = &nv50->framebuffer;
183	struct nouveau_grobj *tesla = nv50->screen->tesla;
184	struct nouveau_stateobj *so;
185	unsigned i;
186
187	for (i = 0; i < fb->num_cbufs; i++)
188		fb->cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED;
189
190	if (fb->zsbuf)
191		fb->zsbuf->status = PIPE_SURFACE_STATUS_DEFINED;
192
193	if (nv50->dirty & NV50_NEW_FRAMEBUFFER)
194		nv50_state_validate_fb(nv50);
195
196	if (nv50->dirty & NV50_NEW_BLEND)
197		so_ref(nv50->blend->so, &nv50->state.blend);
198
199	if (nv50->dirty & NV50_NEW_ZSA)
200		so_ref(nv50->zsa->so, &nv50->state.zsa);
201
202	if (nv50->dirty & (NV50_NEW_VERTPROG | NV50_NEW_VERTPROG_CB))
203		nv50_vertprog_validate(nv50);
204
205	if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB))
206		nv50_fragprog_validate(nv50);
207
208	if (nv50->dirty & NV50_NEW_RASTERIZER)
209		so_ref(nv50->rasterizer->so, &nv50->state.rast);
210
211	if (nv50->dirty & NV50_NEW_BLEND_COLOUR) {
212		so = so_new(5, 0);
213		so_method(so, tesla, NV50TCL_BLEND_COLOR(0), 4);
214		so_data  (so, fui(nv50->blend_colour.color[0]));
215		so_data  (so, fui(nv50->blend_colour.color[1]));
216		so_data  (so, fui(nv50->blend_colour.color[2]));
217		so_data  (so, fui(nv50->blend_colour.color[3]));
218		so_ref(so, &nv50->state.blend_colour);
219	}
220
221	if (nv50->dirty & NV50_NEW_STIPPLE) {
222		so = so_new(33, 0);
223		so_method(so, tesla, NV50TCL_POLYGON_STIPPLE_PATTERN(0), 32);
224		for (i = 0; i < 32; i++)
225			so_data(so, nv50->stipple.stipple[i]);
226		so_ref(so, &nv50->state.stipple);
227	}
228
229	if (nv50->dirty & (NV50_NEW_SCISSOR | NV50_NEW_RASTERIZER)) {
230		struct pipe_rasterizer_state *rast = &nv50->rasterizer->pipe;
231		struct pipe_scissor_state *s = &nv50->scissor;
232
233		if (nv50->state.scissor &&
234		    (rast->scissor == 0 && nv50->state.scissor_enabled == 0))
235			goto scissor_uptodate;
236		nv50->state.scissor_enabled = rast->scissor;
237
238		so = so_new(3, 0);
239		so_method(so, tesla, 0x0ff4, 2);
240		if (nv50->state.scissor_enabled) {
241			so_data(so, ((s->maxx - s->minx) << 16) | s->minx);
242			so_data(so, ((s->maxy - s->miny) << 16) | s->miny);
243		} else {
244			so_data(so, (8192 << 16));
245			so_data(so, (8192 << 16));
246		}
247		so_ref(so, &nv50->state.scissor);
248		nv50->state.dirty |= NV50_NEW_SCISSOR;
249	}
250scissor_uptodate:
251
252	if (nv50->dirty & NV50_NEW_VIEWPORT) {
253		unsigned bypass;
254
255		if (!nv50->rasterizer->pipe.bypass_clipping)
256			bypass = 0;
257		else
258			bypass = 1;
259
260		if (nv50->state.viewport &&
261		    (bypass || !(nv50->dirty & NV50_NEW_VIEWPORT)) &&
262		    nv50->state.viewport_bypass == bypass)
263			goto viewport_uptodate;
264		nv50->state.viewport_bypass = bypass;
265
266		so = so_new(12, 0);
267		if (!bypass) {
268			so_method(so, tesla, NV50TCL_VIEWPORT_UNK1(0), 3);
269			so_data  (so, fui(nv50->viewport.translate[0]));
270			so_data  (so, fui(nv50->viewport.translate[1]));
271			so_data  (so, fui(nv50->viewport.translate[2]));
272			so_method(so, tesla, NV50TCL_VIEWPORT_UNK0(0), 3);
273			so_data  (so, fui(nv50->viewport.scale[0]));
274			so_data  (so, fui(-nv50->viewport.scale[1]));
275			so_data  (so, fui(nv50->viewport.scale[2]));
276			so_method(so, tesla, 0x192c, 1);
277			so_data  (so, 1);
278			so_method(so, tesla, 0x0f90, 1);
279			so_data  (so, 0);
280		} else {
281			so_method(so, tesla, 0x192c, 1);
282			so_data  (so, 0);
283			so_method(so, tesla, 0x0f90, 1);
284			so_data  (so, 1);
285		}
286
287		so_ref(so, &nv50->state.viewport);
288	}
289viewport_uptodate:
290
291	if (nv50->dirty & NV50_NEW_SAMPLER) {
292		int i;
293
294		so = so_new(nv50->sampler_nr * 8 + 3, 0);
295		so_method(so, tesla, 0x0f00, 1);
296		so_data  (so, NV50_CB_TSC);
297		so_method(so, tesla, 0x40000f04, nv50->sampler_nr * 8);
298		for (i = 0; i < nv50->sampler_nr; i++)
299			so_datap (so, nv50->sampler[i], 8);
300		so_ref(so, &nv50->state.tsc_upload);
301	}
302
303	if (nv50->dirty & NV50_NEW_TEXTURE) {
304		int i;
305
306		so = so_new(nv50->miptree_nr * 8 + 3, nv50->miptree_nr * 2);
307		so_method(so, tesla, 0x0f00, 1);
308		so_data  (so, NV50_CB_TIC);
309		so_method(so, tesla, 0x40000f04, nv50->miptree_nr * 8);
310		for (i = 0; i < nv50->miptree_nr; i++) {
311			struct nv50_miptree *mt = nv50->miptree[i];
312
313			so_data (so, 0x2a712488);
314			so_reloc(so, mt->buffer, 0, NOUVEAU_BO_VRAM |
315				     NOUVEAU_BO_LOW, 0, 0);
316			so_data (so, 0xd0005000);
317			so_data (so, 0x00300000);
318			so_data (so, mt->base.width[0]);
319			so_data (so, (mt->base.depth[0] << 16) |
320				      mt->base.height[0]);
321			so_data (so, 0x03000000);
322			so_reloc(so, mt->buffer, 0, NOUVEAU_BO_VRAM |
323				     NOUVEAU_BO_HIGH, 0, 0);
324		}
325
326		so_ref(so, &nv50->state.tic_upload);
327	}
328
329	if (nv50->dirty & NV50_NEW_ARRAYS)
330		nv50_vbo_validate(nv50);
331
332	nv50->state.dirty |= nv50->dirty;
333	nv50->dirty = 0;
334	nv50_state_emit(nv50);
335
336	return TRUE;
337}
338
339