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