1 /**************************************************************************
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 #include "tbm_bufmgr.h"
35 #include "tbm_bufmgr_int.h"
36 #include "tbm_bufmgr_backend.h"
54 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
55 static pthread_mutex_t tbm_bufmgr_lock = PTHREAD_MUTEX_INITIALIZER;
56 static __thread tbm_error_e tbm_last_error = TBM_ERROR_NONE;
58 static void _tbm_bufmgr_mutex_unlock(void);
60 //#define TBM_BUFMGR_INIT_TIME
62 #define PREFIX_LIB "libtbm_"
63 #define SUFFIX_LIB ".so"
64 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
66 /* values to indicate unspecified fields in XF86ModReqInfo. */
67 #define MAJOR_UNSPEC 0xFF
68 #define MINOR_UNSPEC 0xFF
69 #define PATCH_UNSPEC 0xFFFF
70 #define ABI_VERS_UNSPEC 0xFFFFFFFF
72 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
73 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
74 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
75 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
76 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
79 #define TBM_BUFMGR_RETURN_IF_FAIL(cond) {\
81 TBM_LOG_E("'%s' failed.\n", #cond);\
82 _tbm_bufmgr_mutex_unlock();\
87 #define TBM_BUFMGR_RETURN_VAL_IF_FAIL(cond, val) {\
89 TBM_LOG_E("'%s' failed.\n", #cond);\
90 _tbm_bufmgr_mutex_unlock();\
102 _tbm_set_last_result(tbm_error_e err)
104 tbm_last_error = err;
108 _tbm_bufmgr_mutex_init(void)
110 static bool tbm_bufmgr_mutex_init = false;
112 if (tbm_bufmgr_mutex_init)
115 if (pthread_mutex_init(&tbm_bufmgr_lock, NULL)) {
116 TBM_LOG_E("fail: tbm_bufmgr mutex init\n");
120 tbm_bufmgr_mutex_init = true;
126 _tbm_bufmgr_mutex_lock(void)
128 if (!_tbm_bufmgr_mutex_init())
131 pthread_mutex_lock(&tbm_bufmgr_lock);
135 _tbm_bufmgr_mutex_unlock(void)
137 pthread_mutex_unlock(&tbm_bufmgr_lock);
141 _tbm_flag_to_str(int f)
143 static char str[255];
145 if (f == TBM_BO_DEFAULT)
146 snprintf(str, 255, "DEFAULT");
150 if (f & TBM_BO_SCANOUT)
151 c = snprintf(&str[c], 255, "SCANOUT");
153 if (f & TBM_BO_NONCACHABLE) {
155 c = snprintf(&str[c], 255, ", ");
156 c = snprintf(&str[c], 255, "NONCACHABLE,");
161 c = snprintf(&str[c], 255, ", ");
162 c = snprintf(&str[c], 255, "WC");
169 /* LCOV_EXCL_START */
171 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
173 static int last_chk_bo_cnt = 0;
175 if ((bufmgr->bo_cnt >= 500) && ((bufmgr->bo_cnt % 20) == 0) &&
176 (bufmgr->bo_cnt > last_chk_bo_cnt)) {
177 TBM_DEBUG("============TBM BO CNT DEBUG: bo_cnt=%d\n",
180 tbm_bufmgr_debug_show(bufmgr);
182 last_chk_bo_cnt = bufmgr->bo_cnt;
187 _tbm_util_get_max_surface_size(int *w, int *h)
189 tbm_surface_info_s info;
190 tbm_surface_h surface = NULL;
196 if (gBufMgr == NULL || !LIST_IS_EMPTY(&gBufMgr->surf_list))
199 LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link) {
200 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
204 if (*h < info.height)
213 _tbm_util_get_appname_brief(char *brief)
217 char temp[255] = {0,};
218 char *saveptr = NULL;
220 token = strtok_r(brief, delim, &saveptr);
222 while (token != NULL) {
223 memset(temp, 0x00, 255 * sizeof(char));
224 strncpy(temp, token, 254 * sizeof(char));
225 token = strtok_r(NULL, delim, &saveptr);
228 snprintf(brief, sizeof(temp), "%s", temp);
232 _tbm_util_get_appname_from_pid(long pid, char *str)
234 char fn_cmdline[255] = {0, }, cmdline[255];
238 snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", pid);
240 fp = fopen(fn_cmdline, "r");
242 fprintf(stderr, "cannot file open %s\n", fn_cmdline);
246 if (!fgets(cmdline, 255, fp)) {
247 fprintf(stderr, "fail to get appname for pid(%ld)\n", pid);
254 len = strlen(cmdline);
256 memset(cmdline, 0x00, 255);
260 snprintf(str, sizeof(cmdline), "%s", cmdline);
265 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
267 tbm_user_data *old_data = NULL;
269 if (LIST_IS_EMPTY(user_data_list))
272 LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
273 if (old_data->key == key)
281 *user_data_create(unsigned long key, tbm_data_free data_free_func)
283 tbm_user_data *user_data;
285 user_data = calloc(1, sizeof(tbm_user_data));
289 user_data->key = key;
290 user_data->free_func = data_free_func;
296 user_data_delete(tbm_user_data *user_data)
298 if (user_data->data && user_data->free_func)
299 user_data->free_func(user_data->data);
301 LIST_DEL(&user_data->item_link);
307 _bo_lock(tbm_bo bo, int device, int opt)
309 tbm_bufmgr bufmgr = bo->bufmgr;
312 if (bufmgr->backend->bo_lock)
313 ret = bufmgr->backend->bo_lock(bo, device, opt);
319 _bo_unlock(tbm_bo bo)
321 tbm_bufmgr bufmgr = bo->bufmgr;
323 if (bufmgr->backend->bo_unlock)
324 bufmgr->backend->bo_unlock(bo);
328 _tbm_bo_lock(tbm_bo bo, int device, int opt)
338 /* do not try to lock the bo */
339 if (bufmgr->lock_type == LOCK_TRY_NEVER)
342 if (bo->lock_cnt < 0) {
343 TBM_LOG_E("error bo:%p LOCK_CNT=%d\n",
350 switch (bufmgr->lock_type) {
352 if (bo->lock_cnt == 0) {
353 _tbm_bufmgr_mutex_unlock();
354 ret = _bo_lock(bo, device, opt);
355 _tbm_bufmgr_mutex_lock();
361 case LOCK_TRY_ALWAYS:
362 _tbm_bufmgr_mutex_unlock();
363 ret = _bo_lock(bo, device, opt);
364 _tbm_bufmgr_mutex_lock();
369 TBM_LOG_E("error bo:%p lock_type[%d] is wrong.\n",
370 bo, bufmgr->lock_type);
375 TBM_DBG_LOCK(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
381 _tbm_bo_unlock(tbm_bo bo)
391 /* do not try to unlock the bo */
392 if (bufmgr->lock_type == LOCK_TRY_NEVER)
397 switch (bufmgr->lock_type) {
399 if (bo->lock_cnt > 0) {
401 if (bo->lock_cnt == 0)
405 case LOCK_TRY_ALWAYS:
406 if (bo->lock_cnt > 0) {
412 TBM_LOG_E("error bo:%p lock_type[%d] is wrong.\n",
413 bo, bufmgr->lock_type);
417 if (bo->lock_cnt < 0)
420 TBM_DBG_LOCK(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
424 _tbm_bo_is_valid(tbm_bo bo)
428 if (bo == NULL || gBufMgr == NULL) {
429 TBM_LOG_E("error: bo is NULL or tbm_bufmgr was deinited\n");
433 if (LIST_IS_EMPTY(&gBufMgr->bo_list))
436 LIST_FOR_EACH_ENTRY(old_data, &gBufMgr->bo_list, item_link) {
444 /* LCOV_EXCL_START */
446 _check_version(TBMModuleVersionInfo *data)
451 abimaj = GET_ABI_MAJOR(data->abiversion);
452 abimin = GET_ABI_MINOR(data->abiversion);
454 TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
455 data->modname ? data->modname : "UNKNOWN!",
456 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
458 vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
459 vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
461 TBM_DBG("TBM ABI version %d.%d\n",
464 if (abimaj != vermaj) {
465 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
468 } else if (abimin > vermin) {
469 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
478 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
480 char path[PATH_MAX] = {0, };
481 TBMModuleVersionInfo *vers;
482 TBMModuleData *initdata;
486 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
488 module_data = dlopen(path, RTLD_LAZY);
490 TBM_LOG_E("failed to load module: %s(%s)\n", dlerror(), file);
494 initdata = dlsym(module_data, "tbmModuleData");
496 TBM_LOG_E("Error: module does not have data object.\n");
500 vers = initdata->vers;
502 TBM_LOG_E("Error: module does not supply version information.\n");
506 init = initdata->init;
508 TBM_LOG_E("Error: module does not supply init symbol.\n");
512 if (!_check_version(vers)) {
513 TBM_LOG_E("Fail to check version.\n");
517 if (!init(bufmgr, fd)) {
518 TBM_LOG_E("Fail to init module(%s)\n", file);
522 if (!bufmgr->backend || !bufmgr->backend->priv) {
523 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n", file);
527 bufmgr->module_data = module_data;
529 TBM_DBG("Success to load module(%s)\n", file);
534 dlclose(module_data);
539 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
541 struct dirent **namelist;
544 /* load bufmgr priv from default lib */
545 if (_tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB))
548 /* load bufmgr priv from configured path */
549 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
551 TBM_LOG_E("no files : %s\n", BUFMGR_MODULE_DIR);
556 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
557 const char *p = strstr(namelist[n]->d_name, SUFFIX_LIB);
559 if (p && !strcmp(p, SUFFIX_LIB))
560 ret = _tbm_bufmgr_load_module(bufmgr, fd,
561 namelist[n]->d_name);
574 tbm_bufmgr_init(int fd)
578 #ifdef TBM_BUFMGR_INIT_TIME
579 struct timeval start_tv, end_tv;
582 pthread_mutex_lock(&gLock);
584 #ifdef TBM_BUFMGR_INIT_TIME
585 /* get the start tv */
586 gettimeofday(&start_tv, NULL);
589 /* LCOV_EXCL_START */
591 env = getenv("TBM_DLOG");
594 TBM_LOG_D("TBM_DLOG=%s\n", env);
601 env = getenv("TBM_DEBUG");
604 TBM_LOG_D("TBM_DEBUG=%s\n", env);
611 env = getenv("TBM_TRACE");
614 TBM_LOG_D("TBM_TRACE=%s\n", env);
621 /* initialize buffer manager */
623 gBufMgr->ref_count++;
624 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
625 pthread_mutex_unlock(&gLock);
629 TBM_DBG("bufmgr init\n");
631 /* allocate bufmgr */
632 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
634 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
635 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
636 pthread_mutex_unlock(&gLock);
642 /* load bufmgr priv from env */
643 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
644 /* LCOV_EXCL_START */
645 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
646 TBM_LOG_E("error : Fail to load bufmgr backend\n");
649 pthread_mutex_unlock(&gLock);
654 /* log for tbm backend_flag */
655 TBM_DBG("backend flag:%x:", gBufMgr->backend->flags);
658 gBufMgr->ref_count = 1;
660 TBM_DBG("create tizen bufmgr:%p ref_count:%d\n",
661 gBufMgr, gBufMgr->ref_count);
663 /* setup the lock_type */
664 env = getenv("BUFMGR_LOCK_TYPE");
665 if (env && !strcmp(env, "always"))
666 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
667 else if (env && !strcmp(env, "none"))
668 gBufMgr->lock_type = LOCK_TRY_NEVER;
669 else if (env && !strcmp(env, "once"))
670 gBufMgr->lock_type = LOCK_TRY_ONCE;
672 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
674 TBM_DBG("BUFMGR_LOCK_TYPE=%s\n",
675 env ? env : "default:once");
677 TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
679 /* intialize bo_list */
680 LIST_INITHEAD(&gBufMgr->bo_list);
682 /* intialize surf_list */
683 LIST_INITHEAD(&gBufMgr->surf_list);
685 /* intialize surf_list */
686 LIST_INITHEAD(&gBufMgr->surf_queue_list);
688 /* intialize debug_key_list */
689 LIST_INITHEAD(&gBufMgr->debug_key_list);
691 #ifdef TBM_BUFMGR_INIT_TIME
693 gettimeofday(&end_tv, NULL);
694 TBM_LOG_I("tbm_bufmgr_init time: %ld ms", ((end_tv.tv_sec * 1000 + end_tv.tv_usec / 1000) - (start_tv.tv_sec * 1000 + start_tv.tv_usec / 1000)));
697 pthread_mutex_unlock(&gLock);
703 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
705 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
710 tbm_surface_h surf = NULL;
711 tbm_surface_h tmp_surf = NULL;
713 pthread_mutex_lock(&gLock);
716 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
717 pthread_mutex_unlock(&gLock);
722 if (bufmgr->ref_count > 0) {
723 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
724 pthread_mutex_unlock(&gLock);
728 /* destroy bo_list */
729 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
730 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
731 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
738 /* destroy surf_list */
739 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
740 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
741 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
743 tbm_surface_destroy(surf);
747 /* destroy bufmgr priv */
748 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
749 bufmgr->backend->priv = NULL;
750 tbm_backend_free(bufmgr->backend);
751 bufmgr->backend = NULL;
753 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
755 dlclose(bufmgr->module_data);
764 pthread_mutex_unlock(&gLock);
768 tbm_bo_size(tbm_bo bo)
770 tbm_bufmgr bufmgr = NULL;
773 _tbm_bufmgr_mutex_lock();
775 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
776 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
780 size = bufmgr->backend->bo_size(bo);
782 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
784 _tbm_bufmgr_mutex_unlock();
790 tbm_bo_ref(tbm_bo bo)
792 _tbm_bufmgr_mutex_lock();
794 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
795 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
799 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
801 _tbm_bufmgr_mutex_unlock();
807 tbm_bo_unref(tbm_bo bo)
809 tbm_bufmgr bufmgr = NULL;
810 tbm_user_data *old_data = NULL, *tmp = NULL;
812 _tbm_bufmgr_mutex_lock();
814 TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
815 TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
819 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
821 if (bo->ref_cnt <= 0) {
822 _tbm_bufmgr_mutex_unlock();
827 if (bo->ref_cnt == 0) {
828 /* destory the user_data_list */
829 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
830 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
831 TBM_DBG("free user_data\n");
832 user_data_delete(old_data);
836 while (bo->lock_cnt > 0) {
837 TBM_LOG_E("error lock_cnt:%d\n",
843 /* call the bo_free */
844 bufmgr->backend->bo_free(bo);
847 LIST_DEL(&bo->item_link);
853 _tbm_bufmgr_mutex_unlock();
857 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
860 void *bo_priv = NULL;
862 _tbm_bufmgr_mutex_lock();
864 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
865 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
866 TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
868 bo = calloc(1, sizeof(struct _tbm_bo));
870 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n",
871 size, _tbm_flag_to_str(flags));
872 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
873 _tbm_bufmgr_mutex_unlock();
877 _tbm_util_check_bo_cnt(bufmgr);
882 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
884 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n",
885 size, _tbm_flag_to_str(flags));
886 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
888 _tbm_bufmgr_mutex_unlock();
896 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
897 _tbm_flag_to_str(bo->flags));
899 LIST_INITHEAD(&bo->user_data_list);
901 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
903 _tbm_bufmgr_mutex_unlock();
909 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
914 void *bo_priv = NULL;
916 _tbm_bufmgr_mutex_lock();
918 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
919 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
921 if (!bufmgr->backend->bo_import) {
922 _tbm_bufmgr_mutex_unlock();
926 _tbm_util_check_bo_cnt(bufmgr);
928 bo = calloc(1, sizeof(struct _tbm_bo));
930 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
931 _tbm_bufmgr_mutex_unlock();
937 bo_priv = bufmgr->backend->bo_import(bo, key);
939 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
940 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
942 _tbm_bufmgr_mutex_unlock();
946 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
947 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
948 if (bo2->priv == bo_priv) {
949 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
950 bo2, bo2->ref_cnt, key,
951 _tbm_flag_to_str(bo2->flags));
954 _tbm_bufmgr_mutex_unlock();
965 if (bufmgr->backend->bo_get_flags)
966 bo->flags = bufmgr->backend->bo_get_flags(bo);
968 bo->flags = TBM_BO_DEFAULT;
970 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
971 bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
973 LIST_INITHEAD(&bo->user_data_list);
975 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
977 _tbm_bufmgr_mutex_unlock();
983 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
988 void *bo_priv = NULL;
990 _tbm_bufmgr_mutex_lock();
992 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
993 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
995 if (!bufmgr->backend->bo_import_fd) {
996 _tbm_bufmgr_mutex_unlock();
1000 _tbm_util_check_bo_cnt(bufmgr);
1002 bo = calloc(1, sizeof(struct _tbm_bo));
1004 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1005 _tbm_bufmgr_mutex_unlock();
1009 bo->bufmgr = bufmgr;
1011 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1013 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1014 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
1016 _tbm_bufmgr_mutex_unlock();
1020 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1021 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
1022 if (bo2->priv == bo_priv) {
1023 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1024 bo2, bo2->ref_cnt, fd,
1025 _tbm_flag_to_str(bo2->flags));
1028 _tbm_bufmgr_mutex_unlock();
1039 if (bufmgr->backend->bo_get_flags)
1040 bo->flags = bufmgr->backend->bo_get_flags(bo);
1042 bo->flags = TBM_BO_DEFAULT;
1044 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1045 bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1047 LIST_INITHEAD(&bo->user_data_list);
1049 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1051 _tbm_bufmgr_mutex_unlock();
1057 tbm_bo_export(tbm_bo bo)
1059 tbm_bufmgr bufmgr = NULL;
1062 _tbm_bufmgr_mutex_lock();
1064 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1065 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1069 if (!bufmgr->backend->bo_export) {
1070 _tbm_bufmgr_mutex_unlock();
1074 ret = bufmgr->backend->bo_export(bo);
1076 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1077 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1078 _tbm_bufmgr_mutex_unlock();
1082 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
1084 _tbm_bufmgr_mutex_unlock();
1090 tbm_bo_export_fd(tbm_bo bo)
1092 tbm_bufmgr bufmgr = NULL;
1095 _tbm_bufmgr_mutex_lock();
1097 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), -1);
1098 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1102 if (!bufmgr->backend->bo_export_fd) {
1103 _tbm_bufmgr_mutex_unlock();
1107 ret = bufmgr->backend->bo_export_fd(bo);
1109 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1110 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1111 _tbm_bufmgr_mutex_unlock();
1115 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1117 _tbm_bufmgr_mutex_unlock();
1123 tbm_bo_get_handle(tbm_bo bo, int device)
1125 tbm_bufmgr bufmgr = NULL;
1126 tbm_bo_handle bo_handle;
1128 _tbm_bufmgr_mutex_lock();
1130 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1131 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1135 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1136 if (bo_handle.ptr == NULL) {
1137 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1138 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1139 _tbm_bufmgr_mutex_unlock();
1140 return (tbm_bo_handle) NULL;
1143 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1145 _tbm_bufmgr_mutex_unlock();
1151 tbm_bo_map(tbm_bo bo, int device, int opt)
1153 tbm_bufmgr bufmgr = NULL;
1154 tbm_bo_handle bo_handle;
1156 _tbm_bufmgr_mutex_lock();
1158 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1159 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1163 if (!_tbm_bo_lock(bo, device, opt)) {
1164 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1165 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1166 _tbm_bufmgr_mutex_unlock();
1167 return (tbm_bo_handle) NULL;
1170 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1171 if (bo_handle.ptr == NULL) {
1172 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1173 TBM_TRACE("error: fail to map bo:%p\n", bo);
1175 _tbm_bufmgr_mutex_unlock();
1176 return (tbm_bo_handle) NULL;
1179 /* increase the map_count */
1182 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1184 _tbm_bufmgr_mutex_unlock();
1190 tbm_bo_unmap(tbm_bo bo)
1192 tbm_bufmgr bufmgr = NULL;
1195 _tbm_bufmgr_mutex_lock();
1197 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1198 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1202 ret = bufmgr->backend->bo_unmap(bo);
1204 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1205 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1206 _tbm_bufmgr_mutex_unlock();
1210 /* decrease the map_count */
1213 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1217 _tbm_bufmgr_mutex_unlock();
1223 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1225 tbm_bufmgr bufmgr = NULL;
1228 _tbm_bufmgr_mutex_lock();
1230 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1231 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1232 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1236 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1238 if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1239 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1240 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1241 _tbm_bufmgr_mutex_unlock();
1245 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1248 bo1->priv = bo2->priv;
1251 _tbm_bufmgr_mutex_unlock();
1257 tbm_bo_locked(tbm_bo bo)
1259 tbm_bufmgr bufmgr = NULL;
1261 _tbm_bufmgr_mutex_lock();
1263 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1264 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1268 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1269 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1270 _tbm_bufmgr_mutex_unlock();
1274 if (bo->lock_cnt > 0) {
1275 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1276 _tbm_bufmgr_mutex_unlock();
1280 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1281 _tbm_bufmgr_mutex_unlock();
1287 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1288 tbm_data_free data_free_func)
1290 tbm_user_data *data;
1292 _tbm_bufmgr_mutex_lock();
1294 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1295 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1297 /* check if the data according to the key exist if so, return false. */
1298 data = user_data_lookup(&bo->user_data_list, key);
1300 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1301 _tbm_bufmgr_mutex_unlock();
1305 data = user_data_create(key, data_free_func);
1307 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1308 _tbm_bufmgr_mutex_unlock();
1312 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1314 LIST_ADD(&data->item_link, &bo->user_data_list);
1316 _tbm_bufmgr_mutex_unlock();
1322 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1324 tbm_user_data *old_data;
1326 _tbm_bufmgr_mutex_lock();
1328 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1329 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1331 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1332 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1333 _tbm_bufmgr_mutex_unlock();
1337 old_data = user_data_lookup(&bo->user_data_list, key);
1339 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1340 _tbm_bufmgr_mutex_unlock();
1344 if (old_data->data && old_data->free_func)
1345 old_data->free_func(old_data->data);
1347 old_data->data = data;
1349 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1351 _tbm_bufmgr_mutex_unlock();
1357 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1359 tbm_user_data *old_data;
1361 _tbm_bufmgr_mutex_lock();
1363 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1364 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1366 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1367 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1368 _tbm_bufmgr_mutex_unlock();
1372 old_data = user_data_lookup(&bo->user_data_list, key);
1374 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1376 _tbm_bufmgr_mutex_unlock();
1380 *data = old_data->data;
1382 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1384 _tbm_bufmgr_mutex_unlock();
1390 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1392 tbm_user_data *old_data = (void *)0;
1394 _tbm_bufmgr_mutex_lock();
1396 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1397 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1399 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1400 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1401 _tbm_bufmgr_mutex_unlock();
1405 old_data = user_data_lookup(&bo->user_data_list, key);
1407 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1408 _tbm_bufmgr_mutex_unlock();
1412 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1414 user_data_delete(old_data);
1416 _tbm_bufmgr_mutex_unlock();
1422 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1424 int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1426 _tbm_bufmgr_mutex_lock();
1428 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1429 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1431 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1433 capabilities = bufmgr->capabilities;
1435 _tbm_bufmgr_mutex_unlock();
1437 return capabilities;
1441 tbm_bo_get_flags(tbm_bo bo)
1445 _tbm_bufmgr_mutex_lock();
1447 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1448 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1452 TBM_TRACE("bo(%p)\n", bo);
1454 _tbm_bufmgr_mutex_unlock();
1459 /* LCOV_EXCL_START */
1461 tbm_get_last_error(void)
1463 return tbm_last_error;
1467 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1469 tbm_bo bo = NULL, tmp_bo = NULL;
1471 tbm_surface_h surf = NULL, tmp_surf = NULL;
1474 char app_name[255] = {0,};
1475 unsigned int pid = 0;
1476 char title[255] = {0,};
1477 char data[255] = {0,};
1478 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1480 pthread_mutex_lock(&gLock);
1482 if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
1483 TBM_LOG_E("invalid bufmgr\n");
1484 pthread_mutex_unlock(&gLock);
1489 _tbm_util_get_appname_from_pid(getpid(), app_name);
1490 _tbm_util_get_appname_brief(app_name);
1491 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1492 app_name, getpid());
1493 memset(app_name, 0x0, 255 * sizeof(char));
1494 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1495 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1496 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1497 strncat(title, " ", 3);
1498 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1502 TBM_DEBUG("[tbm_surface information]\n");
1503 TBM_DEBUG("%s\n", title);
1504 /* show the tbm_surface information in surf_list */
1505 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1508 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1509 pid = _tbm_surface_internal_get_debug_pid(surf);
1511 /* if pid is null, set the self_pid */
1515 _tbm_util_get_appname_from_pid(pid, app_name);
1516 _tbm_util_get_appname_brief(app_name);
1518 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1525 surf->info.size / 1024,
1529 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1532 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1533 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1534 strncat(data, " ", 3);
1536 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1538 strncat(data, value, strlen(value) + 1);
1540 strncat(data, "none", 5);
1543 TBM_DEBUG("%s\n", data);
1545 for (i = 0; i < surf->num_bos; i++) {
1546 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1548 surf->bos[i]->ref_cnt,
1549 bufmgr->backend->bo_size(surf->bos[i]) / 1024);
1552 memset(app_name, 0x0, 255 * sizeof(char));
1555 TBM_DEBUG("no tbm_surfaces.\n");
1559 TBM_DEBUG("[tbm_bo information]\n");
1560 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1562 /* show the tbm_bo information in bo_list */
1563 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1564 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1565 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1569 bufmgr->backend->bo_size(bo) / 1024,
1576 TBM_DEBUG("no tbm_bos.\n");
1580 TBM_DEBUG("===============================================================\n");
1582 pthread_mutex_unlock(&gLock);
1586 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1588 _tbm_bufmgr_mutex_lock();
1590 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1591 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1594 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1598 _tbm_bufmgr_mutex_unlock();
1602 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1606 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1607 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1609 pthread_mutex_lock(&gLock);
1612 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1613 TBM_LOG_I("No tbm_surface.\n");
1614 pthread_mutex_unlock(&gLock);
1618 tbm_surface_internal_dump_start(path, w, h, count);
1620 } else if (onoff == 0) {
1621 tbm_surface_internal_dump_end();
1624 pthread_mutex_unlock(&gLock);
1628 pthread_mutex_unlock(&gLock);
1633 tbm_bufmgr_debug_dump_all(char *path)
1635 int w = 0, h = 0, count = 0;
1636 tbm_surface_h surface = NULL, tmp = NULL;
1638 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1639 TBM_LOG_D("path=%s\n", path);
1641 pthread_mutex_lock(&gLock);
1643 count = _tbm_util_get_max_surface_size(&w, &h);
1645 TBM_LOG_I("No tbm_surface.\n");
1646 pthread_mutex_unlock(&gLock);
1650 tbm_surface_internal_dump_start(path, w, h, count);
1652 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1653 tbm_surface_internal_dump_buffer(surface, "dump_all");
1656 tbm_surface_internal_dump_end();
1658 pthread_mutex_unlock(&gLock);
1663 /* internal function */
1665 _tbm_bufmgr_get_bufmgr(void)
1671 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1673 _tbm_bufmgr_mutex_lock();
1675 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1676 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1678 bo->surface = surface;
1680 _tbm_bufmgr_mutex_unlock();
1686 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1690 _tbm_bufmgr_mutex_lock();
1692 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1694 if (!bufmgr->backend->bufmgr_bind_native_display) {
1695 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1696 _tbm_bufmgr_mutex_unlock();
1700 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1702 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1703 _tbm_bufmgr_mutex_unlock();
1707 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1709 _tbm_bufmgr_mutex_unlock();
1713 /* LCOV_EXCL_STOP */