1 /**************************************************************************
5 Copyright 2012 - 2016 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>,
8 Changyeon Lee <cyeon.lee@samsung.com>,
9 Boram Park <boram1288.park@samsung.com>,
10 Sangjin Lee <lsj119@samsung.com>
12 Permission is hereby granted, free of charge, to any person obtaining a
13 copy of this software and associated documentation files (the
14 "Software"), to deal in the Software without restriction, including
15 without limitation the rights to use, copy, modify, merge, publish,
16 distribute, sub license, and/or sell copies of the Software, and to
17 permit persons to whom the Software is furnished to do so, subject to
18 the following conditions:
20 The above copyright notice and this permission notice (including the
21 next paragraph) shall be included in all copies or substantial portions
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
27 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
28 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 **************************************************************************/
34 #include "tbm_bufmgr.h"
35 #include "tbm_bufmgr_int.h"
40 #include <sys/ioctl.h>
41 #include <linux/types.h>
43 #define SYNC_IOC_MAGIC '>'
44 #define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
45 #define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
46 #define SW_SYNC_IOC_MAGIC 'W'
47 #define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
48 struct sw_sync_create_fence_data)
49 #define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
51 #define SYNC_DEVICE_PATH "/dev/sw_sync"
53 struct _tbm_sync_timeline {
57 struct _tbm_sync_fence {
61 static pthread_mutex_t tbm_sync_lock;
62 static int tbm_sync_support = 0;
65 _tbm_sync_mutex_init(void)
67 static bool tbm_sync_mutex_init = false;
69 if (tbm_sync_mutex_init)
72 if (pthread_mutex_init(&tbm_sync_lock, NULL)) {
73 TBM_LOG_E("fail: tbm_sync mutex init\n");
77 tbm_sync_mutex_init = true;
83 _tbm_sync_mutex_lock(void)
85 if (!_tbm_sync_mutex_init())
88 pthread_mutex_lock(&tbm_sync_lock);
92 _tbm_sync_mutex_unlock(void)
94 pthread_mutex_unlock(&tbm_sync_lock);
97 static tbm_sync_error_e
98 _tbm_sync_check_capability(void)
100 #ifdef NOT_IMPELMENT_YET
101 tbm_bufmgr bufmgr = NULL;
102 unsigned int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
106 if (tbm_sync_support)
107 return TBM_SYNC_ERROR_NONE;
109 #ifdef NOT_IMPELMENT_YET
110 /* check the bufmgr */
111 bufmgr = _tbm_bufmgr_get_bufmgr();
113 return TBM_SYNC_ERROR_INVALID_OPERATION;
116 /* check the tbm_sync capability */
117 capabilities = tbm_bufmgr_get_capability(bufmgr);
119 if ((capabilities&TBM_BUFMGR_CAPABILITY_TBM_SYNC) != TBM_BUFMGR_CAPABILITY_TBM_SYNC) {
120 //TODO: check the sw_sync device node... to verify the timeline sync
121 tbm_sync_support = 1;
123 return TBM_SYNC_ERROR_INVALID_OPERATION;
127 if (stat(SYNC_DEVICE_PATH, &st_buf) == 0) {
128 tbm_sync_support = 1;
130 TBM_LOG_E("TBM_SYNC not supported\n");
131 return TBM_SYNC_ERROR_INVALID_OPERATION;
134 return TBM_SYNC_ERROR_NONE;
138 tbm_sync_timeline_create(tbm_sync_error_e *error)
140 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
141 tbm_sync_timeline_h timeline = NULL;
144 _tbm_sync_mutex_lock();
146 /* check the tbm_sync capability */
147 ret = _tbm_sync_check_capability();;
148 if (ret != TBM_SYNC_ERROR_NONE)
151 fd = open(SYNC_DEVICE_PATH, O_RDWR);
153 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
154 TBM_LOG_E("%s:%d(%s)\n", "TBM_SYNC open failed", errno, strerror(errno));
156 struct _tbm_sync_timeline *timeline_handle =
157 calloc(1, sizeof(struct _tbm_sync_timeline));
159 if (timeline_handle == NULL) {
160 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
161 TBM_LOG_E("%s\n", "TBM_SYNC calloc failed");
164 timeline_handle->fd = fd;
165 timeline = timeline_handle;
173 _tbm_sync_mutex_unlock();
179 tbm_sync_timeline_destroy(tbm_sync_timeline_h timeline)
181 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
183 _tbm_sync_mutex_lock();
185 /* check the tbm_sync capability */
186 ret = _tbm_sync_check_capability();;
187 if (ret != TBM_SYNC_ERROR_NONE)
191 struct _tbm_sync_timeline *timeline_handle = timeline;
193 if (timeline_handle->fd != -1)
194 close(timeline_handle->fd);
197 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
201 _tbm_sync_mutex_unlock();
207 tbm_sync_timeline_import(int fd, tbm_sync_error_e *error)
209 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
210 tbm_sync_timeline_h timeline = NULL;
213 _tbm_sync_mutex_lock();
215 /* check the tbm_sync capability */
216 ret = _tbm_sync_check_capability();;
217 if (ret != TBM_SYNC_ERROR_NONE)
221 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
227 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
228 TBM_LOG_E("%s:%d(%s)\n", "TBM_SYNC timeline dup failed",
229 errno, strerror(errno));
231 struct _tbm_sync_timeline *timeline_handle =
232 calloc(1, sizeof(struct _tbm_sync_timeline));
235 if ((fd_flag = fcntl(new_fd, F_GETFD, 0)) != -1) {
236 fd_flag |= FD_CLOEXEC;
237 fd_flag = fcntl(new_fd, F_SETFD, fd_flag);
239 TBM_LOG_W("%s\n", "TBM_SYNC fcntl failed");
242 if (timeline_handle == NULL) {
243 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
244 TBM_LOG_E("%s\n", "TBM_SYNC calloc failed");
247 timeline_handle->fd = new_fd;
248 timeline = timeline_handle;
256 _tbm_sync_mutex_unlock();
262 tbm_sync_timeline_export(tbm_sync_timeline_h timeline, tbm_sync_error_e *error)
264 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
267 _tbm_sync_mutex_lock();
269 /* check the tbm_sync capability */
270 ret = _tbm_sync_check_capability();;
271 if (ret != TBM_SYNC_ERROR_NONE)
275 struct _tbm_sync_timeline *timeline_handle = timeline;
278 fd = dup(timeline_handle->fd);
280 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
281 TBM_LOG_E("%s:%d(%s)\n", "TBM_SYNC timeline dup failed",
282 errno, strerror(errno));
284 if ((fd_flag = fcntl(fd, F_GETFD, 0)) != -1) {
285 fd_flag |= FD_CLOEXEC;
286 fd_flag = fcntl(fd, F_SETFD, fd_flag);
288 TBM_LOG_W("%s\n", "TBM_SYNC fcntl failed");
293 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
300 _tbm_sync_mutex_unlock();
306 tbm_sync_timeline_increase_count(tbm_sync_timeline_h timeline, unsigned int interval)
308 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
310 _tbm_sync_mutex_lock();
312 /* check the tbm_sync capability */
313 ret = _tbm_sync_check_capability();;
314 if (ret != TBM_SYNC_ERROR_NONE)
318 struct _tbm_sync_timeline *timeline_handle = timeline;
319 __u32 arg = interval;
321 if (ioctl(timeline_handle->fd, SW_SYNC_IOC_INC, &arg) == -1) {
322 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
323 TBM_LOG_E("%s:%d(%s)\n", "TBM_SYNC timeline inc failed", errno, strerror(errno));
326 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
330 _tbm_sync_mutex_unlock();
336 tbm_sync_timeline_get_cur_count(tbm_sync_timeline_h timeline, tbm_sync_error_e *error)
338 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
339 unsigned int cur_count = 0;
341 _tbm_sync_mutex_lock();
343 /* check the tbm_sync capability */
344 ret = _tbm_sync_check_capability();;
345 if (ret != TBM_SYNC_ERROR_NONE)
348 /* TODO: sync_timeline_get_cur_count */
354 _tbm_sync_mutex_unlock();
360 tbm_sync_fence_create(tbm_sync_timeline_h timeline, const char *name, unsigned int count_val, tbm_sync_error_e *error)
362 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
363 tbm_sync_fence_h fence = NULL;
365 _tbm_sync_mutex_lock();
367 /* check the tbm_sync capability */
368 ret = _tbm_sync_check_capability();;
369 if (ret != TBM_SYNC_ERROR_NONE)
373 struct _tbm_sync_timeline *timeline_handle = timeline;
374 struct sw_sync_create_fence_data {
380 data.value = count_val;
381 strncpy(data.name, name ? name : "", 32);
382 data.name[31] = '\0';
384 if (ioctl(timeline_handle->fd, SW_SYNC_IOC_CREATE_FENCE, &data) == -1) {
385 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
386 TBM_LOG_E("%s:%d(%s)\n", "TBM_SYNC create fence failed",
387 errno, strerror(errno));
389 struct _tbm_sync_fence *fence_handle =
390 calloc(1, sizeof(struct _tbm_sync_fence));
392 if (fence_handle == NULL) {
393 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
394 TBM_LOG_E("%s\n", "TBM_SYNC calloc failed");
397 fence_handle->fd = data.fence;
398 fence = fence_handle;
402 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
409 _tbm_sync_mutex_unlock();
415 tbm_sync_fence_destroy(tbm_sync_fence_h fence)
417 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
419 _tbm_sync_mutex_lock();
421 /* check the tbm_sync capability */
422 ret = _tbm_sync_check_capability();;
423 if (ret != TBM_SYNC_ERROR_NONE)
427 struct _tbm_sync_fence *fence_handle = fence;
429 if (fence_handle->fd != -1)
430 close(fence_handle->fd);
435 _tbm_sync_mutex_unlock();
441 tbm_sync_fence_wait(tbm_sync_fence_h fence, int timeout)
443 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
445 _tbm_sync_mutex_lock();
447 /* check the tbm_sync capability */
448 ret = _tbm_sync_check_capability();;
449 if (ret != TBM_SYNC_ERROR_NONE)
453 struct _tbm_sync_fence *fence_handle = fence;
456 if (ioctl(fence_handle->fd, SYNC_IOC_WAIT, &to) == -1) {
457 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
458 TBM_LOG_E("%s:%d(%s)\n", "TBM_SYNC fence wait failed", errno, strerror(errno));
461 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
465 _tbm_sync_mutex_unlock();
471 tbm_sync_fence_merge(tbm_sync_fence_h fence1, tbm_sync_fence_h fence2, const char *name, tbm_sync_error_e *error)
473 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
474 tbm_sync_fence_h fence = NULL;
476 _tbm_sync_mutex_lock();
478 /* check the tbm_sync capability */
479 ret = _tbm_sync_check_capability();;
480 if (ret != TBM_SYNC_ERROR_NONE)
483 if (fence1 && fence2) {
484 struct _tbm_sync_fence *fence_handle1 = fence1;
485 struct _tbm_sync_fence *fence_handle2 = fence2;
487 struct sync_merge_data {
493 data.fd2 = fence_handle2->fd;
494 strncpy(data.name, name ? name : "", 32);
495 data.name[31] = '\0';
497 if (ioctl(fence_handle1->fd, SYNC_IOC_MERGE, &data) == -1) {
498 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
499 TBM_LOG_E("%s:%d(%s)\n", "TBM_SYNC fence merge failed",
500 errno, strerror(errno));
502 struct _tbm_sync_fence *fence_handle =
503 calloc(1, sizeof(struct _tbm_sync_fence));
505 if (fence_handle == NULL) {
506 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
507 TBM_LOG_E("%s\n", "TBM_SYNC calloc failed");
510 fence_handle->fd = data.fence;
514 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
521 _tbm_sync_mutex_unlock();
527 tbm_sync_fence_get_count_val(tbm_sync_fence_h fence, tbm_sync_error_e *error)
529 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
530 unsigned int count_val = 0;
532 _tbm_sync_mutex_lock();
534 /* check the tbm_sync capability */
535 ret = _tbm_sync_check_capability();;
536 if (ret != TBM_SYNC_ERROR_NONE)
539 /* TODO: sync_fence_get_count_val */
545 _tbm_sync_mutex_unlock();
551 tbm_sync_fence_import(int fd, tbm_sync_error_e *error)
553 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
554 tbm_sync_fence_h fence = NULL;
557 _tbm_sync_mutex_lock();
559 /* check the tbm_sync capability */
560 ret = _tbm_sync_check_capability();;
561 if (ret != TBM_SYNC_ERROR_NONE)
565 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
571 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
572 TBM_LOG_E("%s:%d(%s)\n", "TBM_SYNC fence dup failed",
573 errno, strerror(errno));
575 struct _tbm_sync_fence *fence_handle =
576 calloc(1, sizeof(struct _tbm_sync_fence));
579 if ((fd_flag = fcntl(new_fd, F_GETFD, 0)) != -1) {
580 fd_flag |= FD_CLOEXEC;
581 fd_flag = fcntl(new_fd, F_SETFD, fd_flag);
583 TBM_LOG_W("%s\n", "TBM_SYNC fcntl failed");
586 if (fence_handle == NULL) {
587 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
588 TBM_LOG_E("%s\n", "TBM_SYNC calloc failed");
591 fence_handle->fd = new_fd;
592 fence = fence_handle;
600 _tbm_sync_mutex_unlock();
606 tbm_sync_fence_export(tbm_sync_fence_h fence, tbm_sync_error_e *error)
608 tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
611 _tbm_sync_mutex_lock();
613 /* check the tbm_sync capability */
614 ret = _tbm_sync_check_capability();;
615 if (ret != TBM_SYNC_ERROR_NONE)
619 struct _tbm_sync_fence *fence_handle = fence;
622 fd = dup(fence_handle->fd);
624 ret = TBM_SYNC_ERROR_INVALID_OPERATION;
625 TBM_LOG_E("%s:%d(%s)\n", "TBM_SYNC fence dup failed",
626 errno, strerror(errno));
628 if ((fd_flag = fcntl(fd, F_GETFD, 0)) != -1) {
629 fd_flag |= FD_CLOEXEC;
630 fd_flag = fcntl(fd, F_SETFD, fd_flag);
632 TBM_LOG_W("%s\n", "TBM_SYNC fcntl failed");
637 ret = TBM_SYNC_ERROR_INVALID_PARAMETER;
644 _tbm_sync_mutex_unlock();