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