OSDN Git Service

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