OSDN Git Service

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