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