OSDN Git Service

Use alternative GRALLOC_GBM_HANDLE_MAGIC
[android-x86/external-gbm_gralloc.git] / gralloc_gbm.cpp
1 /*
2  * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
3  * Copyright (C) 2010-2011 LunarG Inc.
4  * Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #define LOG_TAG "GRALLOC-GBM"
26
27 #include <cutils/log.h>
28 #include <cutils/atomic.h>
29 #include <cutils/properties.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <assert.h>
36
37 #include <hardware/gralloc.h>
38 #include <system/graphics.h>
39
40 #include <gbm.h>
41
42 #include "gralloc_gbm_priv.h"
43 #include "gralloc_drm_handle.h"
44
45 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
46
47 #define unlikely(x) __builtin_expect(!!(x), 0)
48
49 struct gralloc_gbm_bo_t {
50         struct gbm_bo *bo;
51         void *map_data;
52
53         struct gralloc_gbm_handle_t *handle;
54
55         int imported;  /* the handle is from a remote proces when true */
56
57         int lock_count;
58         int locked_for;
59
60         unsigned int refcount;
61 };
62
63 static int32_t gralloc_gbm_pid = 0;
64
65 static uint32_t get_gbm_format(int format)
66 {
67         uint32_t fmt;
68
69         switch (format) {
70         case HAL_PIXEL_FORMAT_RGBA_8888:
71                 fmt = GBM_FORMAT_ABGR8888;
72                 break;
73         case HAL_PIXEL_FORMAT_RGBX_8888:
74                 fmt = GBM_FORMAT_XBGR8888;
75                 break;
76         case HAL_PIXEL_FORMAT_RGB_888:
77                 fmt = GBM_FORMAT_RGB888;
78                 break;
79         case HAL_PIXEL_FORMAT_RGB_565:
80                 fmt = GBM_FORMAT_RGB565;
81                 break;
82         case HAL_PIXEL_FORMAT_BGRA_8888:
83                 fmt = GBM_FORMAT_ARGB8888;
84                 break;
85         case HAL_PIXEL_FORMAT_YV12:
86         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
87         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
88         default:
89                 fmt = 0;
90                 break;
91         }
92
93         return fmt;
94 }
95
96 static unsigned int get_pipe_bind(int usage)
97 {
98         unsigned int bind = 0;
99
100         if (usage & (GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN))
101                 bind |= GBM_BO_USE_LINEAR;
102         if (usage & GRALLOC_USAGE_CURSOR)
103                 ;//bind |= GBM_BO_USE_CURSOR;
104         if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
105                 bind |= GBM_BO_USE_RENDERING;
106         if (usage & GRALLOC_USAGE_HW_FB)
107                 bind |= GBM_BO_USE_SCANOUT;
108
109         return bind;
110 }
111
112 static struct gralloc_gbm_bo_t *gbm_import(struct gbm_device *gbm,
113                 struct gralloc_gbm_handle_t *handle)
114 {
115         struct gralloc_gbm_bo_t *buf;
116         struct gbm_import_fd_data data;
117         int format = get_gbm_format(handle->format);
118
119         if (handle->prime_fd < 0)
120                 return NULL;
121
122         buf = new struct gralloc_gbm_bo_t();
123         if (!buf) {
124                 ALOGE("failed to allocate pipe buffer");
125                 return NULL;
126         }
127
128         data.fd = handle->prime_fd;
129         data.width = handle->width;
130         data.height = handle->height;
131         data.stride = handle->stride;
132         data.format = format;
133
134         buf->bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
135         if (!buf->bo) {
136                 delete buf;
137                 return NULL;
138         }
139         return buf;
140 }
141
142 static struct gralloc_gbm_bo_t *gbm_alloc(struct gbm_device *gbm,
143                 struct gralloc_gbm_handle_t *handle)
144 {
145         struct gralloc_gbm_bo_t *buf;
146         int format = get_gbm_format(handle->format);
147         int usage = get_pipe_bind(handle->usage);
148         int width, height;
149
150         buf = new struct gralloc_gbm_bo_t();
151         if (!buf) {
152                 ALOGE("failed to allocate pipe buffer");
153                 return NULL;
154         }
155
156         width = handle->width;
157         height = handle->height;
158         if (usage & GBM_BO_USE_CURSOR) {
159                 if (handle->width < 64)
160                         width = 64;
161                 if (handle->height < 64)
162                         height = 64;
163         }
164
165         ALOGD("create BO, size=%dx%d, fmt=%d, usage=%x",
166               handle->width, handle->height, handle->format, usage);
167         buf->bo = gbm_bo_create(gbm, width, height, format, usage);
168         if (!buf->bo) {
169                 ALOGE("failed to create BO, size=%dx%d, fmt=%d, usage=%x",
170                       handle->width, handle->height, handle->format, usage);
171                 delete buf;
172                 return NULL;
173         }
174
175         handle->prime_fd = gbm_bo_get_fd(buf->bo);
176         handle->stride = gbm_bo_get_stride(buf->bo);
177
178         return buf;
179 }
180
181 static void gbm_free(struct gralloc_gbm_bo_t *bo)
182 {
183         struct gralloc_gbm_handle_t *handle = bo->handle;
184
185         close(handle->prime_fd);
186         handle->prime_fd = -1;
187
188         gbm_bo_destroy(bo->bo);
189         delete bo;
190 }
191
192 static int gbm_map(struct gralloc_gbm_bo_t *bo, int x, int y, int w, int h,
193                 int enable_write, void **addr)
194 {
195         int err = 0;
196         int flags = GBM_BO_TRANSFER_READ;
197         uint32_t stride;
198
199         if (bo->map_data)
200                 return -EINVAL;
201
202         if (enable_write)
203                 flags |= GBM_BO_TRANSFER_WRITE;
204
205         *addr = gbm_bo_map(bo->bo, x, y, w, h, flags, &stride, &bo->map_data);
206         ALOGE("mapped bo %p at %p", bo, *addr);
207         if (*addr == NULL)
208                 return -ENOMEM;
209
210         assert(stride == gbm_bo_get_stride(bo));
211
212         return err;
213 }
214
215 static void gbm_unmap(struct gralloc_gbm_bo_t *bo)
216 {
217         gbm_bo_unmap(bo->bo, bo->map_data);
218         bo->map_data = NULL;
219 }
220
221 void gbm_dev_destroy(struct gbm_device *gbm)
222 {
223         int fd = gbm_device_get_fd(gbm);
224
225         gbm_device_destroy(gbm);
226         close(fd);
227 }
228
229 struct gbm_device *gbm_dev_create(void)
230 {
231         struct gbm_device *gbm;
232         char path[PROPERTY_VALUE_MAX];
233         int fd;
234
235         property_get("gralloc.gbm.device", path, "/dev/dri/renderD128");
236         fd = open(path, O_RDWR | O_CLOEXEC);
237         if (fd < 0) {
238                 ALOGE("failed to open %s", path);
239                 return NULL;
240         }
241
242         gbm = gbm_create_device(fd);
243         if (!gbm) {
244                 ALOGE("failed to create gbm device");
245                 close(fd);
246         }
247
248         return gbm;
249 }
250
251 /*
252  * Return the pid of the process.
253  */
254 static int gralloc_gbm_get_pid(void)
255 {
256         if (unlikely(!gralloc_gbm_pid))
257                 android_atomic_write((int32_t) getpid(), &gralloc_gbm_pid);
258
259         return gralloc_gbm_pid;
260 }
261
262 /*
263  * Validate a buffer handle and return the associated bo.
264  */
265 static struct gralloc_gbm_bo_t *validate_handle(buffer_handle_t _handle,
266                 struct gbm_device *gbm)
267 {
268         struct gralloc_gbm_bo_t *bo;
269         struct gralloc_gbm_handle_t *handle = gralloc_gbm_handle(_handle);
270
271         if (!handle)
272                 return NULL;
273
274         /* the buffer handle is passed to a new process */
275         //ALOGE("data_owner=%d gralloc_pid=%d data=%p\n", handle->data_owner, gralloc_gbm_get_pid(), handle->data);
276         if (handle->data_owner == gralloc_gbm_get_pid())
277                 return (struct gralloc_gbm_bo_t *)handle->data;
278
279         /* check only */
280         if (!gbm)
281                 return NULL;
282
283         ALOGE("handle: name=%d pfd=%d\n", handle->name,
284                 handle->prime_fd);
285         /* create the struct gralloc_gbm_bo_t locally */
286         if (handle->name || handle->prime_fd >= 0)
287                 bo = gbm_import(gbm, handle);
288         else /* an invalid handle */
289                 bo = NULL;
290         if (bo) {
291                 bo->imported = 1;
292                 bo->handle = handle;
293                 bo->refcount = 1;
294         }
295
296         handle->data_owner = gralloc_gbm_get_pid();
297         handle->data = bo;
298
299         return bo;
300 }
301
302 /*
303  * Register a buffer handle.
304  */
305 int gralloc_gbm_handle_register(buffer_handle_t handle, struct gbm_device *gbm)
306 {
307         return (validate_handle(handle, gbm)) ? 0 : -EINVAL;
308 }
309
310 /*
311  * Unregister a buffer handle.  It is no-op for handles created locally.
312  */
313 int gralloc_gbm_handle_unregister(buffer_handle_t handle)
314 {
315         struct gralloc_gbm_bo_t *bo;
316
317         bo = validate_handle(handle, NULL);
318         if (!bo)
319                 return -EINVAL;
320
321         if (bo->imported)
322                 gralloc_gbm_bo_decref(bo);
323
324         return 0;
325 }
326
327 /*
328  * Create a buffer handle.
329  */
330 static struct gralloc_gbm_handle_t *create_bo_handle(int width,
331                 int height, int format, int usage)
332 {
333         struct gralloc_gbm_handle_t *handle;
334
335         handle = new gralloc_gbm_handle_t();
336         if (!handle)
337                 return NULL;
338
339         handle->base.version = sizeof(handle->base);
340         handle->base.numInts = GRALLOC_GBM_HANDLE_NUM_INTS;
341         handle->base.numFds = GRALLOC_GBM_HANDLE_NUM_FDS;
342
343         handle->magic = GRALLOC_GBM_HANDLE_MAGIC;
344         handle->width = width;
345         handle->height = height;
346         handle->format = format;
347         handle->usage = usage;
348         handle->prime_fd = -1;
349
350         return handle;
351 }
352
353 /*
354  * Create a bo.
355  */
356 struct gralloc_gbm_bo_t *gralloc_gbm_bo_create(struct gbm_device *gbm,
357                 int width, int height, int format, int usage)
358 {
359         struct gralloc_gbm_bo_t *bo;
360         struct gralloc_gbm_handle_t *handle;
361
362         handle = create_bo_handle(width, height, format, usage);
363         if (!handle)
364                 return NULL;
365
366         bo = gbm_alloc(gbm, handle);
367         if (!bo) {
368                 delete handle;
369                 return NULL;
370         }
371
372         bo->imported = 0;
373         bo->handle = handle;
374         bo->refcount = 1;
375
376         handle->data_owner = gralloc_gbm_get_pid();
377         handle->data = bo;
378
379         return bo;
380 }
381
382 /*
383  * Destroy a bo.
384  */
385 static void gralloc_gbm_bo_destroy(struct gralloc_gbm_bo_t *bo)
386 {
387         struct gralloc_gbm_handle_t *handle = bo->handle;
388         int imported = bo->imported;
389
390         /* gralloc still has a reference */
391         if (bo->refcount)
392                 return;
393
394         gbm_free(bo);
395         if (imported) {
396                 handle->data_owner = 0;
397                 handle->data = 0;
398         }
399         else {
400                 delete handle;
401         }
402 }
403
404 /*
405  * Decrease refcount, if no refs anymore then destroy.
406  */
407 void gralloc_gbm_bo_decref(struct gralloc_gbm_bo_t *bo)
408 {
409         if (!--bo->refcount)
410                 gralloc_gbm_bo_destroy(bo);
411 }
412
413 /*
414  * Return the bo of a registered handle.
415  */
416 struct gralloc_gbm_bo_t *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
417 {
418         return validate_handle(handle, NULL);
419 }
420
421 /*
422  * Get the buffer handle and stride of a bo.
423  */
424 buffer_handle_t gralloc_gbm_bo_get_handle(struct gralloc_gbm_bo_t *bo)
425 {
426         return &bo->handle->base;
427 }
428
429 /*
430  * Get the buffer handle and stride of a bo.
431  */
432 struct gbm_bo *gralloc_gbm_bo_to_gbm_bo(struct gralloc_gbm_bo_t *_bo)
433 {
434         return _bo->bo;
435 }
436
437 /*
438  * Lock a bo.  XXX thread-safety?
439  */
440 int gralloc_gbm_bo_lock(struct gralloc_gbm_bo_t *bo,
441                 int usage, int x, int y, int w, int h,
442                 void **addr)
443 {
444         if ((bo->handle->usage & usage) != usage) {
445                 /* make FB special for testing software renderer with */
446
447                 if (!(bo->handle->usage & GRALLOC_USAGE_SW_READ_OFTEN) &&
448                                 !(bo->handle->usage & GRALLOC_USAGE_HW_FB) &&
449                                 !(bo->handle->usage & GRALLOC_USAGE_HW_TEXTURE)) {
450                         ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_FB or GRALLOC_USAGE_HW_TEXTURE",
451                                 bo->handle->usage, usage);
452                         return -EINVAL;
453                 }
454         }
455
456         /* allow multiple locks with compatible usages */
457         if (bo->lock_count && (bo->locked_for & usage) != usage)
458                 return -EINVAL;
459
460         usage |= bo->locked_for;
461
462         if (usage & (GRALLOC_USAGE_SW_WRITE_MASK |
463                      GRALLOC_USAGE_SW_READ_MASK)) {
464                 /* the driver is supposed to wait for the bo */
465                 int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK);
466                 int err = gbm_map(bo, x, y, w, h, write, addr);
467                 if (err)
468                         return err;
469         }
470         else {
471                 /* kernel handles the synchronization here */
472         }
473
474         bo->lock_count++;
475         bo->locked_for |= usage;
476
477         return 0;
478 }
479
480 /*
481  * Unlock a bo.
482  */
483 void gralloc_gbm_bo_unlock(struct gralloc_gbm_bo_t *bo)
484 {
485         int mapped = bo->locked_for &
486                 (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
487
488         if (!bo->lock_count)
489                 return;
490
491         if (mapped)
492                 gbm_unmap(bo);
493
494         bo->lock_count--;
495         if (!bo->lock_count)
496                 bo->locked_for = 0;
497 }