OSDN Git Service

Update usage flag handling
[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
36 #include <hardware/gralloc.h>
37 #include <system/graphics.h>
38
39 #include <gbm.h>
40
41 #include "gralloc_gbm_priv.h"
42 #include "gralloc_drm_handle.h"
43
44 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
45
46 #define unlikely(x) __builtin_expect(!!(x), 0)
47
48 struct gralloc_gbm_bo_t {
49         struct gbm_bo *bo;
50         void *map_data;
51
52         struct gralloc_gbm_handle_t *handle;
53
54         int imported;  /* the handle is from a remote proces when true */
55
56         int lock_count;
57         int locked_for;
58
59         unsigned int refcount;
60 };
61
62 static int32_t gralloc_gbm_pid = 0;
63
64 static uint32_t get_gbm_format(int format)
65 {
66         uint32_t fmt;
67
68         switch (format) {
69         case HAL_PIXEL_FORMAT_RGBA_8888:
70                 fmt = GBM_FORMAT_ABGR8888;
71                 break;
72         case HAL_PIXEL_FORMAT_RGBX_8888:
73                 fmt = GBM_FORMAT_XBGR8888;
74                 break;
75         case HAL_PIXEL_FORMAT_RGB_888:
76                 fmt = GBM_FORMAT_RGB888;
77                 break;
78         case HAL_PIXEL_FORMAT_RGB_565:
79                 fmt = GBM_FORMAT_BGR565;
80                 break;
81         case HAL_PIXEL_FORMAT_BGRA_8888:
82                 fmt = GBM_FORMAT_ARGB8888;
83                 break;
84         case HAL_PIXEL_FORMAT_YV12:
85         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
86         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
87         default:
88                 fmt = 0;
89                 break;
90         }
91
92         return fmt;
93 }
94
95 static unsigned int get_pipe_bind(int usage)
96 {
97         unsigned int bind = 0;
98
99         if (usage & (GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN))
100                 bind |= GBM_BO_USE_LINEAR;
101         if (usage & GRALLOC_USAGE_CURSOR)
102                 ;//bind |= GBM_BO_USE_CURSOR;
103         if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
104                 bind |= GBM_BO_USE_RENDERING;
105         if (usage & GRALLOC_USAGE_HW_FB)
106                 bind |= GBM_BO_USE_SCANOUT;
107
108         return bind;
109 }
110
111 static struct gralloc_gbm_bo_t *gbm_import(struct gbm_device *gbm,
112                 struct gralloc_gbm_handle_t *handle)
113 {
114         struct gralloc_gbm_bo_t *buf;
115         struct gbm_import_fd_data data;
116         int format = get_gbm_format(handle->format);
117         int usage = get_pipe_bind(handle->usage);
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
197         if (bo->map_data)
198                 return -EINVAL;
199
200         *addr = gbm_bo_map(bo->bo, x, y, w, h, 0, &bo->map_data);
201         ALOGE("mapped bo %p at %p", bo, *addr);
202         if (*addr == NULL)
203                 err = -ENOMEM;
204
205         return err;
206 }
207
208 static void gbm_unmap(struct gralloc_gbm_bo_t *bo)
209 {
210         gbm_bo_unmap(bo->bo, bo->map_data);
211         bo->map_data = NULL;
212 }
213
214 void gbm_dev_destroy(struct gbm_device *gbm)
215 {
216         int fd = gbm_device_get_fd(gbm);
217
218         gbm_device_destroy(gbm);
219         close(fd);
220 }
221
222 struct gbm_device *gbm_dev_create(void)
223 {
224         struct gbm_device *gbm;
225         char path[PROPERTY_VALUE_MAX];
226         int fd;
227
228         property_get("gralloc.gbm.device", path, "/dev/dri/renderD128");
229         fd = open(path, O_RDWR);
230         if (fd < 0) {
231                 ALOGE("failed to open %s", path);
232                 return NULL;
233         }
234
235         gbm = gbm_create_device(fd);
236         if (!gbm) {
237                 ALOGE("failed to create gbm device");
238         }
239
240         return gbm;
241 }
242
243 /*
244  * Return the pid of the process.
245  */
246 static int gralloc_gbm_get_pid(void)
247 {
248         if (unlikely(!gralloc_gbm_pid))
249                 android_atomic_write((int32_t) getpid(), &gralloc_gbm_pid);
250
251         return gralloc_gbm_pid;
252 }
253
254 /*
255  * Validate a buffer handle and return the associated bo.
256  */
257 static struct gralloc_gbm_bo_t *validate_handle(buffer_handle_t _handle,
258                 struct gbm_device *gbm)
259 {
260         struct gralloc_gbm_bo_t *bo;
261         struct gralloc_gbm_handle_t *handle = gralloc_gbm_handle(_handle);
262
263         if (!handle)
264                 return NULL;
265
266         /* the buffer handle is passed to a new process */
267         //ALOGE("data_owner=%d gralloc_pid=%d data=%p\n", handle->data_owner, gralloc_gbm_get_pid(), handle->data);
268         if (handle->data_owner == gralloc_gbm_get_pid())
269                 return (struct gralloc_gbm_bo_t *)handle->data;
270
271         /* check only */
272         if (!gbm)
273                 return NULL;
274
275         ALOGE("handle: name=%d pfd=%d\n", handle->name,
276                 handle->prime_fd);
277         /* create the struct gralloc_gbm_bo_t locally */
278         if (handle->name || handle->prime_fd >= 0)
279                 bo = gbm_import(gbm, handle);
280         else /* an invalid handle */
281                 bo = NULL;
282         if (bo) {
283                 bo->imported = 1;
284                 bo->handle = handle;
285                 bo->refcount = 1;
286         }
287
288         handle->data_owner = gralloc_gbm_get_pid();
289         handle->data = bo;
290
291         return bo;
292 }
293
294 /*
295  * Register a buffer handle.
296  */
297 int gralloc_gbm_handle_register(buffer_handle_t handle, struct gbm_device *gbm)
298 {
299         return (validate_handle(handle, gbm)) ? 0 : -EINVAL;
300 }
301
302 /*
303  * Unregister a buffer handle.  It is no-op for handles created locally.
304  */
305 int gralloc_gbm_handle_unregister(buffer_handle_t handle)
306 {
307         struct gralloc_gbm_bo_t *bo;
308
309         bo = validate_handle(handle, NULL);
310         if (!bo)
311                 return -EINVAL;
312
313         if (bo->imported)
314                 gralloc_gbm_bo_decref(bo);
315
316         return 0;
317 }
318
319 /*
320  * Create a buffer handle.
321  */
322 static struct gralloc_gbm_handle_t *create_bo_handle(int width,
323                 int height, int format, int usage)
324 {
325         struct gralloc_gbm_handle_t *handle;
326
327         handle = new gralloc_gbm_handle_t();
328         if (!handle)
329                 return NULL;
330
331         handle->base.version = sizeof(handle->base);
332         handle->base.numInts = GRALLOC_GBM_HANDLE_NUM_INTS;
333         handle->base.numFds = GRALLOC_GBM_HANDLE_NUM_FDS;
334
335         handle->magic = GRALLOC_GBM_HANDLE_MAGIC;
336         handle->width = width;
337         handle->height = height;
338         handle->format = format;
339         handle->usage = usage;
340         handle->prime_fd = -1;
341
342         return handle;
343 }
344
345 /*
346  * Create a bo.
347  */
348 struct gralloc_gbm_bo_t *gralloc_gbm_bo_create(struct gbm_device *gbm,
349                 int width, int height, int format, int usage)
350 {
351         struct gralloc_gbm_bo_t *bo;
352         struct gralloc_gbm_handle_t *handle;
353
354         handle = create_bo_handle(width, height, format, usage);
355         if (!handle)
356                 return NULL;
357
358         bo = gbm_alloc(gbm, handle);
359         if (!bo) {
360                 delete handle;
361                 return NULL;
362         }
363
364         bo->imported = 0;
365         bo->handle = handle;
366         bo->refcount = 1;
367
368         handle->data_owner = gralloc_gbm_get_pid();
369         handle->data = bo;
370
371         return bo;
372 }
373
374 /*
375  * Destroy a bo.
376  */
377 static void gralloc_gbm_bo_destroy(struct gralloc_gbm_bo_t *bo)
378 {
379         struct gralloc_gbm_handle_t *handle = bo->handle;
380         int imported = bo->imported;
381
382         /* gralloc still has a reference */
383         if (bo->refcount)
384                 return;
385
386         gbm_free(bo);
387         if (imported) {
388                 handle->data_owner = 0;
389                 handle->data = 0;
390         }
391         else {
392                 delete handle;
393         }
394 }
395
396 /*
397  * Decrease refcount, if no refs anymore then destroy.
398  */
399 void gralloc_gbm_bo_decref(struct gralloc_gbm_bo_t *bo)
400 {
401         if (!--bo->refcount)
402                 gralloc_gbm_bo_destroy(bo);
403 }
404
405 /*
406  * Return the bo of a registered handle.
407  */
408 struct gralloc_gbm_bo_t *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
409 {
410         return validate_handle(handle, NULL);
411 }
412
413 /*
414  * Get the buffer handle and stride of a bo.
415  */
416 buffer_handle_t gralloc_gbm_bo_get_handle(struct gralloc_gbm_bo_t *bo)
417 {
418         return &bo->handle->base;
419 }
420
421 /*
422  * Get the buffer handle and stride of a bo.
423  */
424 struct gbm_bo *gralloc_gbm_bo_to_gbm_bo(struct gralloc_gbm_bo_t *_bo)
425 {
426         return _bo->bo;
427 }
428
429 /*
430  * Query YUV component offsets for a buffer handle
431  */
432 void gralloc_gbm_resolve_format(buffer_handle_t _handle,
433         uint32_t *pitches, uint32_t *offsets, uint32_t *handles)
434 {}
435
436 /*
437  * Lock a bo.  XXX thread-safety?
438  */
439 int gralloc_gbm_bo_lock(struct gralloc_gbm_bo_t *bo,
440                 int usage, int x, int y, int w, int h,
441                 void **addr)
442 {
443         if ((bo->handle->usage & usage) != usage) {
444                 /* make FB special for testing software renderer with */
445
446                 if (!(bo->handle->usage & GRALLOC_USAGE_SW_READ_OFTEN) &&
447                                 !(bo->handle->usage & GRALLOC_USAGE_HW_FB) &&
448                                 !(bo->handle->usage & GRALLOC_USAGE_HW_TEXTURE)) {
449                         ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_FB or GRALLOC_USAGE_HW_TEXTURE",
450                                 bo->handle->usage, usage);
451                         return -EINVAL;
452                 }
453         }
454
455         /* allow multiple locks with compatible usages */
456         if (bo->lock_count && (bo->locked_for & usage) != usage)
457                 return -EINVAL;
458
459         usage |= bo->locked_for;
460
461         if (usage & (GRALLOC_USAGE_SW_WRITE_MASK |
462                      GRALLOC_USAGE_SW_READ_MASK)) {
463                 /* the driver is supposed to wait for the bo */
464                 int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK);
465                 int err = gbm_map(bo, x, y, w, h, write, addr);
466                 if (err)
467                         return err;
468         }
469         else {
470                 /* kernel handles the synchronization here */
471         }
472
473         bo->lock_count++;
474         bo->locked_for |= usage;
475
476         return 0;
477 }
478
479 /*
480  * Unlock a bo.
481  */
482 void gralloc_gbm_bo_unlock(struct gralloc_gbm_bo_t *bo)
483 {
484         int mapped = bo->locked_for &
485                 (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
486
487         if (!bo->lock_count)
488                 return;
489
490         if (mapped)
491                 gbm_unmap(bo);
492
493         bo->lock_count--;
494         if (!bo->lock_count)
495                 bo->locked_for = 0;
496 }