blob: 63e504b7450cfc637a70edbb0a2d742689f7e7c1 [file] [log] [blame]
Chia-I Wu2ec32d42011-06-12 16:21:30 +08001/*
2 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
3 * Copyright (C) 2010-2011 LunarG Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#define LOG_TAG "GRALLOC-DRM"
25
26#include <cutils/log.h>
27#include <cutils/atomic.h>
28#include <stdlib.h>
29#include <errno.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <fcntl.h>
33
34#include "gralloc_drm.h"
35#include "gralloc_drm_priv.h"
36
37#define unlikely(x) __builtin_expect(!!(x), 0)
38
39#define GRALLOC_DRM_DEVICE "/dev/dri/card0"
40
41static int32_t gralloc_drm_pid = 0;
42
43/*
44 * Return the pid of the process.
45 */
46static int gralloc_drm_get_pid(void)
47{
48 if (unlikely(!gralloc_drm_pid))
49 android_atomic_write((int32_t) getpid(), &gralloc_drm_pid);
50
51 return gralloc_drm_pid;
52}
53
54/*
55 * Create the driver for a DRM fd.
56 */
57static struct gralloc_drm_drv_t *
58init_drv_from_fd(int fd)
59{
60 struct gralloc_drm_drv_t *drv = NULL;
61 drmVersionPtr version;
62
63 /* get the kernel module name */
64 version = drmGetVersion(fd);
65 if (!version) {
66 LOGE("invalid DRM fd");
67 return NULL;
68 }
69
70 if (version->name) {
71#ifdef ENABLE_INTEL
72 if (!drv && !strcmp(version->name, "i915"))
73 drv = gralloc_drm_drv_create_for_intel(fd);
74#endif
75#ifdef ENABLE_RADEON
76 if (!drv && !strcmp(version->name, "radeon"))
77 drv = gralloc_drm_drv_create_for_radeon(fd);
78#endif
79#ifdef ENABLE_VMWGFX
80 if (!drv && !strcmp(version->name, "vmwgfx"))
81 drv = gralloc_drm_drv_create_for_vmwgfx(fd);
82#endif
83 }
84
85 if (!drv) {
86 LOGE("unsupported driver: %s", (version->name) ?
87 version->name : "NULL");
88 }
89
90 drmFreeVersion(version);
91
92 return drv;
93}
94
95/*
96 * Create a DRM device object.
97 */
98struct gralloc_drm_t *gralloc_drm_create(void)
99{
100 struct gralloc_drm_t *drm;
101 int err;
102
103 drm = calloc(1, sizeof(*drm));
104 if (!drm)
105 return NULL;
106
107 drm->fd = open(GRALLOC_DRM_DEVICE, O_RDWR);
108 if (drm->fd < 0) {
109 LOGE("failed to open %s", GRALLOC_DRM_DEVICE);
110 return NULL;
111 }
112
113 drm->drv = init_drv_from_fd(drm->fd);
114 if (!drm->drv) {
115 close(drm->fd);
116 free(drm);
117 return NULL;
118 }
119
120 return drm;
121}
122
123/*
124 * Destroy a DRM device object.
125 */
126void gralloc_drm_destroy(struct gralloc_drm_t *drm)
127{
128 if (drm->drv)
129 drm->drv->destroy(drm->drv);
130 close(drm->fd);
131 free(drm);
132}
133
134/*
135 * Get the file descriptor of a DRM device object.
136 */
137int gralloc_drm_get_fd(struct gralloc_drm_t *drm)
138{
139 return drm->fd;
140}
141
142/*
143 * Get the magic for authentication.
144 */
145int gralloc_drm_get_magic(struct gralloc_drm_t *drm, int32_t *magic)
146{
147 return drmGetMagic(drm->fd, (drm_magic_t *) magic);
148}
149
150/*
151 * Authenticate a magic.
152 */
153int gralloc_drm_auth_magic(struct gralloc_drm_t *drm, int32_t magic)
154{
155 return drmAuthMagic(drm->fd, (drm_magic_t) magic);
156}
157
158/*
159 * Set as the master of a DRM device.
160 */
161int gralloc_drm_set_master(struct gralloc_drm_t *drm)
162{
163 LOGD("set master");
164 drmSetMaster(drm->fd);
165 drm->first_post = 1;
166
167 return 0;
168}
169
170/*
171 * Drop from the master of a DRM device.
172 */
173void gralloc_drm_drop_master(struct gralloc_drm_t *drm)
174{
175 drmDropMaster(drm->fd);
176}
177
178/*
179 * Create a buffer handle.
180 */
181static struct gralloc_drm_handle_t *create_bo_handle(int width,
182 int height, int format, int usage)
183{
184 struct gralloc_drm_handle_t *handle;
185
186 handle = calloc(1, sizeof(*handle));
187 if (!handle)
188 return NULL;
189
190 handle->base.version = sizeof(handle->base);
191 handle->base.numInts = GRALLOC_DRM_HANDLE_NUM_INTS;
192 handle->base.numFds = GRALLOC_DRM_HANDLE_NUM_FDS;
193
194 handle->magic = GRALLOC_DRM_HANDLE_MAGIC;
195 handle->width = width;
196 handle->height = height;
197 handle->format = format;
198 handle->usage = usage;
199
200 return handle;
201}
202
203/*
204 * Create a bo.
205 */
206struct gralloc_drm_bo_t *gralloc_drm_bo_create(struct gralloc_drm_t *drm,
207 int width, int height, int format, int usage)
208{
209 struct gralloc_drm_bo_t *bo;
210 struct gralloc_drm_handle_t *handle;
211
212 handle = create_bo_handle(width, height, format, usage);
213 if (!handle)
214 return NULL;
215
216 bo = drm->drv->alloc(drm->drv, handle);
217 if (!bo) {
218 free(handle);
219 return NULL;
220 }
221
222 bo->drm = drm;
223 bo->imported = 0;
224 bo->handle = handle;
225
226 handle->data_owner = gralloc_drm_get_pid();
227 handle->data = (int) bo;
228
229 return bo;
230}
231
232/*
233 * Validate a buffer handle and return the associated bo.
234 */
235struct gralloc_drm_bo_t *gralloc_drm_bo_validate(struct gralloc_drm_t *drm,
236 buffer_handle_t _handle)
237{
238 struct gralloc_drm_handle_t *handle = gralloc_drm_handle(_handle);
239
240 /* the buffer handle is passed to a new process */
241 if (handle && unlikely(handle->data_owner != gralloc_drm_pid)) {
242 struct gralloc_drm_bo_t *bo;
243
244 /* create the struct gralloc_drm_bo_t locally */
245 bo = drm->drv->alloc(drm->drv, handle);
246 if (bo) {
247 bo->drm = drm;
248 bo->imported = 1;
249 bo->handle = handle;
250 }
251
252 handle->data_owner = gralloc_drm_get_pid();
253 handle->data = (int) bo;
254 }
255
256 return (struct gralloc_drm_bo_t *) handle->data;
257}
258
259/*
260 * Destroy a bo.
261 */
262void gralloc_drm_bo_destroy(struct gralloc_drm_bo_t *bo)
263{
264 struct gralloc_drm_handle_t *handle = bo->handle;
265 int imported = bo->imported;
266
267 bo->drm->drv->free(bo->drm->drv, bo);
268 if (imported) {
269 handle->data_owner = 0;
270 handle->data = 0;
271 }
272 else {
273 free(handle);
274 }
275}
276
277/*
278 * Map a bo for CPU access.
279 */
280int gralloc_drm_bo_map(struct gralloc_drm_bo_t *bo,
281 int x, int y, int w, int h,
282 int enable_write, void **addr)
283{
284 return bo->drm->drv->map(bo->drm->drv, bo,
285 x, y, w, h, enable_write, addr);
286}
287
288/*
289 * Unmap a bo.
290 */
291void gralloc_drm_bo_unmap(struct gralloc_drm_bo_t *bo)
292{
293 bo->drm->drv->unmap(bo->drm->drv, bo);
294}
295
296/*
297 * Get the buffer handle and stride of a bo.
298 */
299buffer_handle_t gralloc_drm_bo_get_handle(struct gralloc_drm_bo_t *bo, int *stride)
300{
301 if (stride)
302 *stride = bo->handle->stride;
303 return &bo->handle->base;
304}