nouveau_screen.c revision a6ef7f7ce4a52c05c55a2d265f1fdebc7de5a1db
1#include "pipe/p_defines.h"
2#include "pipe/p_screen.h"
3#include "pipe/p_state.h"
4
5#include "util/u_memory.h"
6#include "util/u_inlines.h"
7#include "util/u_format.h"
8#include "util/u_format_s3tc.h"
9#include "util/u_string.h"
10
11#include <stdio.h>
12#include <errno.h>
13#include <stdlib.h>
14
15#include "nouveau/nouveau_bo.h"
16#include "nouveau/nouveau_mm.h"
17#include "nouveau_winsys.h"
18#include "nouveau_screen.h"
19#include "nouveau_fence.h"
20
21/* XXX this should go away */
22#include "state_tracker/drm_driver.h"
23
24#include "nouveau_drmif.h"
25
26int nouveau_mesa_debug = 0;
27
28static const char *
29nouveau_screen_get_name(struct pipe_screen *pscreen)
30{
31	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
32	static char buffer[128];
33
34	util_snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
35	return buffer;
36}
37
38static const char *
39nouveau_screen_get_vendor(struct pipe_screen *pscreen)
40{
41	return "nouveau";
42}
43
44
45
46struct nouveau_bo *
47nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment,
48		      unsigned usage, unsigned bind, unsigned size)
49{
50	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
51	struct nouveau_bo *bo = NULL;
52	uint32_t flags = NOUVEAU_BO_MAP, tile_mode = 0, tile_flags = 0;
53	int ret;
54
55	if (bind & PIPE_BIND_VERTEX_BUFFER)
56		flags |= nouveau_screen(pscreen)->vertex_buffer_flags;
57	else if (bind & PIPE_BIND_INDEX_BUFFER)
58		flags |= nouveau_screen(pscreen)->index_buffer_flags;
59
60	if (bind & (PIPE_BIND_RENDER_TARGET |
61			PIPE_BIND_DEPTH_STENCIL |
62			PIPE_BIND_SCANOUT |
63			PIPE_BIND_DISPLAY_TARGET |
64			PIPE_BIND_SAMPLER_VIEW))
65	{
66		/* TODO: this may be incorrect or suboptimal */
67		if (!(bind & PIPE_BIND_SCANOUT))
68			flags |= NOUVEAU_BO_GART;
69		if (usage != PIPE_USAGE_DYNAMIC)
70			flags |= NOUVEAU_BO_VRAM;
71
72		if (dev->chipset == 0x50 || dev->chipset >= 0x80) {
73			if (bind & PIPE_BIND_DEPTH_STENCIL)
74				tile_flags = 0x2800;
75			else
76				tile_flags = 0x7000;
77		}
78	}
79
80	ret = nouveau_bo_new_tile(dev, flags, alignment, size,
81				  tile_mode, tile_flags, &bo);
82	if (ret)
83		return NULL;
84
85	return bo;
86}
87
88void *
89nouveau_screen_bo_map(struct pipe_screen *pscreen,
90		      struct nouveau_bo *bo,
91		      unsigned map_flags)
92{
93	int ret;
94
95	ret = nouveau_bo_map(bo, map_flags);
96	if (ret) {
97		debug_printf("map failed: %d\n", ret);
98		return NULL;
99	}
100
101	return bo->map;
102}
103
104void *
105nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct nouveau_bo *bo,
106			    unsigned offset, unsigned length, unsigned flags)
107{
108	int ret;
109
110	ret = nouveau_bo_map_range(bo, offset, length, flags);
111	if (ret) {
112		nouveau_bo_unmap(bo);
113		if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
114			debug_printf("map_range failed: %d\n", ret);
115		return NULL;
116	}
117
118	return (char *)bo->map - offset; /* why gallium? why? */
119}
120
121void
122nouveau_screen_bo_map_flush_range(struct pipe_screen *pscreen, struct nouveau_bo *bo,
123				  unsigned offset, unsigned length)
124{
125	nouveau_bo_map_flush(bo, offset, length);
126}
127
128void
129nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct nouveau_bo *bo)
130{
131	nouveau_bo_unmap(bo);
132}
133
134void
135nouveau_screen_bo_release(struct pipe_screen *pscreen, struct nouveau_bo *bo)
136{
137	nouveau_bo_ref(NULL, &bo);
138}
139
140static void
141nouveau_screen_fence_ref(struct pipe_screen *pscreen,
142			 struct pipe_fence_handle **ptr,
143			 struct pipe_fence_handle *pfence)
144{
145	nouveau_fence_ref(nouveau_fence(pfence), (struct nouveau_fence **)ptr);
146}
147
148static boolean
149nouveau_screen_fence_signalled(struct pipe_screen *screen,
150                               struct pipe_fence_handle *pfence)
151{
152        return nouveau_fence_signalled(nouveau_fence(pfence));
153}
154
155static boolean
156nouveau_screen_fence_finish(struct pipe_screen *screen,
157			    struct pipe_fence_handle *pfence,
158                            uint64_t timeout)
159{
160        return nouveau_fence_wait(nouveau_fence(pfence));
161}
162
163
164struct nouveau_bo *
165nouveau_screen_bo_from_handle(struct pipe_screen *pscreen,
166			      struct winsys_handle *whandle,
167			      unsigned *out_stride)
168{
169	struct nouveau_device *dev = nouveau_screen(pscreen)->device;
170	struct nouveau_bo *bo = 0;
171	int ret;
172
173	ret = nouveau_bo_handle_ref(dev, whandle->handle, &bo);
174	if (ret) {
175		debug_printf("%s: ref name 0x%08x failed with %d\n",
176			     __FUNCTION__, whandle->handle, ret);
177		return NULL;
178	}
179
180	*out_stride = whandle->stride;
181	return bo;
182}
183
184
185boolean
186nouveau_screen_bo_get_handle(struct pipe_screen *pscreen,
187			     struct nouveau_bo *bo,
188			     unsigned stride,
189			     struct winsys_handle *whandle)
190{
191	whandle->stride = stride;
192
193	if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
194		return nouveau_bo_handle_get(bo, &whandle->handle) == 0;
195	} else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
196		whandle->handle = bo->handle;
197		return TRUE;
198	} else {
199		return FALSE;
200	}
201}
202
203int
204nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
205{
206	struct pipe_screen *pscreen = &screen->base;
207	int ret;
208
209	char *nv_dbg = getenv("NOUVEAU_MESA_DEBUG");
210	if (nv_dbg)
211	   nouveau_mesa_debug = atoi(nv_dbg);
212
213	ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202,
214				    512*1024, &screen->channel);
215	if (ret)
216		return ret;
217	screen->device = dev;
218
219	pscreen->get_name = nouveau_screen_get_name;
220	pscreen->get_vendor = nouveau_screen_get_vendor;
221
222	pscreen->fence_reference = nouveau_screen_fence_ref;
223	pscreen->fence_signalled = nouveau_screen_fence_signalled;
224	pscreen->fence_finish = nouveau_screen_fence_finish;
225
226	util_format_s3tc_init();
227
228	screen->mm_GART = nouveau_mm_create(dev,
229					    NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
230					    0x000);
231	screen->mm_VRAM = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, 0x000);
232	return 0;
233}
234
235void
236nouveau_screen_fini(struct nouveau_screen *screen)
237{
238	nouveau_mm_destroy(screen->mm_GART);
239	nouveau_mm_destroy(screen->mm_VRAM);
240
241	nouveau_channel_free(&screen->channel);
242
243	nouveau_device_close(&screen->device);
244}
245
246