OSDN Git Service

Merge branch 'master' into modesetting-gem
[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 #include <stdio.h>
33 #include <stdint.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/mman.h>
37 #include <sys/ioctl.h>
38 #include "xf86drm.h"
39 #include "drm.h"
40 #include "radeon_drm.h"
41 #include "radeon_bo.h"
42 #include "radeon_bo_gem.h"
43
44 struct radeon_bo_gem {
45     struct radeon_bo    base;
46     uint32_t            name;
47     int                 map_count;
48 };
49
50 struct bo_manager_gem {
51     struct radeon_bo_manager    base;
52 };
53
54 static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
55                                  uint32_t handle,
56                                  uint32_t size,
57                                  uint32_t alignment,
58                                  uint32_t domains,
59                                  uint32_t flags)
60 {
61     struct radeon_bo_gem *bo;
62     int r;
63
64     bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem));
65     if (bo == NULL) {
66         return NULL;
67     }
68
69     bo->base.bom = bom;
70     bo->base.handle = 0;
71     bo->base.size = size;
72     bo->base.alignment = alignment;
73     bo->base.domains = domains;
74     bo->base.flags = flags;
75     bo->base.ptr = NULL;
76     bo->map_count = 0;
77     if (handle) {
78         struct drm_gem_open open_arg;
79
80         memset(&open_arg, 0, sizeof(open_arg));
81         open_arg.name = handle;
82         r = ioctl(bom->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
83         if (r != 0) {
84             fprintf(stderr, "GEM open failed: %d (%s)\n",r,strerror(r));
85             free(bo);
86             return NULL;
87         }
88         bo->base.handle = open_arg.handle;
89         bo->base.size = open_arg.size;
90         bo->name = handle;
91     } else {
92         struct drm_radeon_gem_create args;
93
94         args.size = size;
95         args.alignment = alignment;
96         args.initial_domain = bo->base.domains;
97         args.no_backing_store = 0;
98         r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE,
99                                 &args, sizeof(args));
100         bo->base.handle = args.handle;
101         if (r) {
102             fprintf(stderr, "Failed to allocate :\n");
103             fprintf(stderr, "   size      : %d bytes\n", size);
104             fprintf(stderr, "   alignment : %d bytes\n", alignment);
105             fprintf(stderr, "   domains   : %d\n", bo->base.domains);
106             free(bo);
107             return NULL;
108         }
109     }
110     radeon_bo_ref((struct radeon_bo*)bo);
111     return (struct radeon_bo*)bo;
112 }
113
114 static void bo_ref(struct radeon_bo *bo)
115 {
116 }
117
118 static void bo_unref(struct radeon_bo *bo)
119 {
120     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
121     struct drm_gem_close args;
122
123     if (bo == NULL) {
124         return;
125     }
126     if (bo->cref) {
127         return;
128     }
129     if (bo_gem->map_count) {
130         munmap(bo->ptr, bo->size);
131     }
132
133     /* close object */
134     args.handle = bo->handle;
135     ioctl(bo->bom->fd, DRM_IOCTL_GEM_CLOSE, &args);
136     free(bo_gem);
137 }
138
139 static int bo_map(struct radeon_bo *bo, int write)
140 {
141     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
142     struct drm_radeon_gem_mmap args;
143     int r;
144
145     if (bo_gem->map_count++ != 0) {
146         return 0;
147     }
148     bo->ptr = NULL;
149     args.handle = bo->handle;
150     args.offset = 0;
151     args.size = (uint64_t)bo->size;
152     r = drmCommandWriteRead(bo->bom->fd,
153                             DRM_RADEON_GEM_MMAP,
154                             &args,
155                             sizeof(args));
156     if (!r) {
157         bo->ptr = (void *)(unsigned long)args.addr_ptr;
158     } else {
159         fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
160                 bo, bo->handle, r);
161     }
162     return r;
163 }
164
165 static int bo_unmap(struct radeon_bo *bo)
166 {
167     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
168
169     if (--bo_gem->map_count > 0) {
170         return 0;
171     }
172     munmap(bo->ptr, bo->size);
173     bo->ptr = NULL;
174     return 0;
175 }
176
177 static struct radeon_bo_funcs bo_gem_funcs = {
178     bo_open,
179     bo_ref,
180     bo_unref,
181     bo_map,
182     bo_unmap
183 };
184
185 struct radeon_bo_manager *radeon_bo_manager_gem(int fd)
186 {
187     struct bo_manager_gem *bomg;
188
189     bomg = (struct bo_manager_gem*)calloc(1, sizeof(struct bo_manager_gem));
190     if (bomg == NULL) {
191         return NULL;
192     }
193     bomg->base.funcs = &bo_gem_funcs;
194     bomg->base.fd = fd;
195     return (struct radeon_bo_manager*)bomg;
196 }
197
198 void radeon_bo_manager_gem_shutdown(struct radeon_bo_manager *bom)
199 {
200     struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom;
201
202     if (bom == NULL) {
203         return;
204     }
205     free(bomg);
206 }