OSDN Git Service

Merge remote-tracking branch 'origin/master' into nougat-x86
[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 <log/log.h>
28 #include <cutils/atomic.h>
29 #include <cutils/properties.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <assert.h>
38 #include <xf86drm.h>
39
40 #include <hardware/gralloc.h>
41 #include <system/graphics.h>
42
43 #include <gbm.h>
44
45 #include "gralloc_gbm_priv.h"
46 #include <android/gralloc_handle.h>
47
48 #include <unordered_map>
49
50 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
51
52 #define unlikely(x) __builtin_expect(!!(x), 0)
53
54 static std::unordered_map<buffer_handle_t, struct gbm_bo *> gbm_bo_handle_map;
55
56 struct bo_data_t {
57         void *map_data;
58         int lock_count;
59         int locked_for;
60 };
61
62 void gralloc_gbm_destroy_user_data(struct gbm_bo *bo, void *data)
63 {
64         struct bo_data_t *bo_data = (struct bo_data_t *)data;
65         delete bo_data;
66
67         (void)bo;
68 }
69
70 static struct bo_data_t *gbm_bo_data(struct gbm_bo *bo) {
71         return (struct bo_data_t *)gbm_bo_get_user_data(bo);
72 }
73
74
75 static uint32_t get_gbm_format(int format)
76 {
77         uint32_t fmt;
78
79         switch (format) {
80         case HAL_PIXEL_FORMAT_RGBA_8888:
81                 fmt = GBM_FORMAT_ABGR8888;
82                 break;
83         case HAL_PIXEL_FORMAT_RGBX_8888:
84                 fmt = GBM_FORMAT_XBGR8888;
85                 break;
86         case HAL_PIXEL_FORMAT_RGB_888:
87                 fmt = GBM_FORMAT_RGB888;
88                 break;
89         case HAL_PIXEL_FORMAT_RGB_565:
90                 fmt = GBM_FORMAT_RGB565;
91                 break;
92         case HAL_PIXEL_FORMAT_BGRA_8888:
93                 fmt = GBM_FORMAT_ARGB8888;
94                 break;
95         case HAL_PIXEL_FORMAT_YV12:
96                 /* YV12 is planar, but must be a single buffer so ask for GR88 */
97                 fmt = GBM_FORMAT_GR88;
98                 break;
99         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
100         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
101         default:
102                 fmt = 0;
103                 break;
104         }
105
106         return fmt;
107 }
108
109 static int gralloc_gbm_get_bpp(int format)
110 {
111         int bpp;
112
113         switch (format) {
114         case HAL_PIXEL_FORMAT_RGBA_8888:
115         case HAL_PIXEL_FORMAT_RGBX_8888:
116         case HAL_PIXEL_FORMAT_BGRA_8888:
117                 bpp = 4;
118                 break;
119         case HAL_PIXEL_FORMAT_RGB_888:
120                 bpp = 3;
121                 break;
122         case HAL_PIXEL_FORMAT_RGB_565:
123         case HAL_PIXEL_FORMAT_YCbCr_422_I:
124                 bpp = 2;
125                 break;
126         /* planar; only Y is considered */
127         case HAL_PIXEL_FORMAT_YV12:
128         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
129         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
130                 bpp = 1;
131                 break;
132         default:
133                 bpp = 0;
134                 break;
135         }
136
137         return bpp;
138 }
139
140 static unsigned int get_pipe_bind(int usage)
141 {
142         unsigned int bind = 0;
143
144         if (usage & (GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN))
145                 bind |= GBM_BO_USE_LINEAR;
146         if (usage & GRALLOC_USAGE_CURSOR)
147                 ;//bind |= GBM_BO_USE_CURSOR;
148         if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
149                 bind |= GBM_BO_USE_RENDERING;
150         if (usage & GRALLOC_USAGE_HW_FB)
151                 bind |= GBM_BO_USE_SCANOUT;
152         if (usage & GRALLOC_USAGE_HW_COMPOSER)
153                 bind |= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
154
155         return bind;
156 }
157
158 static struct gbm_bo *gbm_import(struct gbm_device *gbm,
159                 buffer_handle_t _handle)
160 {
161         struct gbm_bo *bo;
162         struct gralloc_handle_t *handle = gralloc_handle(_handle);
163         #ifdef GBM_BO_IMPORT_FD_MODIFIER
164         struct gbm_import_fd_modifier_data data;
165         #else
166         struct gbm_import_fd_data data;
167         #endif
168
169         int format = get_gbm_format(handle->format);
170         if (handle->prime_fd < 0)
171                 return NULL;
172
173         memset(&data, 0, sizeof(data));
174         data.width = handle->width;
175         data.height = handle->height;
176         data.format = format;
177         /* Adjust the width and height for a GBM GR88 buffer */
178         if (handle->format == HAL_PIXEL_FORMAT_YV12) {
179                 data.width /= 2;
180                 data.height += handle->height / 2;
181         }
182
183         #ifdef GBM_BO_IMPORT_FD_MODIFIER
184         data.num_fds = 1;
185         data.fds[0] = handle->prime_fd;
186         data.strides[0] = handle->stride;
187         data.modifier = handle->modifier;
188         bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_MODIFIER, &data, 0);
189         #else
190         data.fd = handle->prime_fd;
191         data.stride = handle->stride;
192         bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
193         #endif
194
195         return bo;
196 }
197
198 static struct gbm_bo *gbm_alloc(struct gbm_device *gbm,
199                 buffer_handle_t _handle)
200 {
201         struct gbm_bo *bo;
202         struct gralloc_handle_t *handle = gralloc_handle(_handle);
203         int format = get_gbm_format(handle->format);
204         int usage = get_pipe_bind(handle->usage);
205         int width, height;
206
207         width = handle->width;
208         height = handle->height;
209         if (usage & GBM_BO_USE_CURSOR) {
210                 if (handle->width < 64)
211                         width = 64;
212                 if (handle->height < 64)
213                         height = 64;
214         }
215
216         /*
217          * For YV12, we request GR88, so halve the width since we're getting
218          * 16bpp. Then increase the height by 1.5 for the U and V planes.
219          */
220         if (handle->format == HAL_PIXEL_FORMAT_YV12) {
221                 width /= 2;
222                 height += handle->height / 2;
223         }
224
225         ALOGV("create BO, size=%dx%d, fmt=%d, usage=%x",
226               handle->width, handle->height, handle->format, usage);
227         bo = gbm_bo_create(gbm, width, height, format, usage);
228         if (!bo) {
229                 ALOGE("failed to create BO, size=%dx%d, fmt=%d, usage=%x",
230                       handle->width, handle->height, handle->format, usage);
231                 return NULL;
232         }
233
234         handle->prime_fd = gbm_bo_get_fd(bo);
235         handle->stride = gbm_bo_get_stride(bo);
236         #ifdef GBM_BO_IMPORT_FD_MODIFIER
237         handle->modifier = gbm_bo_get_modifier(bo);
238         #endif
239
240         return bo;
241 }
242
243 int gbm_free(buffer_handle_t handle)
244 {
245         struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
246
247         if (!bo)
248                 return -EINVAL;
249
250         gbm_bo_handle_map.erase(handle);
251         gbm_bo_destroy(bo);
252         return 0;
253 }
254
255 /*
256  * Return the bo of a registered handle.
257  */
258 struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
259 {
260         return gbm_bo_handle_map[handle];
261 }
262
263 static int gbm_map(buffer_handle_t handle, int enable_write, void **addr)
264 {
265         int err = 0;
266         int flags = GBM_BO_TRANSFER_READ;
267         struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
268         struct bo_data_t *bo_data = gbm_bo_data(bo);
269         uint32_t stride;
270
271         if (bo_data->map_data)
272                 return -EINVAL;
273
274         if (enable_write)
275                 flags |= GBM_BO_TRANSFER_WRITE;
276
277         *addr = gbm_bo_map(bo, 0, 0, gbm_bo_get_width(bo), gbm_bo_get_height(bo),
278                            flags, &stride, &bo_data->map_data);
279         ALOGV("mapped bo %p at %p", bo, *addr);
280         if (*addr == NULL)
281                 return -ENOMEM;
282
283         assert(stride == gbm_bo_get_stride(bo));
284
285         return err;
286 }
287
288 static void gbm_unmap(struct gbm_bo *bo)
289 {
290         struct bo_data_t *bo_data = gbm_bo_data(bo);
291
292         gbm_bo_unmap(bo, bo_data->map_data);
293         bo_data->map_data = NULL;
294 }
295
296 void gbm_dev_destroy(struct gbm_device *gbm)
297 {
298         int fd = gbm_device_get_fd(gbm);
299
300         gbm_device_destroy(gbm);
301         close(fd);
302 }
303
304 struct gbm_device *gbm_dev_create(bool master)
305 {
306         struct gbm_device *gbm;
307         char path[PROPERTY_VALUE_MAX];
308         int fd;
309
310         if (property_get("gralloc.gbm.device", path, NULL) > 0)
311                 fd = open(path, O_RDWR | O_CLOEXEC);
312         else
313                 fd = drmOpenByFB(0, master ? DRM_NODE_PRIMARY : DRM_NODE_RENDER);
314
315         if (fd < 0) {
316                 ALOGE("failed to open %s", path);
317                 return NULL;
318         }
319
320         gbm = gbm_create_device(fd);
321         if (!gbm) {
322                 ALOGE("failed to create gbm device");
323                 close(fd);
324         }
325
326         return gbm;
327 }
328
329 /*
330  * Register a buffer handle.
331  */
332 int gralloc_gbm_handle_register(buffer_handle_t _handle, struct gbm_device *gbm)
333 {
334         struct gbm_bo *bo;
335
336         if (!_handle)
337                 return -EINVAL;
338
339         if (gbm_bo_handle_map.count(_handle))
340                 return -EINVAL;
341
342         bo = gbm_import(gbm, _handle);
343         if (!bo)
344                 return -EINVAL;
345
346         gbm_bo_handle_map.emplace(_handle, bo);
347
348         return 0;
349 }
350
351 /*
352  * Unregister a buffer handle.  It is no-op for handles created locally.
353  */
354 int gralloc_gbm_handle_unregister(buffer_handle_t handle)
355 {
356         return gbm_free(handle);
357 }
358
359 /*
360  * Create a bo.
361  */
362 buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm,
363                 int width, int height, int format, int usage, int *stride)
364 {
365         struct gbm_bo *bo;
366         native_handle_t *handle;
367
368         handle = gralloc_handle_create(width, height, format, usage);
369         if (!handle)
370                 return NULL;
371
372         bo = gbm_alloc(gbm, handle);
373         if (!bo) {
374                 native_handle_delete(handle);
375                 return NULL;
376         }
377
378         gbm_bo_handle_map.emplace(handle, bo);
379
380         /* in pixels */
381         *stride = gralloc_handle(handle)->stride / gralloc_gbm_get_bpp(format);
382
383         return handle;
384 }
385
386 /*
387  * Lock a bo.  XXX thread-safety?
388  */
389 int gralloc_gbm_bo_lock(buffer_handle_t handle,
390                 int usage, int /*x*/, int /*y*/, int /*w*/, int /*h*/,
391                 void **addr)
392 {
393         struct gralloc_handle_t *gbm_handle = gralloc_handle(handle);
394         struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
395         struct bo_data_t *bo_data;
396
397         if (!bo)
398                 return -EINVAL;
399
400         if ((gbm_handle->usage & usage) != (uint32_t)usage) {
401                 /* make FB special for testing software renderer with */
402
403                 if (!(gbm_handle->usage & GRALLOC_USAGE_SW_READ_OFTEN) &&
404                                 !(gbm_handle->usage & GRALLOC_USAGE_HW_FB) &&
405                                 !(gbm_handle->usage & GRALLOC_USAGE_HW_TEXTURE)) {
406                         ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_FB or GRALLOC_USAGE_HW_TEXTURE",
407                                 gbm_handle->usage, usage);
408                         return -EINVAL;
409                 }
410         }
411
412         bo_data = gbm_bo_data(bo);
413         if (!bo_data) {
414                 bo_data = new struct bo_data_t();
415                 gbm_bo_set_user_data(bo, bo_data, gralloc_gbm_destroy_user_data);
416         }
417
418         ALOGV("lock bo %p, cnt=%d, usage=%x", bo, bo_data->lock_count, usage);
419
420         /* allow multiple locks with compatible usages */
421         if (bo_data->lock_count && (bo_data->locked_for & usage) != usage)
422                 return -EINVAL;
423
424         usage |= bo_data->locked_for;
425
426         if (usage & (GRALLOC_USAGE_SW_WRITE_MASK |
427                      GRALLOC_USAGE_SW_READ_MASK)) {
428                 /* the driver is supposed to wait for the bo */
429                 int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK);
430                 int err = gbm_map(handle, write, addr);
431                 if (err)
432                         return err;
433         }
434         else {
435                 /* kernel handles the synchronization here */
436         }
437
438         bo_data->lock_count++;
439         bo_data->locked_for |= usage;
440
441         return 0;
442 }
443
444 /*
445  * Unlock a bo.
446  */
447 int gralloc_gbm_bo_unlock(buffer_handle_t handle)
448 {
449         struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
450         struct bo_data_t *bo_data;
451         if (!bo)
452                 return -EINVAL;
453
454         bo_data = gbm_bo_data(bo);
455
456         int mapped = bo_data->locked_for &
457                 (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
458
459         if (!bo_data->lock_count)
460                 return 0;
461
462         if (mapped)
463                 gbm_unmap(bo);
464
465         bo_data->lock_count--;
466         if (!bo_data->lock_count)
467                 bo_data->locked_for = 0;
468
469         return 0;
470 }
471
472 #define GRALLOC_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
473
474 int gralloc_gbm_bo_lock_ycbcr(buffer_handle_t handle,
475                 int usage, int x, int y, int w, int h,
476                 struct android_ycbcr *ycbcr)
477 {
478         struct gralloc_handle_t *hnd = gralloc_handle(handle);
479         int ystride, cstride;
480         void *addr = 0;
481         int err;
482
483         ALOGV("handle %p, hnd %p, usage 0x%x", handle, hnd, usage);
484
485         err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, &addr);
486         if (err)
487                 return err;
488
489         memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
490
491         switch (hnd->format) {
492         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
493                 ystride = cstride = GRALLOC_ALIGN(hnd->width, 16);
494                 ycbcr->y = addr;
495                 ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
496                 ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + 1;
497                 ycbcr->ystride = ystride;
498                 ycbcr->cstride = cstride;
499                 ycbcr->chroma_step = 2;
500                 break;
501         case HAL_PIXEL_FORMAT_YV12:
502                 ystride = hnd->width;
503                 cstride = GRALLOC_ALIGN(ystride / 2, 16);
504                 ycbcr->y = addr;
505                 ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
506                 ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + cstride * hnd->height / 2;
507                 ycbcr->ystride = ystride;
508                 ycbcr->cstride = cstride;
509                 ycbcr->chroma_step = 1;
510                 break;
511         default:
512                 ALOGE("Can not lock buffer, invalid format: 0x%x", hnd->format);
513                 return -EINVAL;
514         }
515
516         return 0;
517 }