8ebae8e27dc15d91e8ee64464cb6994798935927
[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 #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
26 int nouveau_mesa_debug = 0;
27
28 static const char *
29 nouveau_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
38 static const char *
39 nouveau_screen_get_vendor(struct pipe_screen *pscreen)
40 {
41 return "nouveau";
42 }
43
44
45
46 struct nouveau_bo *
47 nouveau_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
88 void *
89 nouveau_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
104 void *
105 nouveau_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
121 void
122 nouveau_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
128 void
129 nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct nouveau_bo *bo)
130 {
131 nouveau_bo_unmap(bo);
132 }
133
134 void
135 nouveau_screen_bo_release(struct pipe_screen *pscreen, struct nouveau_bo *bo)
136 {
137 nouveau_bo_ref(NULL, &bo);
138 }
139
140 static void
141 nouveau_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
148 static boolean
149 nouveau_screen_fence_signalled(struct pipe_screen *screen,
150 struct pipe_fence_handle *pfence)
151 {
152 return nouveau_fence_signalled(nouveau_fence(pfence));
153 }
154
155 static boolean
156 nouveau_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
164 struct nouveau_bo *
165 nouveau_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
185 boolean
186 nouveau_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
203 int
204 nouveau_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
235 void
236 nouveau_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