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)
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);
617 /* initialize buffer manager */
619 gBufMgr->ref_count++;
620 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
621 pthread_mutex_unlock(&gLock);
625 TBM_DBG("bufmgr init\n");
627 /* allocate bufmgr */
628 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
630 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
631 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
632 pthread_mutex_unlock(&gLock);
638 /* load bufmgr priv from env */
639 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
640 /* LCOV_EXCL_START */
641 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
642 TBM_LOG_E("error : Fail to load bufmgr backend\n");
645 pthread_mutex_unlock(&gLock);
650 /* log for tbm backend_flag */
651 TBM_DBG("backend flag:%x:", gBufMgr->backend->flags);
654 gBufMgr->ref_count = 1;
656 TBM_DBG("create tizen bufmgr:%p ref_count:%d\n",
657 gBufMgr, gBufMgr->ref_count);
659 /* setup the lock_type */
660 env = getenv("BUFMGR_LOCK_TYPE");
661 if (env && !strcmp(env, "always"))
662 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
663 else if (env && !strcmp(env, "none"))
664 gBufMgr->lock_type = LOCK_TRY_NEVER;
665 else if (env && !strcmp(env, "once"))
666 gBufMgr->lock_type = LOCK_TRY_ONCE;
668 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
670 TBM_DBG("BUFMGR_LOCK_TYPE=%s\n", env ? env : "default:once");
672 TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
674 /* intialize bo_list */
675 LIST_INITHEAD(&gBufMgr->bo_list);
677 /* intialize surf_list */
678 LIST_INITHEAD(&gBufMgr->surf_list);
680 /* intialize surf_queue_list */
681 LIST_INITHEAD(&gBufMgr->surf_queue_list);
683 /* intialize debug_key_list */
684 LIST_INITHEAD(&gBufMgr->debug_key_list);
686 #ifdef TBM_BUFMGR_INIT_TIME
688 gettimeofday(&end_tv, NULL);
689 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)));
692 pthread_mutex_unlock(&gLock);
698 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
700 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
702 pthread_mutex_lock(&gLock);
705 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
706 pthread_mutex_unlock(&gLock);
711 if (bufmgr->ref_count > 0) {
712 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
713 pthread_mutex_unlock(&gLock);
717 /* destroy bo_list */
718 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
719 tbm_bo bo = NULL, tmp;
721 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
722 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n", bo, bo->ref_cnt);
728 /* destroy surf_list */
729 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
730 tbm_surface_h surf = NULL, tmp;
732 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &bufmgr->surf_list, item_link) {
733 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n", surf, surf->refcnt);
734 tbm_surface_destroy(surf);
738 /* destroy bufmgr priv */
739 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
740 bufmgr->backend->priv = NULL;
741 tbm_backend_free(bufmgr->backend);
742 bufmgr->backend = NULL;
744 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
746 dlclose(bufmgr->module_data);
754 pthread_mutex_unlock(&gLock);
758 tbm_bo_size(tbm_bo bo)
760 tbm_bufmgr bufmgr = NULL;
763 _tbm_bufmgr_mutex_lock();
765 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
766 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
770 size = bufmgr->backend->bo_size(bo);
772 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
774 _tbm_bufmgr_mutex_unlock();
780 tbm_bo_ref(tbm_bo bo)
782 _tbm_bufmgr_mutex_lock();
784 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
785 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
789 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
791 _tbm_bufmgr_mutex_unlock();
797 tbm_bo_unref(tbm_bo bo)
799 tbm_bufmgr bufmgr = NULL;
800 tbm_user_data *old_data = NULL, *tmp = NULL;
802 _tbm_bufmgr_mutex_lock();
804 TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
805 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 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
821 TBM_DBG("free user_data\n");
822 user_data_delete(old_data);
826 while (bo->lock_cnt > 0) {
827 TBM_LOG_E("error lock_cnt:%d\n",
833 /* call the bo_free */
834 bufmgr->backend->bo_free(bo);
837 LIST_DEL(&bo->item_link);
843 _tbm_bufmgr_mutex_unlock();
847 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
850 void *bo_priv = NULL;
852 _tbm_bufmgr_mutex_lock();
854 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
855 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
856 TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
858 bo = calloc(1, sizeof(struct _tbm_bo));
860 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n",
861 size, _tbm_flag_to_str(flags));
862 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
863 _tbm_bufmgr_mutex_unlock();
867 _tbm_util_check_bo_cnt(bufmgr);
872 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
874 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n",
875 size, _tbm_flag_to_str(flags));
876 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
878 _tbm_bufmgr_mutex_unlock();
886 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
887 _tbm_flag_to_str(bo->flags));
889 LIST_INITHEAD(&bo->user_data_list);
891 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
893 _tbm_bufmgr_mutex_unlock();
899 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
904 void *bo_priv = NULL;
906 _tbm_bufmgr_mutex_lock();
908 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
909 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
911 if (!bufmgr->backend->bo_import) {
912 _tbm_bufmgr_mutex_unlock();
916 _tbm_util_check_bo_cnt(bufmgr);
918 bo = calloc(1, sizeof(struct _tbm_bo));
920 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
921 _tbm_bufmgr_mutex_unlock();
927 bo_priv = bufmgr->backend->bo_import(bo, key);
929 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
930 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
932 _tbm_bufmgr_mutex_unlock();
936 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
937 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
938 if (bo2->priv == bo_priv) {
939 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
940 bo2, bo2->ref_cnt, key,
941 _tbm_flag_to_str(bo2->flags));
944 _tbm_bufmgr_mutex_unlock();
955 if (bufmgr->backend->bo_get_flags)
956 bo->flags = bufmgr->backend->bo_get_flags(bo);
958 bo->flags = TBM_BO_DEFAULT;
960 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
961 bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
963 LIST_INITHEAD(&bo->user_data_list);
965 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
967 _tbm_bufmgr_mutex_unlock();
973 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
978 void *bo_priv = NULL;
980 _tbm_bufmgr_mutex_lock();
982 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
983 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
985 if (!bufmgr->backend->bo_import_fd) {
986 _tbm_bufmgr_mutex_unlock();
990 _tbm_util_check_bo_cnt(bufmgr);
992 bo = calloc(1, sizeof(struct _tbm_bo));
994 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
995 _tbm_bufmgr_mutex_unlock();
1001 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1003 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1004 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
1006 _tbm_bufmgr_mutex_unlock();
1010 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1011 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
1012 if (bo2->priv == bo_priv) {
1013 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1014 bo2, bo2->ref_cnt, fd,
1015 _tbm_flag_to_str(bo2->flags));
1018 _tbm_bufmgr_mutex_unlock();
1029 if (bufmgr->backend->bo_get_flags)
1030 bo->flags = bufmgr->backend->bo_get_flags(bo);
1032 bo->flags = TBM_BO_DEFAULT;
1034 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1035 bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1037 LIST_INITHEAD(&bo->user_data_list);
1039 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1041 _tbm_bufmgr_mutex_unlock();
1047 tbm_bo_export(tbm_bo bo)
1049 tbm_bufmgr bufmgr = NULL;
1052 _tbm_bufmgr_mutex_lock();
1054 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1055 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1059 if (!bufmgr->backend->bo_export) {
1060 _tbm_bufmgr_mutex_unlock();
1064 ret = bufmgr->backend->bo_export(bo);
1066 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1067 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1068 _tbm_bufmgr_mutex_unlock();
1072 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
1074 _tbm_bufmgr_mutex_unlock();
1080 tbm_bo_export_fd(tbm_bo bo)
1082 tbm_bufmgr bufmgr = NULL;
1085 _tbm_bufmgr_mutex_lock();
1087 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), -1);
1088 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1092 if (!bufmgr->backend->bo_export_fd) {
1093 _tbm_bufmgr_mutex_unlock();
1097 ret = bufmgr->backend->bo_export_fd(bo);
1099 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1100 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1101 _tbm_bufmgr_mutex_unlock();
1105 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1107 _tbm_bufmgr_mutex_unlock();
1113 tbm_bo_get_handle(tbm_bo bo, int device)
1115 tbm_bufmgr bufmgr = NULL;
1116 tbm_bo_handle bo_handle;
1118 _tbm_bufmgr_mutex_lock();
1120 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1121 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1125 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1126 if (bo_handle.ptr == NULL) {
1127 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1128 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1129 _tbm_bufmgr_mutex_unlock();
1130 return (tbm_bo_handle) NULL;
1133 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1135 _tbm_bufmgr_mutex_unlock();
1141 tbm_bo_map(tbm_bo bo, int device, int opt)
1143 tbm_bufmgr bufmgr = NULL;
1144 tbm_bo_handle bo_handle;
1146 _tbm_bufmgr_mutex_lock();
1148 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1149 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1153 if (!_tbm_bo_lock(bo, device, opt)) {
1154 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1155 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1156 _tbm_bufmgr_mutex_unlock();
1157 return (tbm_bo_handle) NULL;
1160 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1161 if (bo_handle.ptr == NULL) {
1162 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1163 TBM_TRACE("error: fail to map bo:%p\n", bo);
1165 _tbm_bufmgr_mutex_unlock();
1166 return (tbm_bo_handle) NULL;
1169 /* increase the map_count */
1172 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1174 _tbm_bufmgr_mutex_unlock();
1180 tbm_bo_unmap(tbm_bo bo)
1182 tbm_bufmgr bufmgr = NULL;
1185 _tbm_bufmgr_mutex_lock();
1187 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1188 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1192 ret = bufmgr->backend->bo_unmap(bo);
1194 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1195 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1196 _tbm_bufmgr_mutex_unlock();
1200 /* decrease the map_count */
1203 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1207 _tbm_bufmgr_mutex_unlock();
1213 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1215 tbm_bufmgr bufmgr = NULL;
1218 _tbm_bufmgr_mutex_lock();
1220 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1221 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1222 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1226 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1228 if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1229 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1230 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1231 _tbm_bufmgr_mutex_unlock();
1235 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1238 bo1->priv = bo2->priv;
1241 _tbm_bufmgr_mutex_unlock();
1247 tbm_bo_locked(tbm_bo bo)
1249 tbm_bufmgr bufmgr = NULL;
1251 _tbm_bufmgr_mutex_lock();
1253 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1254 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1258 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1259 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1260 _tbm_bufmgr_mutex_unlock();
1264 if (bo->lock_cnt > 0) {
1265 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1266 _tbm_bufmgr_mutex_unlock();
1270 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1271 _tbm_bufmgr_mutex_unlock();
1277 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1278 tbm_data_free data_free_func)
1280 tbm_user_data *data;
1282 _tbm_bufmgr_mutex_lock();
1284 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1285 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1287 /* check if the data according to the key exist if so, return false. */
1288 data = user_data_lookup(&bo->user_data_list, key);
1290 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1291 _tbm_bufmgr_mutex_unlock();
1295 data = user_data_create(key, data_free_func);
1297 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1298 _tbm_bufmgr_mutex_unlock();
1302 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1304 LIST_ADD(&data->item_link, &bo->user_data_list);
1306 _tbm_bufmgr_mutex_unlock();
1312 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1314 tbm_user_data *old_data;
1316 _tbm_bufmgr_mutex_lock();
1318 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1319 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1321 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1322 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1323 _tbm_bufmgr_mutex_unlock();
1327 old_data = user_data_lookup(&bo->user_data_list, key);
1329 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1330 _tbm_bufmgr_mutex_unlock();
1334 if (old_data->data && old_data->free_func)
1335 old_data->free_func(old_data->data);
1337 old_data->data = data;
1339 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1341 _tbm_bufmgr_mutex_unlock();
1347 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1349 tbm_user_data *old_data;
1351 _tbm_bufmgr_mutex_lock();
1353 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1354 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1356 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1357 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1358 _tbm_bufmgr_mutex_unlock();
1362 old_data = user_data_lookup(&bo->user_data_list, key);
1364 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1366 _tbm_bufmgr_mutex_unlock();
1370 *data = old_data->data;
1372 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1374 _tbm_bufmgr_mutex_unlock();
1380 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1382 tbm_user_data *old_data = (void *)0;
1384 _tbm_bufmgr_mutex_lock();
1386 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1387 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1389 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1390 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1391 _tbm_bufmgr_mutex_unlock();
1395 old_data = user_data_lookup(&bo->user_data_list, key);
1397 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1398 _tbm_bufmgr_mutex_unlock();
1402 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1404 user_data_delete(old_data);
1406 _tbm_bufmgr_mutex_unlock();
1412 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1414 int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1416 _tbm_bufmgr_mutex_lock();
1418 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1419 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1421 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1423 capabilities = bufmgr->capabilities;
1425 _tbm_bufmgr_mutex_unlock();
1427 return capabilities;
1431 tbm_bo_get_flags(tbm_bo bo)
1435 _tbm_bufmgr_mutex_lock();
1437 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1438 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1442 TBM_TRACE("bo(%p)\n", bo);
1444 _tbm_bufmgr_mutex_unlock();
1449 /* LCOV_EXCL_START */
1451 tbm_get_last_error(void)
1453 return tbm_last_error;
1457 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1459 tbm_bo bo = NULL, tmp_bo = NULL;
1461 tbm_surface_h surf = NULL, tmp_surf = NULL;
1464 char app_name[255] = {0,};
1465 unsigned int pid = 0;
1466 char title[255] = {0,};
1467 char data[255] = {0,};
1468 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1470 pthread_mutex_lock(&gLock);
1472 if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
1473 TBM_LOG_E("invalid bufmgr\n");
1474 pthread_mutex_unlock(&gLock);
1479 _tbm_util_get_appname_from_pid(getpid(), app_name);
1480 _tbm_util_get_appname_brief(app_name);
1481 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1482 app_name, getpid());
1483 memset(app_name, 0x0, 255 * sizeof(char));
1484 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1485 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1486 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1487 strncat(title, " ", 3);
1488 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1492 TBM_DEBUG("[tbm_surface information]\n");
1493 TBM_DEBUG("%s\n", title);
1494 /* show the tbm_surface information in surf_list */
1495 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1498 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1499 pid = _tbm_surface_internal_get_debug_pid(surf);
1501 /* if pid is null, set the self_pid */
1505 _tbm_util_get_appname_from_pid(pid, app_name);
1506 _tbm_util_get_appname_brief(app_name);
1508 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1515 surf->info.size / 1024,
1519 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1522 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1523 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1524 strncat(data, " ", 3);
1526 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1528 strncat(data, value, strlen(value) + 1);
1530 strncat(data, "none", 5);
1533 TBM_DEBUG("%s\n", data);
1535 for (i = 0; i < surf->num_bos; i++) {
1536 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1538 surf->bos[i]->ref_cnt,
1539 bufmgr->backend->bo_size(surf->bos[i]) / 1024);
1542 memset(app_name, 0x0, 255 * sizeof(char));
1545 TBM_DEBUG("no tbm_surfaces.\n");
1549 TBM_DEBUG("[tbm_bo information]\n");
1550 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1552 /* show the tbm_bo information in bo_list */
1553 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1554 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1555 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1559 bufmgr->backend->bo_size(bo) / 1024,
1566 TBM_DEBUG("no tbm_bos.\n");
1570 TBM_DEBUG("===============================================================\n");
1572 pthread_mutex_unlock(&gLock);
1576 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1578 _tbm_bufmgr_mutex_lock();
1580 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1581 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1584 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1588 _tbm_bufmgr_mutex_unlock();
1592 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1596 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1597 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1599 pthread_mutex_lock(&gLock);
1602 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1603 TBM_LOG_I("No tbm_surface.\n");
1604 pthread_mutex_unlock(&gLock);
1608 tbm_surface_internal_dump_start(path, w, h, count);
1610 } else if (onoff == 0) {
1611 tbm_surface_internal_dump_end();
1614 pthread_mutex_unlock(&gLock);
1618 pthread_mutex_unlock(&gLock);
1623 tbm_bufmgr_debug_dump_all(char *path)
1625 int w = 0, h = 0, count = 0;
1626 tbm_surface_h surface = NULL, tmp = NULL;
1628 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1629 TBM_LOG_D("path=%s\n", path);
1631 pthread_mutex_lock(&gLock);
1633 count = _tbm_util_get_max_surface_size(&w, &h);
1635 TBM_LOG_I("No tbm_surface.\n");
1636 pthread_mutex_unlock(&gLock);
1640 tbm_surface_internal_dump_start(path, w, h, count);
1642 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1643 tbm_surface_internal_dump_buffer(surface, "dump_all");
1646 tbm_surface_internal_dump_end();
1648 pthread_mutex_unlock(&gLock);
1653 /* internal function */
1655 _tbm_bufmgr_get_bufmgr(void)
1661 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1663 _tbm_bufmgr_mutex_lock();
1665 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1666 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1668 bo->surface = surface;
1670 _tbm_bufmgr_mutex_unlock();
1676 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1680 _tbm_bufmgr_mutex_lock();
1682 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1684 if (!bufmgr->backend->bufmgr_bind_native_display) {
1685 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1686 _tbm_bufmgr_mutex_unlock();
1690 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1692 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1693 _tbm_bufmgr_mutex_unlock();
1697 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1699 _tbm_bufmgr_mutex_unlock();
1703 /* LCOV_EXCL_STOP */