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 = gBufMgr;
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);
768 size = bufmgr->backend->bo_size(bo);
770 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
772 _tbm_bufmgr_mutex_unlock();
778 tbm_bo_ref(tbm_bo bo)
780 _tbm_bufmgr_mutex_lock();
782 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
783 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
787 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
789 _tbm_bufmgr_mutex_unlock();
795 tbm_bo_unref(tbm_bo bo)
797 tbm_bufmgr bufmgr = gBufMgr;
799 _tbm_bufmgr_mutex_lock();
801 TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
802 TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
804 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
806 if (bo->ref_cnt <= 0) {
807 _tbm_bufmgr_mutex_unlock();
812 if (bo->ref_cnt == 0) {
813 /* destory the user_data_list */
814 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
815 tbm_user_data *old_data = NULL, *tmp;
817 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
818 &bo->user_data_list, item_link) {
819 TBM_DBG("free user_data\n");
820 user_data_delete(old_data);
824 while (bo->lock_cnt > 0) {
825 TBM_LOG_E("error lock_cnt:%d\n", bo->lock_cnt);
830 /* call the bo_free */
831 bufmgr->backend->bo_free(bo);
834 LIST_DEL(&bo->item_link);
840 _tbm_bufmgr_mutex_unlock();
844 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
849 _tbm_bufmgr_mutex_lock();
851 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
852 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
853 TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
855 bo = calloc(1, sizeof(struct _tbm_bo));
857 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n",
858 size, _tbm_flag_to_str(flags));
859 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
860 _tbm_bufmgr_mutex_unlock();
864 _tbm_util_check_bo_cnt(bufmgr);
868 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
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_BO_ALLOC_FAILED);
874 _tbm_bufmgr_mutex_unlock();
884 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
885 _tbm_flag_to_str(bo->flags));
887 LIST_INITHEAD(&bo->user_data_list);
889 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
891 _tbm_bufmgr_mutex_unlock();
897 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
902 _tbm_bufmgr_mutex_lock();
904 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
905 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
907 if (!bufmgr->backend->bo_import) {
908 _tbm_bufmgr_mutex_unlock();
912 _tbm_util_check_bo_cnt(bufmgr);
914 bo = calloc(1, sizeof(struct _tbm_bo));
916 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
917 _tbm_bufmgr_mutex_unlock();
923 bo_priv = bufmgr->backend->bo_import(bo, key);
925 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
926 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
928 _tbm_bufmgr_mutex_unlock();
932 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
935 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
936 if (bo2->priv == bo_priv) {
937 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
938 bo2, bo2->ref_cnt, key,
939 _tbm_flag_to_str(bo2->flags));
942 _tbm_bufmgr_mutex_unlock();
953 if (bufmgr->backend->bo_get_flags)
954 bo->flags = bufmgr->backend->bo_get_flags(bo);
956 bo->flags = TBM_BO_DEFAULT;
958 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
959 bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
961 LIST_INITHEAD(&bo->user_data_list);
963 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
965 _tbm_bufmgr_mutex_unlock();
971 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
976 _tbm_bufmgr_mutex_lock();
978 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
979 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
981 if (!bufmgr->backend->bo_import_fd) {
982 _tbm_bufmgr_mutex_unlock();
986 _tbm_util_check_bo_cnt(bufmgr);
988 bo = calloc(1, sizeof(struct _tbm_bo));
990 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
991 _tbm_bufmgr_mutex_unlock();
997 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
999 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1000 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
1002 _tbm_bufmgr_mutex_unlock();
1006 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1009 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1010 if (bo2->priv == bo_priv) {
1011 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1012 bo2, bo2->ref_cnt, fd,
1013 _tbm_flag_to_str(bo2->flags));
1016 _tbm_bufmgr_mutex_unlock();
1027 if (bufmgr->backend->bo_get_flags)
1028 bo->flags = bufmgr->backend->bo_get_flags(bo);
1030 bo->flags = TBM_BO_DEFAULT;
1032 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1033 bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1035 LIST_INITHEAD(&bo->user_data_list);
1037 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1039 _tbm_bufmgr_mutex_unlock();
1045 tbm_bo_export(tbm_bo bo)
1047 tbm_bufmgr bufmgr = gBufMgr;
1050 _tbm_bufmgr_mutex_lock();
1052 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1053 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1055 if (!bufmgr->backend->bo_export) {
1056 _tbm_bufmgr_mutex_unlock();
1060 ret = bufmgr->backend->bo_export(bo);
1062 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1063 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1064 _tbm_bufmgr_mutex_unlock();
1068 TBM_TRACE("bo(%p) tbm_key(%u)\n", bo, ret);
1070 _tbm_bufmgr_mutex_unlock();
1076 tbm_bo_export_fd(tbm_bo bo)
1078 tbm_bufmgr bufmgr = gBufMgr;
1081 _tbm_bufmgr_mutex_lock();
1083 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), -1);
1084 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1086 if (!bufmgr->backend->bo_export_fd) {
1087 _tbm_bufmgr_mutex_unlock();
1091 ret = bufmgr->backend->bo_export_fd(bo);
1093 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1094 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1095 _tbm_bufmgr_mutex_unlock();
1099 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1101 _tbm_bufmgr_mutex_unlock();
1107 tbm_bo_get_handle(tbm_bo bo, int device)
1109 tbm_bufmgr bufmgr = gBufMgr;
1110 tbm_bo_handle bo_handle;
1112 _tbm_bufmgr_mutex_lock();
1114 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1115 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1117 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1118 if (bo_handle.ptr == NULL) {
1119 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1120 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1121 _tbm_bufmgr_mutex_unlock();
1122 return (tbm_bo_handle) NULL;
1125 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1127 _tbm_bufmgr_mutex_unlock();
1133 tbm_bo_map(tbm_bo bo, int device, int opt)
1135 tbm_bufmgr bufmgr = gBufMgr;
1136 tbm_bo_handle bo_handle;
1138 _tbm_bufmgr_mutex_lock();
1140 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1141 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1143 if (!_tbm_bo_lock(bo, device, opt)) {
1144 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1145 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1146 _tbm_bufmgr_mutex_unlock();
1147 return (tbm_bo_handle) NULL;
1150 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1151 if (bo_handle.ptr == NULL) {
1152 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1153 TBM_TRACE("error: fail to map bo:%p\n", bo);
1155 _tbm_bufmgr_mutex_unlock();
1156 return (tbm_bo_handle) NULL;
1159 /* increase the map_count */
1162 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1164 _tbm_bufmgr_mutex_unlock();
1170 tbm_bo_unmap(tbm_bo bo)
1172 tbm_bufmgr bufmgr = gBufMgr;
1175 _tbm_bufmgr_mutex_lock();
1177 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1178 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1180 ret = bufmgr->backend->bo_unmap(bo);
1182 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1183 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1184 _tbm_bufmgr_mutex_unlock();
1188 /* decrease the map_count */
1191 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1195 _tbm_bufmgr_mutex_unlock();
1201 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1203 tbm_bufmgr bufmgr = gBufMgr;
1206 _tbm_bufmgr_mutex_lock();
1208 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1209 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1210 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1212 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1214 if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1215 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1216 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1217 _tbm_bufmgr_mutex_unlock();
1221 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1224 bo1->priv = bo2->priv;
1227 _tbm_bufmgr_mutex_unlock();
1233 tbm_bo_locked(tbm_bo bo)
1235 tbm_bufmgr bufmgr = gBufMgr;
1237 _tbm_bufmgr_mutex_lock();
1239 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1240 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1242 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1243 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1244 _tbm_bufmgr_mutex_unlock();
1248 if (bo->lock_cnt > 0) {
1249 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1250 _tbm_bufmgr_mutex_unlock();
1254 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1255 _tbm_bufmgr_mutex_unlock();
1261 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1262 tbm_data_free data_free_func)
1264 tbm_user_data *data;
1266 _tbm_bufmgr_mutex_lock();
1268 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1269 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1271 /* check if the data according to the key exist if so, return false. */
1272 data = user_data_lookup(&bo->user_data_list, key);
1274 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1275 _tbm_bufmgr_mutex_unlock();
1279 data = user_data_create(key, data_free_func);
1281 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1282 _tbm_bufmgr_mutex_unlock();
1286 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1288 LIST_ADD(&data->item_link, &bo->user_data_list);
1290 _tbm_bufmgr_mutex_unlock();
1296 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1298 tbm_user_data *old_data;
1300 _tbm_bufmgr_mutex_lock();
1302 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1303 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1305 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1306 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1307 _tbm_bufmgr_mutex_unlock();
1311 old_data = user_data_lookup(&bo->user_data_list, key);
1313 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1314 _tbm_bufmgr_mutex_unlock();
1318 if (old_data->data && old_data->free_func)
1319 old_data->free_func(old_data->data);
1320 old_data->data = data;
1322 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1324 _tbm_bufmgr_mutex_unlock();
1330 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1332 tbm_user_data *old_data;
1334 _tbm_bufmgr_mutex_lock();
1336 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1337 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1339 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1340 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1341 _tbm_bufmgr_mutex_unlock();
1345 old_data = user_data_lookup(&bo->user_data_list, key);
1347 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1349 _tbm_bufmgr_mutex_unlock();
1353 *data = old_data->data;
1355 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1357 _tbm_bufmgr_mutex_unlock();
1363 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1365 tbm_user_data *old_data;
1367 _tbm_bufmgr_mutex_lock();
1369 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1370 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1372 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1373 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1374 _tbm_bufmgr_mutex_unlock();
1378 old_data = user_data_lookup(&bo->user_data_list, key);
1380 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1381 _tbm_bufmgr_mutex_unlock();
1385 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1387 user_data_delete(old_data);
1389 _tbm_bufmgr_mutex_unlock();
1395 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1397 int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1399 _tbm_bufmgr_mutex_lock();
1401 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1402 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1404 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1406 capabilities = bufmgr->capabilities;
1408 _tbm_bufmgr_mutex_unlock();
1410 return capabilities;
1414 tbm_bo_get_flags(tbm_bo bo)
1418 _tbm_bufmgr_mutex_lock();
1420 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1421 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1425 TBM_TRACE("bo(%p)\n", bo);
1427 _tbm_bufmgr_mutex_unlock();
1432 /* LCOV_EXCL_START */
1434 tbm_get_last_error(void)
1436 return tbm_last_error;
1440 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1442 tbm_bo bo = NULL, tmp_bo = NULL;
1444 tbm_surface_h surf = NULL, tmp_surf = NULL;
1447 char app_name[255] = {0,};
1448 unsigned int pid = 0;
1449 char title[255] = {0,};
1450 char data[255] = {0,};
1451 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1453 pthread_mutex_lock(&gLock);
1455 if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
1456 TBM_LOG_E("invalid bufmgr\n");
1457 pthread_mutex_unlock(&gLock);
1462 _tbm_util_get_appname_from_pid(getpid(), app_name);
1463 _tbm_util_get_appname_brief(app_name);
1464 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1465 app_name, getpid());
1466 memset(app_name, 0x0, 255 * sizeof(char));
1467 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1468 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1469 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1470 strncat(title, " ", 3);
1471 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1475 TBM_DEBUG("[tbm_surface information]\n");
1476 TBM_DEBUG("%s\n", title);
1477 /* show the tbm_surface information in surf_list */
1478 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1481 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1482 pid = _tbm_surface_internal_get_debug_pid(surf);
1484 /* if pid is null, set the self_pid */
1488 _tbm_util_get_appname_from_pid(pid, app_name);
1489 _tbm_util_get_appname_brief(app_name);
1491 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1498 surf->info.size / 1024,
1502 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1505 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1506 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1507 strncat(data, " ", 3);
1509 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1511 strncat(data, value, strlen(value) + 1);
1513 strncat(data, "none", 5);
1516 TBM_DEBUG("%s\n", data);
1518 for (i = 0; i < surf->num_bos; i++) {
1519 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1521 surf->bos[i]->ref_cnt,
1522 bufmgr->backend->bo_size(surf->bos[i]) / 1024);
1525 memset(app_name, 0x0, 255 * sizeof(char));
1528 TBM_DEBUG("no tbm_surfaces.\n");
1532 TBM_DEBUG("[tbm_bo information]\n");
1533 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1535 /* show the tbm_bo information in bo_list */
1536 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1537 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1538 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1542 bufmgr->backend->bo_size(bo) / 1024,
1549 TBM_DEBUG("no tbm_bos.\n");
1553 TBM_DEBUG("===============================================================\n");
1555 pthread_mutex_unlock(&gLock);
1559 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1561 _tbm_bufmgr_mutex_lock();
1563 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1564 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1567 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1571 _tbm_bufmgr_mutex_unlock();
1575 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1579 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1580 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1582 pthread_mutex_lock(&gLock);
1585 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1586 TBM_LOG_I("No tbm_surface.\n");
1587 pthread_mutex_unlock(&gLock);
1591 tbm_surface_internal_dump_start(path, w, h, count);
1593 } else if (onoff == 0) {
1594 tbm_surface_internal_dump_end();
1597 pthread_mutex_unlock(&gLock);
1601 pthread_mutex_unlock(&gLock);
1606 tbm_bufmgr_debug_dump_all(char *path)
1608 int w = 0, h = 0, count = 0;
1609 tbm_surface_h surface = NULL, tmp = NULL;
1611 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1612 TBM_LOG_D("path=%s\n", path);
1614 pthread_mutex_lock(&gLock);
1616 count = _tbm_util_get_max_surface_size(&w, &h);
1618 TBM_LOG_I("No tbm_surface.\n");
1619 pthread_mutex_unlock(&gLock);
1623 tbm_surface_internal_dump_start(path, w, h, count);
1625 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1626 tbm_surface_internal_dump_buffer(surface, "dump_all");
1629 tbm_surface_internal_dump_end();
1631 pthread_mutex_unlock(&gLock);
1636 /* internal function */
1638 _tbm_bufmgr_get_bufmgr(void)
1644 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1646 _tbm_bufmgr_mutex_lock();
1648 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1649 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1651 bo->surface = surface;
1653 _tbm_bufmgr_mutex_unlock();
1659 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1663 _tbm_bufmgr_mutex_lock();
1665 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1667 if (!bufmgr->backend->bufmgr_bind_native_display) {
1668 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1669 _tbm_bufmgr_mutex_unlock();
1673 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1675 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1676 _tbm_bufmgr_mutex_unlock();
1680 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1682 _tbm_bufmgr_mutex_unlock();
1686 /* LCOV_EXCL_STOP */