Merge branch 'upstream-gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / mesa / pipe / nv30 / nv30_context.c
1 #include "pipe/draw/draw_context.h"
2 #include "pipe/p_defines.h"
3 #include "pipe/p_winsys.h"
4 #include "pipe/p_util.h"
5
6 #include "nv30_context.h"
7
8 static const char *
9 nv30_get_name(struct pipe_context *pipe)
10 {
11 struct nv30_context *nv30 = nv30_context(pipe);
12 static char buffer[128];
13
14 snprintf(buffer, sizeof(buffer), "NV%02X", nv30->chipset);
15 return buffer;
16 }
17
18 static const char *
19 nv30_get_vendor(struct pipe_context *pipe)
20 {
21 return "nouveau";
22 }
23
24 static int
25 nv30_get_param(struct pipe_context *pipe, int param)
26 {
27 switch (param) {
28 case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
29 return 16;
30 case PIPE_CAP_NPOT_TEXTURES:
31 return 0;
32 case PIPE_CAP_TWO_SIDED_STENCIL:
33 return 1;
34 case PIPE_CAP_GLSL:
35 return 0;
36 case PIPE_CAP_S3TC:
37 return 0;
38 case PIPE_CAP_ANISOTROPIC_FILTER:
39 return 1;
40 case PIPE_CAP_POINT_SPRITE:
41 return 1;
42 case PIPE_CAP_MAX_RENDER_TARGETS:
43 return 2;
44 case PIPE_CAP_OCCLUSION_QUERY:
45 return 1;
46 case PIPE_CAP_TEXTURE_SHADOW_MAP:
47 return 1;
48 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
49 return 13;
50 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
51 return 10;
52 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
53 return 13;
54 default:
55 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
56 return 0;
57 }
58 }
59
60 static float
61 nv30_get_paramf(struct pipe_context *pipe, int param)
62 {
63 switch (param) {
64 case PIPE_CAP_MAX_LINE_WIDTH:
65 case PIPE_CAP_MAX_LINE_WIDTH_AA:
66 return 10.0;
67 case PIPE_CAP_MAX_POINT_WIDTH:
68 case PIPE_CAP_MAX_POINT_WIDTH_AA:
69 return 64.0;
70 case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
71 return 16.0;
72 case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
73 return 4.0;
74 case PIPE_CAP_BITMAP_TEXCOORD_BIAS:
75 return 0.0;
76 default:
77 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
78 return 0.0;
79 }
80 }
81
82 static void
83 nv30_flush(struct pipe_context *pipe, unsigned flags)
84 {
85 struct nv30_context *nv30 = nv30_context(pipe);
86 struct nouveau_winsys *nvws = nv30->nvws;
87
88 if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
89 BEGIN_RING(rankine, 0x1fd8, 1);
90 OUT_RING (2);
91 BEGIN_RING(rankine, 0x1fd8, 1);
92 OUT_RING (1);
93 }
94
95 if (flags & PIPE_FLUSH_WAIT) {
96 nvws->notifier_reset(nv30->sync, 0);
97 BEGIN_RING(rankine, 0x104, 1);
98 OUT_RING (0);
99 BEGIN_RING(rankine, 0x100, 1);
100 OUT_RING (0);
101 }
102
103 FIRE_RING();
104
105 if (flags & PIPE_FLUSH_WAIT)
106 nvws->notifier_wait(nv30->sync, 0, 0, 2000);
107 }
108
109 static void
110 nv30_destroy(struct pipe_context *pipe)
111 {
112 struct nv30_context *nv30 = nv30_context(pipe);
113 struct nouveau_winsys *nvws = nv30->nvws;
114
115 if (nv30->draw)
116 draw_destroy(nv30->draw);
117
118 nvws->res_free(&nv30->vertprog.exec_heap);
119 nvws->res_free(&nv30->vertprog.data_heap);
120
121 nvws->res_free(&nv30->query_heap);
122 nvws->notifier_free(&nv30->query);
123
124 nvws->notifier_free(&nv30->sync);
125
126 nvws->grobj_free(&nv30->rankine);
127
128 free(nv30);
129 }
130
131 static boolean
132 nv30_init_hwctx(struct nv30_context *nv30, int rankine_class)
133 {
134 struct nouveau_winsys *nvws = nv30->nvws;
135 int ret;
136 int i;
137
138 ret = nvws->grobj_alloc(nvws, rankine_class, &nv30->rankine);
139 if (ret) {
140 NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
141 return FALSE;
142 }
143
144 BEGIN_RING(rankine, NV34TCL_DMA_NOTIFY, 1);
145 OUT_RING (nv30->sync->handle);
146 BEGIN_RING(rankine, NV34TCL_DMA_TEXTURE0, 2);
147 OUT_RING (nvws->channel->vram->handle);
148 OUT_RING (nvws->channel->gart->handle);
149 BEGIN_RING(rankine, NV34TCL_DMA_COLOR1, 1);
150 OUT_RING (nvws->channel->vram->handle);
151 BEGIN_RING(rankine, NV34TCL_DMA_COLOR0, 2);
152 OUT_RING (nvws->channel->vram->handle);
153 OUT_RING (nvws->channel->vram->handle);
154 BEGIN_RING(rankine, NV34TCL_DMA_VTXBUF0, 2);
155 OUT_RING (nvws->channel->vram->handle);
156 OUT_RING (nvws->channel->gart->handle);
157 /* BEGIN_RING(rankine, NV34TCL_DMA_FENCE, 2);
158 OUT_RING (0);
159 OUT_RING (nv30->query->handle);*/
160 BEGIN_RING(rankine, NV34TCL_DMA_IN_MEMORY7, 1);
161 OUT_RING (nvws->channel->vram->handle);
162 BEGIN_RING(rankine, NV34TCL_DMA_IN_MEMORY8, 1);
163 OUT_RING (nvws->channel->vram->handle);
164
165 for (i=1; i<8; i++) {
166 BEGIN_RING(rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1);
167 OUT_RING (0);
168 BEGIN_RING(rankine, NV34TCL_VIEWPORT_CLIP_VERT(i), 1);
169 OUT_RING (0);
170 }
171
172 BEGIN_RING(rankine, 0x220, 1);
173 OUT_RING (1);
174
175 BEGIN_RING(rankine, 0x03b0, 1);
176 OUT_RING (0x00100000);
177 BEGIN_RING(rankine, 0x1454, 1);
178 OUT_RING (0);
179 BEGIN_RING(rankine, 0x1d80, 1);
180 OUT_RING (3);
181 BEGIN_RING(rankine, 0x1450, 1);
182 OUT_RING (0x00030004);
183
184 /* NEW */
185 BEGIN_RING(rankine, 0x1e98, 1);
186 OUT_RING (0);
187 BEGIN_RING(rankine, 0x17e0, 3);
188 OUT_RING (0);
189 OUT_RING (0);
190 OUT_RING (0x3f800000);
191 BEGIN_RING(rankine, 0x1f80, 16);
192 OUT_RING (0); OUT_RING (0); OUT_RING (0); OUT_RING (0);
193 OUT_RING (0); OUT_RING (0); OUT_RING (0); OUT_RING (0);
194 OUT_RING (0x0000ffff);
195 OUT_RING (0); OUT_RING (0); OUT_RING (0); OUT_RING (0);
196 OUT_RING (0); OUT_RING (0); OUT_RING (0);
197
198 BEGIN_RING(rankine, 0x120, 3);
199 OUT_RING (0);
200 OUT_RING (1);
201 OUT_RING (2);
202
203 BEGIN_RING(rankine, 0x1d88, 1);
204 OUT_RING (0x00001200);
205
206 BEGIN_RING(rankine, NV34TCL_RC_ENABLE, 1);
207 OUT_RING (0);
208
209 /* Attempt to setup a known state.. Probably missing a heap of
210 * stuff here..
211 */
212 BEGIN_RING(rankine, NV34TCL_STENCIL_FRONT_ENABLE, 1);
213 OUT_RING (0);
214 BEGIN_RING(rankine, NV34TCL_STENCIL_BACK_ENABLE, 1);
215 OUT_RING (0);
216 BEGIN_RING(rankine, NV34TCL_ALPHA_FUNC_ENABLE, 1);
217 OUT_RING (0);
218 BEGIN_RING(rankine, NV34TCL_DEPTH_WRITE_ENABLE, 2);
219 OUT_RING (0); /* wr disable */
220 OUT_RING (0); /* test disable */
221 BEGIN_RING(rankine, NV34TCL_COLOR_MASK, 1);
222 OUT_RING (0x01010101); /* TR,TR,TR,TR */
223 BEGIN_RING(rankine, NV34TCL_CULL_FACE_ENABLE, 1);
224 OUT_RING (0);
225 BEGIN_RING(rankine, NV34TCL_BLEND_FUNC_ENABLE, 5);
226 OUT_RING (0); /* Blend enable */
227 OUT_RING (0); /* Blend src */
228 OUT_RING (0); /* Blend dst */
229 OUT_RING (0x00000000); /* Blend colour */
230 OUT_RING (0x8006); /* FUNC_ADD */
231 BEGIN_RING(rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2);
232 OUT_RING (0);
233 OUT_RING (0x1503 /*GL_COPY*/);
234 BEGIN_RING(rankine, NV34TCL_DITHER_ENABLE, 1);
235 OUT_RING (1);
236 BEGIN_RING(rankine, NV34TCL_SHADE_MODEL, 1);
237 OUT_RING (0x1d01 /*GL_SMOOTH*/);
238 BEGIN_RING(rankine, NV34TCL_POLYGON_OFFSET_FACTOR,2);
239 OUT_RINGf (0.0);
240 OUT_RINGf (0.0);
241 BEGIN_RING(rankine, NV34TCL_POLYGON_MODE_FRONT, 2);
242 OUT_RING (0x1b02 /*GL_FILL*/);
243 OUT_RING (0x1b02 /*GL_FILL*/);
244 /* - Disable texture units
245 * - Set fragprog to MOVR result.color, fragment.color */
246 for (i=0;i<16;i++) {
247 BEGIN_RING(rankine,
248 NV34TCL_TX_ENABLE(i), 1);
249 OUT_RING (0);
250 }
251 /* Polygon stipple */
252 BEGIN_RING(rankine,
253 NV34TCL_POLYGON_STIPPLE_PATTERN(0), 0x20);
254 for (i=0;i<0x20;i++)
255 OUT_RING (0xFFFFFFFF);
256
257 int w=4096;
258 int h=4096;
259 int pitch=4096*4;
260 BEGIN_RING(rankine, NV34TCL_RT_HORIZ, 5);
261 OUT_RING (w<<16);
262 OUT_RING (h<<16);
263 OUT_RING (0x148); /* format */
264 OUT_RING (pitch << 16 | pitch);
265 OUT_RING (0x0);
266 BEGIN_RING(rankine, 0x0a00, 2);
267 OUT_RING ((w<<16) | 0);
268 OUT_RING ((h<<16) | 0);
269 BEGIN_RING(rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2);
270 OUT_RING ((w-1)<<16);
271 OUT_RING ((h-1)<<16);
272 BEGIN_RING(rankine, NV34TCL_SCISSOR_HORIZ, 2);
273 OUT_RING (w<<16);
274 OUT_RING (h<<16);
275 BEGIN_RING(rankine, NV34TCL_VIEWPORT_HORIZ, 2);
276 OUT_RING (w<<16);
277 OUT_RING (h<<16);
278
279 BEGIN_RING(rankine, NV34TCL_VIEWPORT_TRANSLATE_X, 8);
280 OUT_RINGf (0.0);
281 OUT_RINGf (0.0);
282 OUT_RINGf (0.0);
283 OUT_RINGf (0.0);
284 OUT_RINGf (1.0);
285 OUT_RINGf (1.0);
286 OUT_RINGf (1.0);
287 OUT_RINGf (0.0);
288
289 BEGIN_RING(rankine, NV34TCL_MODELVIEW_MATRIX(0), 16);
290 OUT_RINGf (1.0);
291 OUT_RINGf (0.0);
292 OUT_RINGf (0.0);
293 OUT_RINGf (0.0);
294 OUT_RINGf (0.0);
295 OUT_RINGf (1.0);
296 OUT_RINGf (0.0);
297 OUT_RINGf (0.0);
298 OUT_RINGf (0.0);
299 OUT_RINGf (0.0);
300 OUT_RINGf (1.0);
301 OUT_RINGf (0.0);
302 OUT_RINGf (0.0);
303 OUT_RINGf (0.0);
304 OUT_RINGf (0.0);
305 OUT_RINGf (1.0);
306
307 BEGIN_RING(rankine, NV34TCL_PROJECTION_MATRIX(0), 16);
308 OUT_RINGf (1.0);
309 OUT_RINGf (0.0);
310 OUT_RINGf (0.0);
311 OUT_RINGf (0.0);
312 OUT_RINGf (0.0);
313 OUT_RINGf (1.0);
314 OUT_RINGf (0.0);
315 OUT_RINGf (0.0);
316 OUT_RINGf (0.0);
317 OUT_RINGf (0.0);
318 OUT_RINGf (1.0);
319 OUT_RINGf (0.0);
320 OUT_RINGf (0.0);
321 OUT_RINGf (0.0);
322 OUT_RINGf (0.0);
323 OUT_RINGf (1.0);
324
325 BEGIN_RING(rankine, NV34TCL_SCISSOR_HORIZ, 2);
326 OUT_RING (4096<<16);
327 OUT_RING (4096<<16);
328
329 BEGIN_RING(rankine, NV34TCL_MULTISAMPLE_CONTROL, 1);
330 OUT_RING (0xffff0000);
331
332 FIRE_RING ();
333 return TRUE;
334 }
335
336 #define NV30TCL_CHIPSET_3X_MASK 0x00000003
337 #define NV34TCL_CHIPSET_3X_MASK 0x00000010
338 #define NV35TCL_CHIPSET_3X_MASK 0x000001e0
339
340 struct pipe_context *
341 nv30_create(struct pipe_winsys *pipe_winsys, struct nouveau_winsys *nvws,
342 unsigned chipset)
343 {
344 struct nv30_context *nv30;
345 int rankine_class = 0, ret;
346
347 if ((chipset & 0xf0) != 0x30) {
348 NOUVEAU_ERR("Not a NV3X chipset\n");
349 return NULL;
350 }
351
352 if (NV30TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f))) {
353 rankine_class = 0x0397;
354 } else if (NV34TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f))) {
355 rankine_class = 0x0697;
356 } else if (NV35TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f))) {
357 rankine_class = 0x0497;
358 } else {
359 NOUVEAU_ERR("Unknown NV3X chipset: NV%02x\n", chipset);
360 return NULL;
361 }
362
363 nv30 = CALLOC_STRUCT(nv30_context);
364 if (!nv30)
365 return NULL;
366 nv30->chipset = chipset;
367 nv30->nvws = nvws;
368
369 /* Notifier for sync purposes */
370 ret = nvws->notifier_alloc(nvws, 1, &nv30->sync);
371 if (ret) {
372 NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
373 nv30_destroy(&nv30->pipe);
374 return NULL;
375 }
376
377 /* Query objects */
378 ret = nvws->notifier_alloc(nvws, 32, &nv30->query);
379 if (ret) {
380 NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
381 nv30_destroy(&nv30->pipe);
382 return NULL;
383 }
384
385 ret = nvws->res_init(&nv30->query_heap, 0, 32);
386 if (ret) {
387 NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
388 nv30_destroy(&nv30->pipe);
389 return NULL;
390 }
391
392 /* Vtxprog resources */
393 if (nvws->res_init(&nv30->vertprog.exec_heap, 0, 512) ||
394 nvws->res_init(&nv30->vertprog.data_heap, 0, 256)) {
395 nv30_destroy(&nv30->pipe);
396 return NULL;
397 }
398
399 /* Static rankine initialisation */
400 if (!nv30_init_hwctx(nv30, rankine_class)) {
401 nv30_destroy(&nv30->pipe);
402 return NULL;
403 }
404
405 /* Pipe context setup */
406 nv30->pipe.winsys = pipe_winsys;
407
408 nv30->pipe.destroy = nv30_destroy;
409 nv30->pipe.get_name = nv30_get_name;
410 nv30->pipe.get_vendor = nv30_get_vendor;
411 nv30->pipe.get_param = nv30_get_param;
412 nv30->pipe.get_paramf = nv30_get_paramf;
413
414 nv30->pipe.draw_arrays = nv30_draw_arrays;
415 nv30->pipe.draw_elements = nv30_draw_elements;
416 nv30->pipe.clear = nv30_clear;
417
418 nv30->pipe.flush = nv30_flush;
419
420 nv30_init_query_functions(nv30);
421 nv30_init_surface_functions(nv30);
422 nv30_init_state_functions(nv30);
423 nv30_init_miptree_functions(nv30);
424
425 nv30->draw = draw_create();
426 assert(nv30->draw);
427 draw_set_rasterize_stage(nv30->draw, nv30_draw_render_stage(nv30));
428
429 return &nv30->pipe;
430 }
431