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