1 #include "pipe/p_defines.h"
2 #include "pipe/p_screen.h"
3 #include "pipe/p_state.h"
5 #include "util/u_memory.h"
6 #include "util/u_inlines.h"
7 #include "util/u_format.h"
12 #include "nouveau/nouveau_bo.h"
13 #include "nouveau_winsys.h"
14 #include "nouveau_screen.h"
16 /* XXX this should go away */
17 #include "state_tracker/drm_api.h"
20 nouveau_screen_get_name(struct pipe_screen *pscreen)
22 struct nouveau_device *dev = nouveau_screen(pscreen)->device;
23 static char buffer[128];
25 snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
30 nouveau_screen_get_vendor(struct pipe_screen *pscreen)
35 static struct pipe_buffer *
36 nouveau_screen_bo_skel(struct pipe_screen *pscreen, struct nouveau_bo *bo,
37 unsigned alignment, unsigned usage, unsigned size)
39 struct pipe_buffer *pb;
41 pb = CALLOC(1, sizeof(struct pipe_buffer)+sizeof(struct nouveau_bo *));
43 nouveau_bo_ref(NULL, &bo);
47 pipe_reference_init(&pb->reference, 1);
49 pb->alignment = alignment;
52 *(struct nouveau_bo **)(pb + 1) = bo;
56 static struct pipe_buffer *
57 nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment,
58 unsigned usage, unsigned size)
60 struct nouveau_device *dev = nouveau_screen(pscreen)->device;
61 struct nouveau_bo *bo = NULL;
62 uint32_t flags = NOUVEAU_BO_MAP, tile_mode = 0, tile_flags = 0;
65 if (usage & NOUVEAU_BUFFER_USAGE_TRANSFER)
66 flags |= NOUVEAU_BO_GART;
68 if (usage & PIPE_BUFFER_USAGE_VERTEX) {
69 if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF))
70 flags |= NOUVEAU_BO_GART;
72 if (usage & PIPE_BUFFER_USAGE_INDEX) {
73 if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF))
74 flags |= NOUVEAU_BO_GART;
77 if (usage & PIPE_BUFFER_USAGE_PIXEL) {
78 if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
79 flags |= NOUVEAU_BO_GART;
80 if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE))
81 flags |= NOUVEAU_BO_VRAM;
83 if (dev->chipset == 0x50 || dev->chipset >= 0x80) {
84 if (usage & NOUVEAU_BUFFER_USAGE_ZETA)
91 ret = nouveau_bo_new_tile(dev, flags, alignment, size,
92 tile_mode, tile_flags, &bo);
96 return nouveau_screen_bo_skel(pscreen, bo, alignment, usage, size);
99 static struct pipe_buffer *
100 nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes)
102 struct nouveau_device *dev = nouveau_screen(pscreen)->device;
103 struct nouveau_bo *bo = NULL;
106 ret = nouveau_bo_user(dev, ptr, bytes, &bo);
110 return nouveau_screen_bo_skel(pscreen, bo, 0, 0, bytes);
113 static inline uint32_t
114 nouveau_screen_map_flags(unsigned pipe)
118 if (pipe & PIPE_BUFFER_USAGE_CPU_READ)
119 flags |= NOUVEAU_BO_RD;
120 if (pipe & PIPE_BUFFER_USAGE_CPU_WRITE)
121 flags |= NOUVEAU_BO_WR;
122 if (pipe & PIPE_BUFFER_USAGE_DISCARD)
123 flags |= NOUVEAU_BO_INVAL;
124 if (pipe & PIPE_BUFFER_USAGE_DONTBLOCK)
125 flags |= NOUVEAU_BO_NOWAIT;
127 if (pipe & PIPE_BUFFER_USAGE_UNSYNCHRONIZED)
128 flags |= NOUVEAU_BO_NOSYNC;
134 nouveau_screen_bo_map(struct pipe_screen *pscreen, struct pipe_buffer *pb,
137 struct nouveau_bo *bo = nouveau_bo(pb);
138 struct nouveau_screen *nscreen = nouveau_screen(pscreen);
141 if (nscreen->pre_pipebuffer_map_callback) {
142 ret = nscreen->pre_pipebuffer_map_callback(pscreen, pb, usage);
144 debug_printf("pre_pipebuffer_map_callback failed %d\n",
150 ret = nouveau_bo_map(bo, nouveau_screen_map_flags(usage));
152 debug_printf("map failed: %d\n", ret);
160 nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct pipe_buffer *pb,
161 unsigned offset, unsigned length, unsigned usage)
163 struct nouveau_bo *bo = nouveau_bo(pb);
164 struct nouveau_screen *nscreen = nouveau_screen(pscreen);
165 uint32_t flags = nouveau_screen_map_flags(usage);
168 if (nscreen->pre_pipebuffer_map_callback) {
169 ret = nscreen->pre_pipebuffer_map_callback(pscreen, pb, usage);
171 debug_printf("pre_pipebuffer_map_callback failed %d\n",
177 ret = nouveau_bo_map_range(bo, offset, length, flags);
179 nouveau_bo_unmap(bo);
180 if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
181 debug_printf("map_range failed: %d\n", ret);
185 return (char *)bo->map - offset; /* why gallium? why? */
189 nouveau_screen_bo_map_flush(struct pipe_screen *pscreen, struct pipe_buffer *pb,
190 unsigned offset, unsigned length)
192 struct nouveau_bo *bo = nouveau_bo(pb);
194 nouveau_bo_map_flush(bo, offset, length);
198 nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct pipe_buffer *pb)
200 struct nouveau_bo *bo = nouveau_bo(pb);
202 nouveau_bo_unmap(bo);
206 nouveau_screen_bo_del(struct pipe_buffer *pb)
208 struct nouveau_bo *bo = nouveau_bo(pb);
210 nouveau_bo_ref(NULL, &bo);
215 nouveau_screen_fence_ref(struct pipe_screen *pscreen,
216 struct pipe_fence_handle **ptr,
217 struct pipe_fence_handle *pfence)
223 nouveau_screen_fence_signalled(struct pipe_screen *screen,
224 struct pipe_fence_handle *pfence,
231 nouveau_screen_fence_finish(struct pipe_screen *screen,
232 struct pipe_fence_handle *pfence,
240 * Both texture_{from|get}_handle use drm api defines directly which they
241 * shouldn't do. The problem is that from|get are pipe functions and as
242 * such they should be defined in the pipe level. If nouveau had a propper
243 * winsys interface we would have added from|get to that interface using
244 * the winsys_handle struct as done with other drivers. However this code
245 * calls directly into the libdrm_nouveau.so functions (nouveau_bo_*). So
246 * we need to translate the handle into something they understand.
248 static struct pipe_texture *
249 nouveau_screen_texture_from_handle(struct pipe_screen *pscreen,
250 const struct pipe_texture *templ,
251 struct winsys_handle *whandle)
253 struct nouveau_device *dev = nouveau_screen(pscreen)->device;
254 struct pipe_texture *pt;
255 struct pipe_buffer *pb;
258 pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*));
262 ret = nouveau_bo_handle_ref(dev, whandle->handle, (struct nouveau_bo**)(pb+1));
264 debug_printf("%s: ref name 0x%08x failed with %d\n",
265 __func__, whandle->handle, ret);
270 pipe_reference_init(&pb->reference, 1);
271 pb->screen = pscreen;
273 pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE |
274 PIPE_BUFFER_USAGE_CPU_READ_WRITE;
275 pb->size = nouveau_bo(pb)->size;
276 pt = nouveau_screen(pscreen)->texture_blanket(pscreen, templ,
277 &whandle->stride, pb);
278 pipe_buffer_reference(&pb, NULL);
283 nouveau_screen_texture_get_handle(struct pipe_screen *pscreen,
284 struct pipe_texture *pt,
285 struct winsys_handle *whandle)
287 struct nouveau_miptree *mt = nouveau_miptree(pt);
292 whandle->stride = util_format_get_stride(mt->base.format, mt->base.width0);
294 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
295 return nouveau_bo_handle_get(mt->bo, &whandle->handle) == 0;
296 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
297 whandle->handle = mt->bo->handle;
305 nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
307 struct pipe_screen *pscreen = &screen->base;
310 ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202,
314 screen->device = dev;
316 pscreen->get_name = nouveau_screen_get_name;
317 pscreen->get_vendor = nouveau_screen_get_vendor;
319 pscreen->buffer_create = nouveau_screen_bo_new;
320 pscreen->user_buffer_create = nouveau_screen_bo_user;
321 pscreen->buffer_map = nouveau_screen_bo_map;
322 pscreen->buffer_map_range = nouveau_screen_bo_map_range;
323 pscreen->buffer_flush_mapped_range = nouveau_screen_bo_map_flush;
324 pscreen->buffer_unmap = nouveau_screen_bo_unmap;
325 pscreen->buffer_destroy = nouveau_screen_bo_del;
327 pscreen->fence_reference = nouveau_screen_fence_ref;
328 pscreen->fence_signalled = nouveau_screen_fence_signalled;
329 pscreen->fence_finish = nouveau_screen_fence_finish;
331 pscreen->texture_from_handle = nouveau_screen_texture_from_handle;
332 pscreen->texture_get_handle = nouveau_screen_texture_get_handle;
338 nouveau_screen_fini(struct nouveau_screen *screen)
340 struct pipe_winsys *ws = screen->base.winsys;
341 nouveau_channel_free(&screen->channel);