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