OSDN Git Service

3c3b3e5b55d6ac10150efbb1784271dc71cdba1c
[android-x86/external-libdrm.git] / libdrm / radeon / radeon_bo_gem.c
1 /* 
2  * Copyright © 2008 Dave Airlie
3  * Copyright © 2008 Jérôme Glisse
4  * All Rights Reserved.
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  * 
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
18  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * The above copyright notice and this permission notice (including the
24  * next paragraph) shall be included in all copies or substantial portions
25  * of the Software.
26  */
27 /*
28  * Authors:
29  *      Dave Airlie
30  *      Jérôme Glisse <glisse@freedesktop.org>
31  */
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35 #include <stdio.h>
36 #include <stdint.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/mman.h>
40 #include <sys/ioctl.h>
41 #include <errno.h>
42 #include "xf86drm.h"
43 #include "drm.h"
44 #include "radeon_drm.h"
45 #include "radeon_bo.h"
46 #include "radeon_bo_gem.h"
47
48 struct radeon_bo_gem {
49     struct radeon_bo    base;
50     uint32_t            name;
51     int                 map_count;
52     void *priv_ptr;
53 };
54
55 struct bo_manager_gem {
56     struct radeon_bo_manager    base;
57 };
58
59 static int bo_wait(struct radeon_bo *bo);
60
61 static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
62                                  uint32_t handle,
63                                  uint32_t size,
64                                  uint32_t alignment,
65                                  uint32_t domains,
66                                  uint32_t flags)
67 {
68     struct radeon_bo_gem *bo;
69     int r;
70
71     bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem));
72     if (bo == NULL) {
73         return NULL;
74     }
75
76     bo->base.bom = bom;
77     bo->base.handle = 0;
78     bo->base.size = size;
79     bo->base.alignment = alignment;
80     bo->base.domains = domains;
81     bo->base.flags = flags;
82     bo->base.ptr = NULL;
83     bo->map_count = 0;
84     if (handle) {
85         struct drm_gem_open open_arg;
86
87         memset(&open_arg, 0, sizeof(open_arg));
88         open_arg.name = handle;
89         r = ioctl(bom->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
90         if (r != 0) {
91             free(bo);
92             return NULL;
93         }
94         bo->base.handle = open_arg.handle;
95         bo->base.size = open_arg.size;
96         bo->name = handle;
97     } else {
98         struct drm_radeon_gem_create args;
99
100         args.size = size;
101         args.alignment = alignment;
102         args.initial_domain = bo->base.domains;
103         args.flags = 0;
104         args.handle = 0;
105         r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE,
106                                 &args, sizeof(args));
107         bo->base.handle = args.handle;
108         if (r) {
109             fprintf(stderr, "Failed to allocate :\n");
110             fprintf(stderr, "   size      : %d bytes\n", size);
111             fprintf(stderr, "   alignment : %d bytes\n", alignment);
112             fprintf(stderr, "   domains   : %d\n", bo->base.domains);
113             free(bo);
114             return NULL;
115         }
116     }
117     radeon_bo_ref((struct radeon_bo*)bo);
118     return (struct radeon_bo*)bo;
119 }
120
121 static void bo_ref(struct radeon_bo *bo)
122 {
123 }
124
125 static struct radeon_bo *bo_unref(struct radeon_bo *bo)
126 {
127     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
128     struct drm_gem_close args;
129
130     if (bo == NULL) {
131         return NULL;
132     }
133     if (bo->cref) {
134         return bo;
135     }
136     if (bo_gem->priv_ptr) {
137         munmap(bo_gem->priv_ptr, bo->size);
138     }
139
140     /* close object */
141     args.handle = bo->handle;
142     ioctl(bo->bom->fd, DRM_IOCTL_GEM_CLOSE, &args);
143     memset(bo_gem, 0, sizeof(struct radeon_bo_gem));
144     free(bo_gem);
145     return NULL;
146 }
147
148 static int bo_map(struct radeon_bo *bo, int write)
149 {
150     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
151     struct drm_radeon_gem_mmap args;
152     int r;
153     void *ptr;
154
155     if (bo_gem->map_count++ != 0) {
156         return 0;
157     }
158     if (bo_gem->priv_ptr) {
159         r = bo_wait(bo);
160         bo->ptr = bo_gem->priv_ptr;
161         if (r)
162                 return r;
163         return 0;
164     }
165
166     bo->ptr = NULL;
167     args.handle = bo->handle;
168     args.offset = 0;
169     args.size = (uint64_t)bo->size;
170     r = drmCommandWriteRead(bo->bom->fd,
171                             DRM_RADEON_GEM_MMAP,
172                             &args,
173                             sizeof(args));
174     if (r) {
175         fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
176                 bo, bo->handle, r);
177         return r;
178     }
179     ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->bom->fd, args.addr_ptr);
180     if (ptr == MAP_FAILED)
181         return -errno;
182     bo_gem->priv_ptr = ptr;
183     bo->ptr = bo_gem->priv_ptr;
184     return r;
185 }
186
187 static int bo_unmap(struct radeon_bo *bo)
188 {
189     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
190
191     if (--bo_gem->map_count > 0) {
192         return 0;
193     }
194     //munmap(bo->ptr, bo->size);
195     bo->ptr = NULL;
196     return 0;
197 }
198
199 static int bo_wait(struct radeon_bo *bo)
200 {
201     struct drm_radeon_gem_wait_idle args;
202     int ret;
203
204     args.handle = bo->handle;
205     do {
206         ret = drmCommandWriteRead(bo->bom->fd, DRM_RADEON_GEM_WAIT_IDLE,
207                                   &args, sizeof(args));
208     } while (ret == -EBUSY);
209     return ret;
210 }
211
212 static int bo_set_tiling(struct radeon_bo *bo, uint32_t tiling_flags,
213                                  uint32_t pitch)
214 {
215     struct drm_radeon_gem_set_tiling args;
216     int r;
217
218     args.handle = bo->handle;
219     args.tiling_flags = tiling_flags;
220     args.pitch = pitch;
221
222     r = drmCommandWriteRead(bo->bom->fd,
223                             DRM_RADEON_GEM_SET_TILING,
224                             &args,
225                             sizeof(args));
226     return r;
227 }
228
229 static int bo_get_tiling(struct radeon_bo *bo, uint32_t *tiling_flags,
230                                  uint32_t *pitch)
231 {
232     struct drm_radeon_gem_set_tiling args;
233     int r;
234
235     args.handle = bo->handle;
236
237     r = drmCommandWriteRead(bo->bom->fd,
238                             DRM_RADEON_GEM_GET_TILING,
239                             &args,
240                             sizeof(args));
241
242     if (r)
243         return r;
244
245     *tiling_flags = args.tiling_flags;
246     *pitch = args.pitch;
247     return r;
248 }
249
250 static struct radeon_bo_funcs bo_gem_funcs = {
251     bo_open,
252     bo_ref,
253     bo_unref,
254     bo_map,
255     bo_unmap,
256     bo_wait,
257     NULL,
258     bo_set_tiling,
259     bo_get_tiling,
260 };
261
262 struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd)
263 {
264     struct bo_manager_gem *bomg;
265
266     bomg = (struct bo_manager_gem*)calloc(1, sizeof(struct bo_manager_gem));
267     if (bomg == NULL) {
268         return NULL;
269     }
270     bomg->base.funcs = &bo_gem_funcs;
271     bomg->base.fd = fd;
272     return (struct radeon_bo_manager*)bomg;
273 }
274
275 void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom)
276 {
277     struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom;
278
279     if (bom == NULL) {
280         return;
281     }
282     free(bomg);
283 }
284
285 uint32_t radeon_gem_name_bo(struct radeon_bo *bo)
286 {
287     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
288     return bo_gem->name;
289 }
290
291 int radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name)
292 {
293     struct drm_gem_flink flink;
294     int r;
295
296     flink.handle = bo->handle;
297     r = ioctl(bo->bom->fd, DRM_IOCTL_GEM_FLINK, &flink);
298     if (r) {
299         return r;
300     }
301     *name = flink.name;
302     return 0;
303 }
304
305 int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain)
306 {
307     struct drm_radeon_gem_set_domain args;
308     int r;
309
310     args.handle = bo->handle;
311     args.read_domains = read_domains;
312     args.write_domain = write_domain;
313
314     r = drmCommandWriteRead(bo->bom->fd,
315                             DRM_RADEON_GEM_SET_DOMAIN,
316                             &args,
317                             sizeof(args));
318     return r;
319 }