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)
426 tbm_bo old_data = NULL;
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)
576 #ifdef TBM_BUFMGR_INIT_TIME
577 struct timeval start_tv, end_tv;
581 #ifdef TBM_BUFMGR_INIT_TIME
582 /* get the start tv */
583 gettimeofday(&start_tv, NULL);
586 /* LCOV_EXCL_START */
588 env = getenv("TBM_DLOG");
591 TBM_LOG_D("TBM_DLOG=%s\n", env);
597 env = getenv("TBM_DEBUG");
600 TBM_LOG_D("TBM_DEBUG=%s\n", env);
606 env = getenv("TBM_TRACE");
609 TBM_LOG_D("TBM_TRACE=%s\n", env);
615 pthread_mutex_lock(&gLock);
618 TBM_LOG_W("!!!!!WARNING:: The tbm_bufmgr_init DOSE NOT use argument fd ANYMORE.\n");
619 TBM_LOG_W("!!!!!WARNING:: IT WILL BE CHANGED like tbm_bufmgr_init(int fd) --> tbm_bufmgr_init(void).\n");
622 /* initialize buffer manager */
624 gBufMgr->ref_count++;
625 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
626 pthread_mutex_unlock(&gLock);
630 TBM_DBG("bufmgr init\n");
632 /* allocate bufmgr */
633 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
635 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
636 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
637 pthread_mutex_unlock(&gLock);
643 /* load bufmgr priv from env */
644 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
645 /* LCOV_EXCL_START */
646 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
647 TBM_LOG_E("error : Fail to load bufmgr backend\n");
650 pthread_mutex_unlock(&gLock);
655 /* log for tbm backend_flag */
656 TBM_DBG("backend flag:%x:", gBufMgr->backend->flags);
659 gBufMgr->ref_count = 1;
661 TBM_DBG("create tizen bufmgr:%p ref_count:%d\n",
662 gBufMgr, gBufMgr->ref_count);
664 /* setup the lock_type */
665 env = getenv("BUFMGR_LOCK_TYPE");
666 if (env && !strcmp(env, "always"))
667 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
668 else if (env && !strcmp(env, "none"))
669 gBufMgr->lock_type = LOCK_TRY_NEVER;
670 else if (env && !strcmp(env, "once"))
671 gBufMgr->lock_type = LOCK_TRY_ONCE;
673 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
675 TBM_DBG("BUFMGR_LOCK_TYPE=%s\n", 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_queue_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));
707 pthread_mutex_lock(&gLock);
710 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
711 pthread_mutex_unlock(&gLock);
716 if (bufmgr->ref_count > 0) {
717 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
718 pthread_mutex_unlock(&gLock);
722 /* destroy bo_list */
723 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
724 tbm_bo bo = NULL, tmp;
726 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
727 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n", bo, bo->ref_cnt);
733 /* destroy surf_list */
734 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
735 tbm_surface_h surf = NULL, tmp;
737 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &bufmgr->surf_list, item_link) {
738 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n", surf, surf->refcnt);
739 tbm_surface_destroy(surf);
743 /* destroy bufmgr priv */
744 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
745 bufmgr->backend->priv = NULL;
746 tbm_backend_free(bufmgr->backend);
747 bufmgr->backend = NULL;
749 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
751 dlclose(bufmgr->module_data);
759 pthread_mutex_unlock(&gLock);
763 tbm_bo_size(tbm_bo bo)
765 tbm_bufmgr bufmgr = gBufMgr;
768 _tbm_bufmgr_mutex_lock();
770 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
771 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
773 size = bufmgr->backend->bo_size(bo);
775 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
777 _tbm_bufmgr_mutex_unlock();
783 tbm_bo_ref(tbm_bo bo)
785 _tbm_bufmgr_mutex_lock();
787 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
788 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
792 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
794 _tbm_bufmgr_mutex_unlock();
800 tbm_bo_unref(tbm_bo bo)
802 tbm_bufmgr bufmgr = gBufMgr;
804 _tbm_bufmgr_mutex_lock();
806 TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
807 TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
809 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
811 if (bo->ref_cnt <= 0) {
812 _tbm_bufmgr_mutex_unlock();
817 if (bo->ref_cnt == 0) {
818 /* destory the user_data_list */
819 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
820 tbm_user_data *old_data = NULL, *tmp;
822 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
823 &bo->user_data_list, item_link) {
824 TBM_DBG("free user_data\n");
825 user_data_delete(old_data);
829 while (bo->lock_cnt > 0) {
830 TBM_LOG_E("error lock_cnt:%d\n", bo->lock_cnt);
835 /* call the bo_free */
836 bufmgr->backend->bo_free(bo);
839 LIST_DEL(&bo->item_link);
845 _tbm_bufmgr_mutex_unlock();
849 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
854 _tbm_bufmgr_mutex_lock();
856 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
857 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
858 TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
860 bo = calloc(1, sizeof(struct _tbm_bo));
862 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n",
863 size, _tbm_flag_to_str(flags));
864 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
865 _tbm_bufmgr_mutex_unlock();
869 _tbm_util_check_bo_cnt(bufmgr);
873 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
875 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n",
876 size, _tbm_flag_to_str(flags));
877 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
879 _tbm_bufmgr_mutex_unlock();
889 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
890 _tbm_flag_to_str(bo->flags));
892 LIST_INITHEAD(&bo->user_data_list);
894 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
896 _tbm_bufmgr_mutex_unlock();
902 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
907 _tbm_bufmgr_mutex_lock();
909 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
910 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
912 if (!bufmgr->backend->bo_import) {
913 _tbm_bufmgr_mutex_unlock();
917 _tbm_util_check_bo_cnt(bufmgr);
919 bo = calloc(1, sizeof(struct _tbm_bo));
921 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
922 _tbm_bufmgr_mutex_unlock();
928 bo_priv = bufmgr->backend->bo_import(bo, key);
930 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
931 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
933 _tbm_bufmgr_mutex_unlock();
937 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
940 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
941 if (bo2->priv == bo_priv) {
942 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
943 bo2, bo2->ref_cnt, key,
944 _tbm_flag_to_str(bo2->flags));
947 _tbm_bufmgr_mutex_unlock();
958 if (bufmgr->backend->bo_get_flags)
959 bo->flags = bufmgr->backend->bo_get_flags(bo);
961 bo->flags = TBM_BO_DEFAULT;
963 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
964 bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
966 LIST_INITHEAD(&bo->user_data_list);
968 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
970 _tbm_bufmgr_mutex_unlock();
976 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
981 _tbm_bufmgr_mutex_lock();
983 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
984 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
986 if (!bufmgr->backend->bo_import_fd) {
987 _tbm_bufmgr_mutex_unlock();
991 _tbm_util_check_bo_cnt(bufmgr);
993 bo = calloc(1, sizeof(struct _tbm_bo));
995 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
996 _tbm_bufmgr_mutex_unlock();
1000 bo->bufmgr = bufmgr;
1002 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1004 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1005 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
1007 _tbm_bufmgr_mutex_unlock();
1011 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1014 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1015 if (bo2->priv == bo_priv) {
1016 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1017 bo2, bo2->ref_cnt, fd,
1018 _tbm_flag_to_str(bo2->flags));
1021 _tbm_bufmgr_mutex_unlock();
1032 if (bufmgr->backend->bo_get_flags)
1033 bo->flags = bufmgr->backend->bo_get_flags(bo);
1035 bo->flags = TBM_BO_DEFAULT;
1037 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1038 bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1040 LIST_INITHEAD(&bo->user_data_list);
1042 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1044 _tbm_bufmgr_mutex_unlock();
1050 tbm_bo_export(tbm_bo bo)
1052 tbm_bufmgr bufmgr = gBufMgr;
1055 _tbm_bufmgr_mutex_lock();
1057 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1058 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1060 if (!bufmgr->backend->bo_export) {
1061 _tbm_bufmgr_mutex_unlock();
1065 ret = bufmgr->backend->bo_export(bo);
1067 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1068 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1069 _tbm_bufmgr_mutex_unlock();
1073 TBM_TRACE("bo(%p) tbm_key(%u)\n", bo, ret);
1075 _tbm_bufmgr_mutex_unlock();
1081 tbm_bo_export_fd(tbm_bo bo)
1083 tbm_bufmgr bufmgr = gBufMgr;
1086 _tbm_bufmgr_mutex_lock();
1088 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), -1);
1089 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1091 if (!bufmgr->backend->bo_export_fd) {
1092 _tbm_bufmgr_mutex_unlock();
1096 ret = bufmgr->backend->bo_export_fd(bo);
1098 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1099 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1100 _tbm_bufmgr_mutex_unlock();
1104 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1106 _tbm_bufmgr_mutex_unlock();
1112 tbm_bo_get_handle(tbm_bo bo, int device)
1114 tbm_bufmgr bufmgr = gBufMgr;
1115 tbm_bo_handle bo_handle;
1117 _tbm_bufmgr_mutex_lock();
1119 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1120 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1122 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1123 if (bo_handle.ptr == NULL) {
1124 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1125 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1126 _tbm_bufmgr_mutex_unlock();
1127 return (tbm_bo_handle) NULL;
1130 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1132 _tbm_bufmgr_mutex_unlock();
1138 tbm_bo_map(tbm_bo bo, int device, int opt)
1140 tbm_bufmgr bufmgr = gBufMgr;
1141 tbm_bo_handle bo_handle;
1143 _tbm_bufmgr_mutex_lock();
1145 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1146 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1148 if (!_tbm_bo_lock(bo, device, opt)) {
1149 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1150 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1151 _tbm_bufmgr_mutex_unlock();
1152 return (tbm_bo_handle) NULL;
1155 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1156 if (bo_handle.ptr == NULL) {
1157 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1158 TBM_TRACE("error: fail to map bo:%p\n", bo);
1160 _tbm_bufmgr_mutex_unlock();
1161 return (tbm_bo_handle) NULL;
1164 /* increase the map_count */
1167 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1169 _tbm_bufmgr_mutex_unlock();
1175 tbm_bo_unmap(tbm_bo bo)
1177 tbm_bufmgr bufmgr = gBufMgr;
1180 _tbm_bufmgr_mutex_lock();
1182 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1183 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1185 ret = bufmgr->backend->bo_unmap(bo);
1187 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1188 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1189 _tbm_bufmgr_mutex_unlock();
1193 /* decrease the map_count */
1196 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1200 _tbm_bufmgr_mutex_unlock();
1206 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1208 tbm_bufmgr bufmgr = gBufMgr;
1211 _tbm_bufmgr_mutex_lock();
1213 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1214 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1215 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1217 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1219 if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1220 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1221 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1222 _tbm_bufmgr_mutex_unlock();
1226 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1229 bo1->priv = bo2->priv;
1232 _tbm_bufmgr_mutex_unlock();
1238 tbm_bo_locked(tbm_bo bo)
1240 tbm_bufmgr bufmgr = gBufMgr;
1242 _tbm_bufmgr_mutex_lock();
1244 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1245 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1247 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1248 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1249 _tbm_bufmgr_mutex_unlock();
1253 if (bo->lock_cnt > 0) {
1254 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1255 _tbm_bufmgr_mutex_unlock();
1259 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1260 _tbm_bufmgr_mutex_unlock();
1266 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1267 tbm_data_free data_free_func)
1269 tbm_user_data *data;
1271 _tbm_bufmgr_mutex_lock();
1273 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1274 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1276 /* check if the data according to the key exist if so, return false. */
1277 data = user_data_lookup(&bo->user_data_list, key);
1279 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1280 _tbm_bufmgr_mutex_unlock();
1284 data = user_data_create(key, data_free_func);
1286 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1287 _tbm_bufmgr_mutex_unlock();
1291 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1293 LIST_ADD(&data->item_link, &bo->user_data_list);
1295 _tbm_bufmgr_mutex_unlock();
1301 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1303 tbm_user_data *old_data;
1305 _tbm_bufmgr_mutex_lock();
1307 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1308 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1310 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1311 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1312 _tbm_bufmgr_mutex_unlock();
1316 old_data = user_data_lookup(&bo->user_data_list, key);
1318 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1319 _tbm_bufmgr_mutex_unlock();
1323 if (old_data->data && old_data->free_func)
1324 old_data->free_func(old_data->data);
1325 old_data->data = data;
1327 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1329 _tbm_bufmgr_mutex_unlock();
1335 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1337 tbm_user_data *old_data;
1339 _tbm_bufmgr_mutex_lock();
1341 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1342 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1344 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1345 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1346 _tbm_bufmgr_mutex_unlock();
1350 old_data = user_data_lookup(&bo->user_data_list, key);
1352 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1354 _tbm_bufmgr_mutex_unlock();
1358 *data = old_data->data;
1360 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1362 _tbm_bufmgr_mutex_unlock();
1368 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1370 tbm_user_data *old_data;
1372 _tbm_bufmgr_mutex_lock();
1374 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1375 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1377 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1378 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1379 _tbm_bufmgr_mutex_unlock();
1383 old_data = user_data_lookup(&bo->user_data_list, key);
1385 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1386 _tbm_bufmgr_mutex_unlock();
1390 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1392 user_data_delete(old_data);
1394 _tbm_bufmgr_mutex_unlock();
1400 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1402 unsigned int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1404 _tbm_bufmgr_mutex_lock();
1406 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1407 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1409 TBM_TRACE("tbm_bufmgr(%p) capability(%u)\n", bufmgr, bufmgr->capabilities);
1411 capabilities = bufmgr->capabilities;
1413 _tbm_bufmgr_mutex_unlock();
1415 return capabilities;
1419 tbm_bo_get_flags(tbm_bo bo)
1423 _tbm_bufmgr_mutex_lock();
1425 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1426 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1430 TBM_TRACE("bo(%p)\n", bo);
1432 _tbm_bufmgr_mutex_unlock();
1437 /* LCOV_EXCL_START */
1439 tbm_get_last_error(void)
1441 return tbm_last_error;
1445 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1447 char app_name[255] = {0,}, title[255] = {0,};
1448 tbm_surface_debug_data *debug_old_data = NULL;
1450 pthread_mutex_lock(&gLock);
1452 if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
1453 TBM_LOG_E("invalid bufmgr\n");
1454 pthread_mutex_unlock(&gLock);
1459 _tbm_util_get_appname_from_pid(getpid(), app_name);
1460 _tbm_util_get_appname_brief(app_name);
1461 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1462 app_name, getpid());
1464 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1466 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1467 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
1468 strncat(title, " ", 3);
1469 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1473 TBM_DEBUG("[tbm_surface information]\n");
1474 TBM_DEBUG("%s\n", title);
1476 /* show the tbm_surface information in surf_list */
1477 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1478 tbm_surface_h surf = NULL;
1481 LIST_FOR_EACH_ENTRY(surf, &bufmgr->surf_list, item_link) {
1482 char data[255] = {0,};
1486 pid = _tbm_surface_internal_get_debug_pid(surf);
1488 /* if pid is null, set the self_pid */
1492 memset(app_name, 0x0, 255 * sizeof(char));
1493 _tbm_util_get_appname_from_pid(pid, app_name);
1494 _tbm_util_get_appname_brief(app_name);
1496 snprintf(data, 255, "%-2d %-9p %-4d %-5u %-6u %-3u %-6u %-2d %-2d %-3d %-8s %-15s",
1503 surf->info.size / 1024,
1507 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1510 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1511 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
1514 strncat(data, " ", 3);
1516 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1518 strncat(data, value, strlen(value) + 1);
1520 strncat(data, "none", 5);
1523 TBM_DEBUG("%s\n", data);
1525 for (i = 0; i < surf->num_bos; i++) {
1526 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1528 surf->bos[i]->ref_cnt,
1529 bufmgr->backend->bo_size(surf->bos[i]) / 1024);
1533 TBM_DEBUG("no tbm_surfaces.\n");
1536 TBM_DEBUG("[tbm_bo information]\n");
1537 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1539 /* show the tbm_bo information in bo_list */
1540 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1544 LIST_FOR_EACH_ENTRY(bo, &bufmgr->bo_list, item_link) {
1545 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4u %-3d %-11p\n",
1549 bufmgr->backend->bo_size(bo) / 1024,
1556 TBM_DEBUG("no tbm_bos.\n");
1559 TBM_DEBUG("===============================================================\n");
1561 pthread_mutex_unlock(&gLock);
1565 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1567 _tbm_bufmgr_mutex_lock();
1569 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1570 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1573 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1577 _tbm_bufmgr_mutex_unlock();
1581 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1583 pthread_mutex_lock(&gLock);
1586 TBM_LOG_D("count=%d onoff=%d\n", count, onoff);
1588 tbm_surface_internal_dump_end();
1593 TBM_LOG_E("path is null");
1594 pthread_mutex_unlock(&gLock);
1597 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1599 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1600 TBM_LOG_I("Fail to get tbm_surface size.\n");
1601 pthread_mutex_unlock(&gLock);
1605 tbm_surface_internal_dump_start(path, w, h, count);
1609 pthread_mutex_unlock(&gLock);
1614 tbm_bufmgr_debug_dump_all(char *path)
1616 int w, h, count = 0;
1617 tbm_surface_h surface = NULL;
1619 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1620 TBM_LOG_D("path=%s\n", path);
1622 pthread_mutex_lock(&gLock);
1624 count = _tbm_util_get_max_surface_size(&w, &h);
1626 TBM_LOG_I("No tbm_surface.\n");
1627 pthread_mutex_unlock(&gLock);
1631 tbm_surface_internal_dump_start(path, w, h, count);
1633 LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link)
1634 tbm_surface_internal_dump_buffer(surface, "dump_all");
1636 tbm_surface_internal_dump_end();
1638 pthread_mutex_unlock(&gLock);
1643 /* internal function */
1645 _tbm_bufmgr_get_bufmgr(void)
1651 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1653 _tbm_bufmgr_mutex_lock();
1655 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1656 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1658 bo->surface = surface;
1660 _tbm_bufmgr_mutex_unlock();
1666 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1670 _tbm_bufmgr_mutex_lock();
1672 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1674 if (!bufmgr->backend->bufmgr_bind_native_display) {
1675 TBM_TRACE("skip: tbm_bufmgr(%p) NativeDisplay(%p)\n",
1676 bufmgr, NativeDisplay);
1677 _tbm_bufmgr_mutex_unlock();
1681 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1683 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n",
1684 bufmgr, NativeDisplay);
1685 _tbm_bufmgr_mutex_unlock();
1689 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1691 _tbm_bufmgr_mutex_unlock();
1695 /* LCOV_EXCL_STOP */