Merge commit 'origin/gallium-master-merge'
[mesa.git] / src / gallium / drivers / nv30 / nv30_screen.c
1 #include "pipe/p_screen.h"
2 #include "util/u_simple_screen.h"
3
4 #include "nv30_context.h"
5 #include "nv30_screen.h"
6
7 #define NV30TCL_CHIPSET_3X_MASK 0x00000003
8 #define NV34TCL_CHIPSET_3X_MASK 0x00000010
9 #define NV35TCL_CHIPSET_3X_MASK 0x000001e0
10
11 static const char *
12 nv30_screen_get_name(struct pipe_screen *pscreen)
13 {
14 struct nv30_screen *screen = nv30_screen(pscreen);
15 struct nouveau_device *dev = screen->nvws->channel->device;
16 static char buffer[128];
17
18 snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
19 return buffer;
20 }
21
22 static const char *
23 nv30_screen_get_vendor(struct pipe_screen *pscreen)
24 {
25 return "nouveau";
26 }
27
28 static int
29 nv30_screen_get_param(struct pipe_screen *pscreen, int param)
30 {
31 switch (param) {
32 case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
33 return 16;
34 case PIPE_CAP_NPOT_TEXTURES:
35 return 0;
36 case PIPE_CAP_TWO_SIDED_STENCIL:
37 return 1;
38 case PIPE_CAP_GLSL:
39 return 0;
40 case PIPE_CAP_S3TC:
41 return 0;
42 case PIPE_CAP_ANISOTROPIC_FILTER:
43 return 1;
44 case PIPE_CAP_POINT_SPRITE:
45 return 1;
46 case PIPE_CAP_MAX_RENDER_TARGETS:
47 return 2;
48 case PIPE_CAP_OCCLUSION_QUERY:
49 return 1;
50 case PIPE_CAP_TEXTURE_SHADOW_MAP:
51 return 1;
52 case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
53 return 13;
54 case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
55 return 10;
56 case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
57 return 13;
58 case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
59 return 0;
60 case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
61 return 1;
62 case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
63 return 0;
64 case NOUVEAU_CAP_HW_VTXBUF:
65 case NOUVEAU_CAP_HW_IDXBUF:
66 return 1;
67 default:
68 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
69 return 0;
70 }
71 }
72
73 static float
74 nv30_screen_get_paramf(struct pipe_screen *pscreen, int param)
75 {
76 switch (param) {
77 case PIPE_CAP_MAX_LINE_WIDTH:
78 case PIPE_CAP_MAX_LINE_WIDTH_AA:
79 return 10.0;
80 case PIPE_CAP_MAX_POINT_WIDTH:
81 case PIPE_CAP_MAX_POINT_WIDTH_AA:
82 return 64.0;
83 case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
84 return 8.0;
85 case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
86 return 4.0;
87 default:
88 NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param);
89 return 0.0;
90 }
91 }
92
93 static boolean
94 nv30_screen_surface_format_supported(struct pipe_screen *pscreen,
95 enum pipe_format format,
96 enum pipe_texture_target target,
97 unsigned tex_usage, unsigned geom_flags)
98 {
99 if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
100 switch (format) {
101 case PIPE_FORMAT_A8R8G8B8_UNORM:
102 case PIPE_FORMAT_R5G6B5_UNORM:
103 case PIPE_FORMAT_Z24S8_UNORM:
104 case PIPE_FORMAT_Z16_UNORM:
105 return TRUE;
106 default:
107 break;
108 }
109 } else {
110 switch (format) {
111 case PIPE_FORMAT_A8R8G8B8_UNORM:
112 case PIPE_FORMAT_A1R5G5B5_UNORM:
113 case PIPE_FORMAT_A4R4G4B4_UNORM:
114 case PIPE_FORMAT_R5G6B5_UNORM:
115 case PIPE_FORMAT_L8_UNORM:
116 case PIPE_FORMAT_A8_UNORM:
117 case PIPE_FORMAT_I8_UNORM:
118 case PIPE_FORMAT_A8L8_UNORM:
119 case PIPE_FORMAT_Z16_UNORM:
120 case PIPE_FORMAT_Z24S8_UNORM:
121 return TRUE;
122 default:
123 break;
124 }
125 }
126
127 return FALSE;
128 }
129
130 static struct pipe_buffer *
131 nv30_surface_buffer(struct pipe_surface *surf)
132 {
133 struct nv30_miptree *mt = (struct nv30_miptree *)surf->texture;
134
135 return mt->buffer;
136 }
137
138 static void *
139 nv30_surface_map(struct pipe_screen *screen, struct pipe_surface *surface,
140 unsigned flags )
141 {
142 struct pipe_winsys *ws = screen->winsys;
143 struct pipe_surface *surface_to_map;
144 void *map;
145
146 if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
147 struct nv30_miptree *mt = (struct nv30_miptree *)surface->texture;
148
149 if (!mt->shadow_tex) {
150 unsigned old_tex_usage = surface->texture->tex_usage;
151 surface->texture->tex_usage = NOUVEAU_TEXTURE_USAGE_LINEAR |
152 PIPE_TEXTURE_USAGE_DYNAMIC;
153 mt->shadow_tex = screen->texture_create(screen, surface->texture);
154 surface->texture->tex_usage = old_tex_usage;
155
156 assert(mt->shadow_tex->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR);
157 }
158
159 mt->shadow_surface = screen->get_tex_surface
160 (
161 screen, mt->shadow_tex,
162 surface->face, surface->level, surface->zslice,
163 surface->usage
164 );
165
166 surface_to_map = mt->shadow_surface;
167 }
168 else
169 surface_to_map = surface;
170
171 assert(surface_to_map);
172
173 map = ws->buffer_map(ws, nv30_surface_buffer(surface_to_map), flags);
174 if (!map)
175 return NULL;
176
177 return map + surface_to_map->offset;
178 }
179
180 static void
181 nv30_surface_unmap(struct pipe_screen *screen, struct pipe_surface *surface)
182 {
183 struct pipe_winsys *ws = screen->winsys;
184 struct pipe_surface *surface_to_unmap;
185
186 /* TODO: Copy from shadow just before push buffer is flushed instead.
187 There are probably some programs that map/unmap excessively
188 before rendering. */
189 if (!(surface->texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
190 struct nv30_miptree *mt = (struct nv30_miptree *)surface->texture;
191
192 assert(mt->shadow_tex);
193
194 surface_to_unmap = mt->shadow_surface;
195 }
196 else
197 surface_to_unmap = surface;
198
199 assert(surface_to_unmap);
200
201 ws->buffer_unmap(ws, nv30_surface_buffer(surface_to_unmap));
202
203 if (surface_to_unmap != surface) {
204 struct nv30_screen *nvscreen = nv30_screen(screen);
205
206 nvscreen->eng2d->copy(nvscreen->eng2d, surface, 0, 0,
207 surface_to_unmap, 0, 0,
208 surface->width, surface->height);
209
210 screen->tex_surface_release(screen, &surface_to_unmap);
211 }
212 }
213
214 static void
215 nv30_screen_destroy(struct pipe_screen *pscreen)
216 {
217 struct nv30_screen *screen = nv30_screen(pscreen);
218 struct nouveau_winsys *nvws = screen->nvws;
219
220 nvws->res_free(&screen->vp_exec_heap);
221 nvws->res_free(&screen->vp_data_heap);
222 nvws->res_free(&screen->query_heap);
223 nvws->notifier_free(&screen->query);
224 nvws->notifier_free(&screen->sync);
225 nvws->grobj_free(&screen->rankine);
226
227 FREE(pscreen);
228 }
229
230 struct pipe_screen *
231 nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
232 {
233 struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
234 struct nouveau_stateobj *so;
235 unsigned rankine_class = 0;
236 unsigned chipset = nvws->channel->device->chipset;
237 int ret, i;
238
239 if (!screen)
240 return NULL;
241 screen->nvws = nvws;
242
243 /* 2D engine setup */
244 screen->eng2d = nv04_surface_2d_init(nvws);
245 screen->eng2d->buf = nv30_surface_buffer;
246
247 /* 3D object */
248 switch (chipset & 0xf0) {
249 case 0x30:
250 if (NV30TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f)))
251 rankine_class = 0x0397;
252 else
253 if (NV34TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f)))
254 rankine_class = 0x0697;
255 else
256 if (NV35TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f)))
257 rankine_class = 0x0497;
258 break;
259 default:
260 break;
261 }
262
263 if (!rankine_class) {
264 NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", chipset);
265 return NULL;
266 }
267
268 ret = nvws->grobj_alloc(nvws, rankine_class, &screen->rankine);
269 if (ret) {
270 NOUVEAU_ERR("Error creating 3D object: %d\n", ret);
271 return FALSE;
272 }
273
274 /* Notifier for sync purposes */
275 ret = nvws->notifier_alloc(nvws, 1, &screen->sync);
276 if (ret) {
277 NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
278 nv30_screen_destroy(&screen->pipe);
279 return NULL;
280 }
281
282 /* Query objects */
283 ret = nvws->notifier_alloc(nvws, 32, &screen->query);
284 if (ret) {
285 NOUVEAU_ERR("Error initialising query objects: %d\n", ret);
286 nv30_screen_destroy(&screen->pipe);
287 return NULL;
288 }
289
290 ret = nvws->res_init(&screen->query_heap, 0, 32);
291 if (ret) {
292 NOUVEAU_ERR("Error initialising query object heap: %d\n", ret);
293 nv30_screen_destroy(&screen->pipe);
294 return NULL;
295 }
296
297 /* Vtxprog resources */
298 if (nvws->res_init(&screen->vp_exec_heap, 0, 256) ||
299 nvws->res_init(&screen->vp_data_heap, 0, 256)) {
300 nv30_screen_destroy(&screen->pipe);
301 return NULL;
302 }
303
304 /* Static rankine initialisation */
305 so = so_new(128, 0);
306 so_method(so, screen->rankine, NV34TCL_DMA_NOTIFY, 1);
307 so_data (so, screen->sync->handle);
308 so_method(so, screen->rankine, NV34TCL_DMA_TEXTURE0, 2);
309 so_data (so, nvws->channel->vram->handle);
310 so_data (so, nvws->channel->gart->handle);
311 so_method(so, screen->rankine, NV34TCL_DMA_COLOR1, 1);
312 so_data (so, nvws->channel->vram->handle);
313 so_method(so, screen->rankine, NV34TCL_DMA_COLOR0, 2);
314 so_data (so, nvws->channel->vram->handle);
315 so_data (so, nvws->channel->vram->handle);
316 so_method(so, screen->rankine, NV34TCL_DMA_VTXBUF0, 2);
317 so_data (so, nvws->channel->vram->handle);
318 so_data (so, nvws->channel->gart->handle);
319 /* so_method(so, screen->rankine, NV34TCL_DMA_FENCE, 2);
320 so_data (so, 0);
321 so_data (so, screen->query->handle);*/
322 so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY7, 1);
323 so_data (so, nvws->channel->vram->handle);
324 so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY8, 1);
325 so_data (so, nvws->channel->vram->handle);
326
327 for (i=1; i<8; i++) {
328 so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1);
329 so_data (so, 0);
330 so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_VERT(i), 1);
331 so_data (so, 0);
332 }
333
334 so_method(so, screen->rankine, 0x220, 1);
335 so_data (so, 1);
336
337 so_method(so, screen->rankine, 0x03b0, 1);
338 so_data (so, 0x00100000);
339 so_method(so, screen->rankine, 0x1454, 1);
340 so_data (so, 0);
341 so_method(so, screen->rankine, 0x1d80, 1);
342 so_data (so, 3);
343 so_method(so, screen->rankine, 0x1450, 1);
344 so_data (so, 0x00030004);
345
346 /* NEW */
347 so_method(so, screen->rankine, 0x1e98, 1);
348 so_data (so, 0);
349 so_method(so, screen->rankine, 0x17e0, 3);
350 so_data (so, fui(0.0));
351 so_data (so, fui(0.0));
352 so_data (so, fui(1.0));
353 so_method(so, screen->rankine, 0x1f80, 16);
354 for (i=0; i<16; i++) {
355 so_data (so, (i==8) ? 0x0000ffff : 0);
356 }
357
358 so_method(so, screen->rankine, 0x120, 3);
359 so_data (so, 0);
360 so_data (so, 1);
361 so_data (so, 2);
362
363 so_method(so, screen->rankine, 0x1d88, 1);
364 so_data (so, 0x00001200);
365
366 so_method(so, screen->rankine, NV34TCL_RC_ENABLE, 1);
367 so_data (so, 0);
368
369 so_method(so, screen->rankine, NV34TCL_DEPTH_RANGE_NEAR, 2);
370 so_data (so, fui(0.0));
371 so_data (so, fui(1.0));
372
373 so_method(so, screen->rankine, NV34TCL_MULTISAMPLE_CONTROL, 1);
374 so_data (so, 0xffff0000);
375
376 /* enables use of vp rather than fixed-function somehow */
377 so_method(so, screen->rankine, 0x1e94, 1);
378 so_data (so, 0x13);
379
380 so_emit(nvws, so);
381 so_ref(NULL, &so);
382 nvws->push_flush(nvws, 0, NULL);
383
384 screen->pipe.winsys = ws;
385 screen->pipe.destroy = nv30_screen_destroy;
386
387 screen->pipe.get_name = nv30_screen_get_name;
388 screen->pipe.get_vendor = nv30_screen_get_vendor;
389 screen->pipe.get_param = nv30_screen_get_param;
390 screen->pipe.get_paramf = nv30_screen_get_paramf;
391
392 screen->pipe.is_format_supported = nv30_screen_surface_format_supported;
393
394 screen->pipe.surface_map = nv30_surface_map;
395 screen->pipe.surface_unmap = nv30_surface_unmap;
396
397 nv30_screen_init_miptree_functions(&screen->pipe);
398 u_simple_screen_init(&screen->pipe);
399
400 return &screen->pipe;
401 }