OSDN Git Service

gralloc: set supported planes for buffers on allocation
[android-x86/external-drm_gralloc.git] / gralloc_drm.c
1 /*
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
41 static int32_t gralloc_drm_pid = 0;
42
43 /*
44  * Return the pid of the process.
45  */
46 static 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  */
57 static struct gralloc_drm_drv_t *
58 init_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                 ALOGE("invalid DRM fd");
67                 return NULL;
68         }
69
70         if (version->name) {
71 #ifdef ENABLE_PIPE
72                 drv = gralloc_drm_drv_create_for_pipe(fd, version->name);
73 #endif
74
75 #ifdef ENABLE_INTEL
76                 if (!drv && !strcmp(version->name, "i915"))
77                         drv = gralloc_drm_drv_create_for_intel(fd);
78 #endif
79 #ifdef ENABLE_RADEON
80                 if (!drv && !strcmp(version->name, "radeon"))
81                         drv = gralloc_drm_drv_create_for_radeon(fd);
82 #endif
83 #ifdef ENABLE_NOUVEAU
84                 if (!drv && !strcmp(version->name, "nouveau"))
85                         drv = gralloc_drm_drv_create_for_nouveau(fd);
86 #endif
87         }
88
89         if (!drv) {
90                 ALOGE("unsupported driver: %s", (version->name) ?
91                                 version->name : "NULL");
92         }
93
94         drmFreeVersion(version);
95
96         return drv;
97 }
98
99 /*
100  * Create a DRM device object.
101  */
102 struct gralloc_drm_t *gralloc_drm_create(void)
103 {
104         struct gralloc_drm_t *drm;
105         int err;
106
107         drm = calloc(1, sizeof(*drm));
108         if (!drm)
109                 return NULL;
110
111         drm->fd = open(GRALLOC_DRM_DEVICE, O_RDWR);
112         if (drm->fd < 0) {
113                 ALOGE("failed to open %s", GRALLOC_DRM_DEVICE);
114                 return NULL;
115         }
116
117         drm->drv = init_drv_from_fd(drm->fd);
118         if (!drm->drv) {
119                 close(drm->fd);
120                 free(drm);
121                 return NULL;
122         }
123
124         return drm;
125 }
126
127 /*
128  * Destroy a DRM device object.
129  */
130 void gralloc_drm_destroy(struct gralloc_drm_t *drm)
131 {
132         if (drm->drv)
133                 drm->drv->destroy(drm->drv);
134         close(drm->fd);
135         free(drm);
136 }
137
138 /*
139  * Get the file descriptor of a DRM device object.
140  */
141 int gralloc_drm_get_fd(struct gralloc_drm_t *drm)
142 {
143         return drm->fd;
144 }
145
146 /*
147  * Get the magic for authentication.
148  */
149 int gralloc_drm_get_magic(struct gralloc_drm_t *drm, int32_t *magic)
150 {
151         return drmGetMagic(drm->fd, (drm_magic_t *) magic);
152 }
153
154 /*
155  * Authenticate a magic.
156  */
157 int gralloc_drm_auth_magic(struct gralloc_drm_t *drm, int32_t magic)
158 {
159         return drmAuthMagic(drm->fd, (drm_magic_t) magic);
160 }
161
162 /*
163  * Set as the master of a DRM device.
164  */
165 int gralloc_drm_set_master(struct gralloc_drm_t *drm)
166 {
167         ALOGD("set master");
168         drmSetMaster(drm->fd);
169         drm->first_post = 1;
170
171         return 0;
172 }
173
174 /*
175  * Drop from the master of a DRM device.
176  */
177 void gralloc_drm_drop_master(struct gralloc_drm_t *drm)
178 {
179         drmDropMaster(drm->fd);
180 }
181
182 /*
183  * Validate a buffer handle and return the associated bo.
184  */
185 static struct gralloc_drm_bo_t *validate_handle(buffer_handle_t _handle,
186                 struct gralloc_drm_t *drm)
187 {
188         struct gralloc_drm_handle_t *handle = gralloc_drm_handle(_handle);
189
190         if (!handle)
191                 return NULL;
192
193         /* the buffer handle is passed to a new process */
194         if (unlikely(handle->data_owner != gralloc_drm_pid)) {
195                 struct gralloc_drm_bo_t *bo;
196
197                 /* check only */
198                 if (!drm)
199                         return NULL;
200
201                 /* create the struct gralloc_drm_bo_t locally */
202                 if (handle->name)
203                         bo = drm->drv->alloc(drm->drv, handle);
204                 else /* an invalid handle */
205                         bo = NULL;
206                 if (bo) {
207                         bo->drm = drm;
208                         bo->imported = 1;
209                         bo->handle = handle;
210                 }
211
212                 handle->data_owner = gralloc_drm_get_pid();
213                 handle->data = (int) bo;
214         }
215
216         return (struct gralloc_drm_bo_t *) handle->data;
217 }
218
219 /*
220  * Register a buffer handle.
221  */
222 int gralloc_drm_handle_register(buffer_handle_t handle, struct gralloc_drm_t *drm)
223 {
224         return (validate_handle(handle, drm)) ? 0 : -EINVAL;
225 }
226
227 /*
228  * Unregister a buffer handle.  It is no-op for handles created locally.
229  */
230 int gralloc_drm_handle_unregister(buffer_handle_t handle)
231 {
232         struct gralloc_drm_bo_t *bo;
233
234         bo = validate_handle(handle, NULL);
235         if (!bo)
236                 return -EINVAL;
237
238         if (bo->imported)
239                 gralloc_drm_bo_decref(bo);
240
241         return 0;
242 }
243
244 /*
245  * Create a buffer handle.
246  */
247 static struct gralloc_drm_handle_t *create_bo_handle(int width,
248                 int height, int format, int usage)
249 {
250         struct gralloc_drm_handle_t *handle;
251
252         handle = calloc(1, sizeof(*handle));
253         if (!handle)
254                 return NULL;
255
256         handle->base.version = sizeof(handle->base);
257         handle->base.numInts = GRALLOC_DRM_HANDLE_NUM_INTS;
258         handle->base.numFds = GRALLOC_DRM_HANDLE_NUM_FDS;
259
260         handle->magic = GRALLOC_DRM_HANDLE_MAGIC;
261         handle->width = width;
262         handle->height = height;
263         handle->format = format;
264         handle->usage = usage;
265         handle->plane_mask = 0;
266
267         return handle;
268 }
269
270 /*
271  * Create a bo.
272  */
273 struct gralloc_drm_bo_t *gralloc_drm_bo_create(struct gralloc_drm_t *drm,
274                 int width, int height, int format, int usage)
275 {
276         struct gralloc_drm_bo_t *bo;
277         struct gralloc_drm_handle_t *handle;
278
279         handle = create_bo_handle(width, height, format, usage);
280         if (!handle)
281                 return NULL;
282
283         handle->plane_mask = planes_for_format(drm, format);
284
285         bo = drm->drv->alloc(drm->drv, handle);
286         if (!bo) {
287                 free(handle);
288                 return NULL;
289         }
290
291         bo->drm = drm;
292         bo->imported = 0;
293         bo->handle = handle;
294         bo->fb_id = 0;
295         bo->refcount = 1;
296
297         handle->data_owner = gralloc_drm_get_pid();
298         handle->data = (int) bo;
299
300         return bo;
301 }
302
303 /*
304  * Destroy a bo.
305  */
306 static void gralloc_drm_bo_destroy(struct gralloc_drm_bo_t *bo)
307 {
308         struct gralloc_drm_handle_t *handle = bo->handle;
309         int imported = bo->imported;
310
311         /* gralloc still has a reference */
312         if (bo->refcount)
313                 return;
314
315         gralloc_drm_bo_rm_fb(bo);
316
317         bo->drm->drv->free(bo->drm->drv, bo);
318         if (imported) {
319                 handle->data_owner = 0;
320                 handle->data = 0;
321         }
322         else {
323                 free(handle);
324         }
325 }
326
327 /*
328  * Decrease refcount, if no refs anymore then destroy.
329  */
330 void gralloc_drm_bo_decref(struct gralloc_drm_bo_t *bo)
331 {
332         if (!--bo->refcount)
333                 gralloc_drm_bo_destroy(bo);
334 }
335
336 /*
337  * Return the bo of a registered handle.
338  */
339 struct gralloc_drm_bo_t *gralloc_drm_bo_from_handle(buffer_handle_t handle)
340 {
341         return validate_handle(handle, NULL);
342 }
343
344 /*
345  * Get the buffer handle and stride of a bo.
346  */
347 buffer_handle_t gralloc_drm_bo_get_handle(struct gralloc_drm_bo_t *bo, int *stride)
348 {
349         if (stride)
350                 *stride = bo->handle->stride;
351         return &bo->handle->base;
352 }
353
354 int gralloc_drm_get_gem_handle(buffer_handle_t _handle)
355 {
356         struct gralloc_drm_handle_t *handle = gralloc_drm_handle(_handle);
357         return (handle) ? handle->name : 0;
358 }
359
360 /*
361  * Query YUV component offsets for a buffer handle
362  */
363 void gralloc_drm_resolve_format(buffer_handle_t _handle,
364         uint32_t *pitches, uint32_t *offsets, uint32_t *handles)
365 {
366         struct gralloc_drm_handle_t *handle = gralloc_drm_handle(_handle);
367         struct gralloc_drm_bo_t *bo = (struct gralloc_drm_bo_t *) handle->data;
368         struct gralloc_drm_t *drm = bo->drm;
369
370         /* if handle exists and driver implements resolve_format */
371         if (handle && drm->drv->resolve_format)
372                 drm->drv->resolve_format(drm->drv, bo,
373                         pitches, offsets, handles);
374 }
375
376 /*
377  * Lock a bo.  XXX thread-safety?
378  */
379 int gralloc_drm_bo_lock(struct gralloc_drm_bo_t *bo,
380                 int usage, int x, int y, int w, int h,
381                 void **addr)
382 {
383         if ((bo->handle->usage & usage) != usage) {
384                 /* make FB special for testing software renderer with */
385                 if (!(bo->handle->usage & GRALLOC_USAGE_HW_FB))
386                         return -EINVAL;
387         }
388
389         /* allow multiple locks with compatible usages */
390         if (bo->lock_count && (bo->locked_for & usage) != usage)
391                 return -EINVAL;
392
393         usage |= bo->locked_for;
394
395         if (usage & (GRALLOC_USAGE_SW_WRITE_MASK |
396                      GRALLOC_USAGE_SW_READ_MASK)) {
397                 /* the driver is supposed to wait for the bo */
398                 int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK);
399                 int err = bo->drm->drv->map(bo->drm->drv, bo,
400                                 x, y, w, h, write, addr);
401                 if (err)
402                         return err;
403         }
404         else {
405                 /* kernel handles the synchronization here */
406         }
407
408         bo->lock_count++;
409         bo->locked_for |= usage;
410
411         return 0;
412 }
413
414 /*
415  * Unlock a bo.
416  */
417 void gralloc_drm_bo_unlock(struct gralloc_drm_bo_t *bo)
418 {
419         int mapped = bo->locked_for &
420                 (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
421
422         if (!bo->lock_count)
423                 return;
424
425         if (mapped)
426                 bo->drm->drv->unmap(bo->drm->drv, bo);
427
428         bo->lock_count--;
429         if (!bo->lock_count)
430                 bo->locked_for = 0;
431 }