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 TBMModuleData *initdata = NULL;
484 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
486 module_data = dlopen(path, RTLD_LAZY);
488 TBM_LOG_E("failed to load module: %s(%s)\n",
493 initdata = dlsym(module_data, "tbmModuleData");
496 TBMModuleVersionInfo *vers;
498 vers = initdata->vers;
499 init = initdata->init;
502 if (!_check_version(vers)) {
503 dlclose(module_data);
507 TBM_LOG_E("Error: module does not supply version information.\n");
509 dlclose(module_data);
514 if (!init(bufmgr, fd)) {
515 TBM_LOG_E("Fail to init module(%s)\n",
517 dlclose(module_data);
521 if (!bufmgr->backend || !bufmgr->backend->priv) {
522 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n",
524 dlclose(module_data);
528 TBM_LOG_E("Error: module does not supply init symbol.\n");
529 dlclose(module_data);
533 TBM_LOG_E("Error: module does not have data object.\n");
534 dlclose(module_data);
538 bufmgr->module_data = module_data;
540 TBM_DBG("Success to load module(%s)\n",
547 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
549 struct dirent **namelist;
550 const char *p = NULL;
554 /* load bufmgr priv from default lib */
555 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
557 /* load bufmgr priv from configured path */
559 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
561 TBM_LOG_E("no files : %s\n",
565 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
566 p = strstr(namelist[n]->d_name, SUFFIX_LIB);
567 if (p && !strcmp(p, SUFFIX_LIB))
568 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
581 tbm_bufmgr_init(int fd)
585 #ifdef TBM_BUFMGR_INIT_TIME
586 struct timeval start_tv, end_tv;
589 pthread_mutex_lock(&gLock);
591 #ifdef TBM_BUFMGR_INIT_TIME
592 /* get the start tv */
593 gettimeofday(&start_tv, NULL);
596 /* LCOV_EXCL_START */
598 env = getenv("TBM_DLOG");
601 TBM_LOG_D("TBM_DLOG=%s\n", env);
608 env = getenv("TBM_DEBUG");
611 TBM_LOG_D("TBM_DEBUG=%s\n", env);
618 env = getenv("TBM_TRACE");
621 TBM_LOG_D("TBM_TRACE=%s\n", env);
628 /* initialize buffer manager */
630 gBufMgr->ref_count++;
631 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
632 pthread_mutex_unlock(&gLock);
636 TBM_DBG("bufmgr init\n");
638 /* allocate bufmgr */
639 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
641 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
642 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
643 pthread_mutex_unlock(&gLock);
649 /* load bufmgr priv from env */
650 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
651 /* LCOV_EXCL_START */
652 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
653 TBM_LOG_E("error : Fail to load bufmgr backend\n");
656 pthread_mutex_unlock(&gLock);
661 /* log for tbm backend_flag */
662 TBM_DBG("backend flag:%x:", gBufMgr->backend->flags);
665 gBufMgr->ref_count = 1;
667 TBM_DBG("create tizen bufmgr:%p ref_count:%d\n",
668 gBufMgr, gBufMgr->ref_count);
670 /* setup the lock_type */
671 env = getenv("BUFMGR_LOCK_TYPE");
672 if (env && !strcmp(env, "always"))
673 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
674 else if (env && !strcmp(env, "none"))
675 gBufMgr->lock_type = LOCK_TRY_NEVER;
676 else if (env && !strcmp(env, "once"))
677 gBufMgr->lock_type = LOCK_TRY_ONCE;
679 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
681 TBM_DBG("BUFMGR_LOCK_TYPE=%s\n",
682 env ? env : "default:once");
684 TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
686 /* intialize bo_list */
687 LIST_INITHEAD(&gBufMgr->bo_list);
689 /* intialize surf_list */
690 LIST_INITHEAD(&gBufMgr->surf_list);
692 /* intialize surf_list */
693 LIST_INITHEAD(&gBufMgr->surf_queue_list);
695 /* intialize debug_key_list */
696 LIST_INITHEAD(&gBufMgr->debug_key_list);
698 #ifdef TBM_BUFMGR_INIT_TIME
700 gettimeofday(&end_tv, NULL);
701 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)));
704 pthread_mutex_unlock(&gLock);
710 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
712 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
717 tbm_surface_h surf = NULL;
718 tbm_surface_h tmp_surf = NULL;
720 pthread_mutex_lock(&gLock);
723 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
724 pthread_mutex_unlock(&gLock);
729 if (bufmgr->ref_count > 0) {
730 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
731 pthread_mutex_unlock(&gLock);
735 /* destroy bo_list */
736 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
737 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
738 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
745 /* destroy surf_list */
746 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
747 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
748 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
750 tbm_surface_destroy(surf);
754 /* destroy bufmgr priv */
755 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
756 bufmgr->backend->priv = NULL;
757 tbm_backend_free(bufmgr->backend);
758 bufmgr->backend = NULL;
760 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
762 dlclose(bufmgr->module_data);
771 pthread_mutex_unlock(&gLock);
775 tbm_bo_size(tbm_bo bo)
777 tbm_bufmgr bufmgr = NULL;
780 _tbm_bufmgr_mutex_lock();
782 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
783 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
787 size = bufmgr->backend->bo_size(bo);
789 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
791 _tbm_bufmgr_mutex_unlock();
797 tbm_bo_ref(tbm_bo bo)
799 _tbm_bufmgr_mutex_lock();
801 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
802 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
806 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
808 _tbm_bufmgr_mutex_unlock();
814 tbm_bo_unref(tbm_bo bo)
816 tbm_bufmgr bufmgr = NULL;
817 tbm_user_data *old_data = NULL, *tmp = NULL;
819 _tbm_bufmgr_mutex_lock();
821 TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
822 TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
826 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
828 if (bo->ref_cnt <= 0) {
829 _tbm_bufmgr_mutex_unlock();
834 if (bo->ref_cnt == 0) {
835 /* destory the user_data_list */
836 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
837 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
838 TBM_DBG("free user_data\n");
839 user_data_delete(old_data);
843 while (bo->lock_cnt > 0) {
844 TBM_LOG_E("error lock_cnt:%d\n",
850 /* call the bo_free */
851 bufmgr->backend->bo_free(bo);
854 LIST_DEL(&bo->item_link);
860 _tbm_bufmgr_mutex_unlock();
864 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
867 void *bo_priv = NULL;
869 _tbm_bufmgr_mutex_lock();
871 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
872 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
873 TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
875 bo = calloc(1, sizeof(struct _tbm_bo));
877 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n",
878 size, _tbm_flag_to_str(flags));
879 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
880 _tbm_bufmgr_mutex_unlock();
884 _tbm_util_check_bo_cnt(bufmgr);
889 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
891 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n",
892 size, _tbm_flag_to_str(flags));
893 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
895 _tbm_bufmgr_mutex_unlock();
903 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
904 _tbm_flag_to_str(bo->flags));
906 LIST_INITHEAD(&bo->user_data_list);
908 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
910 _tbm_bufmgr_mutex_unlock();
916 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
921 void *bo_priv = NULL;
923 _tbm_bufmgr_mutex_lock();
925 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
926 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
928 if (!bufmgr->backend->bo_import) {
929 _tbm_bufmgr_mutex_unlock();
933 _tbm_util_check_bo_cnt(bufmgr);
935 bo = calloc(1, sizeof(struct _tbm_bo));
937 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
938 _tbm_bufmgr_mutex_unlock();
944 bo_priv = bufmgr->backend->bo_import(bo, key);
946 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
947 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
949 _tbm_bufmgr_mutex_unlock();
953 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
954 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
955 if (bo2->priv == bo_priv) {
956 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
957 bo2, bo2->ref_cnt, key,
958 _tbm_flag_to_str(bo2->flags));
961 _tbm_bufmgr_mutex_unlock();
972 if (bufmgr->backend->bo_get_flags)
973 bo->flags = bufmgr->backend->bo_get_flags(bo);
975 bo->flags = TBM_BO_DEFAULT;
977 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
978 bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
980 LIST_INITHEAD(&bo->user_data_list);
982 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
984 _tbm_bufmgr_mutex_unlock();
990 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
995 void *bo_priv = NULL;
997 _tbm_bufmgr_mutex_lock();
999 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1000 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
1002 if (!bufmgr->backend->bo_import_fd) {
1003 _tbm_bufmgr_mutex_unlock();
1007 _tbm_util_check_bo_cnt(bufmgr);
1009 bo = calloc(1, sizeof(struct _tbm_bo));
1011 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1012 _tbm_bufmgr_mutex_unlock();
1016 bo->bufmgr = bufmgr;
1018 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1020 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1021 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
1023 _tbm_bufmgr_mutex_unlock();
1027 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1028 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
1029 if (bo2->priv == bo_priv) {
1030 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1031 bo2, bo2->ref_cnt, fd,
1032 _tbm_flag_to_str(bo2->flags));
1035 _tbm_bufmgr_mutex_unlock();
1046 if (bufmgr->backend->bo_get_flags)
1047 bo->flags = bufmgr->backend->bo_get_flags(bo);
1049 bo->flags = TBM_BO_DEFAULT;
1051 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1052 bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1054 LIST_INITHEAD(&bo->user_data_list);
1056 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1058 _tbm_bufmgr_mutex_unlock();
1064 tbm_bo_export(tbm_bo bo)
1066 tbm_bufmgr bufmgr = NULL;
1069 _tbm_bufmgr_mutex_lock();
1071 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1072 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1076 if (!bufmgr->backend->bo_export) {
1077 _tbm_bufmgr_mutex_unlock();
1081 ret = bufmgr->backend->bo_export(bo);
1083 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1084 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1085 _tbm_bufmgr_mutex_unlock();
1089 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
1091 _tbm_bufmgr_mutex_unlock();
1097 tbm_bo_export_fd(tbm_bo bo)
1099 tbm_bufmgr bufmgr = NULL;
1102 _tbm_bufmgr_mutex_lock();
1104 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), -1);
1105 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1109 if (!bufmgr->backend->bo_export_fd) {
1110 _tbm_bufmgr_mutex_unlock();
1114 ret = bufmgr->backend->bo_export_fd(bo);
1116 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1117 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1118 _tbm_bufmgr_mutex_unlock();
1122 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1124 _tbm_bufmgr_mutex_unlock();
1130 tbm_bo_get_handle(tbm_bo bo, int device)
1132 tbm_bufmgr bufmgr = NULL;
1133 tbm_bo_handle bo_handle;
1135 _tbm_bufmgr_mutex_lock();
1137 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1138 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1142 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1143 if (bo_handle.ptr == NULL) {
1144 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1145 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1146 _tbm_bufmgr_mutex_unlock();
1147 return (tbm_bo_handle) NULL;
1150 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1152 _tbm_bufmgr_mutex_unlock();
1158 tbm_bo_map(tbm_bo bo, int device, int opt)
1160 tbm_bufmgr bufmgr = NULL;
1161 tbm_bo_handle bo_handle;
1163 _tbm_bufmgr_mutex_lock();
1165 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1166 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1170 if (!_tbm_bo_lock(bo, device, opt)) {
1171 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1172 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1173 _tbm_bufmgr_mutex_unlock();
1174 return (tbm_bo_handle) NULL;
1177 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1178 if (bo_handle.ptr == NULL) {
1179 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1180 TBM_TRACE("error: fail to map bo:%p\n", bo);
1182 _tbm_bufmgr_mutex_unlock();
1183 return (tbm_bo_handle) NULL;
1186 /* increase the map_count */
1189 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1191 _tbm_bufmgr_mutex_unlock();
1197 tbm_bo_unmap(tbm_bo bo)
1199 tbm_bufmgr bufmgr = NULL;
1202 _tbm_bufmgr_mutex_lock();
1204 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1205 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1209 ret = bufmgr->backend->bo_unmap(bo);
1211 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1212 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1213 _tbm_bufmgr_mutex_unlock();
1217 /* decrease the map_count */
1220 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1224 _tbm_bufmgr_mutex_unlock();
1230 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1232 tbm_bufmgr bufmgr = NULL;
1235 _tbm_bufmgr_mutex_lock();
1237 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1238 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1239 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1243 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1245 if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1246 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1247 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1248 _tbm_bufmgr_mutex_unlock();
1252 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1255 bo1->priv = bo2->priv;
1258 _tbm_bufmgr_mutex_unlock();
1264 tbm_bo_locked(tbm_bo bo)
1266 tbm_bufmgr bufmgr = NULL;
1268 _tbm_bufmgr_mutex_lock();
1270 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1271 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1275 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1276 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1277 _tbm_bufmgr_mutex_unlock();
1281 if (bo->lock_cnt > 0) {
1282 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1283 _tbm_bufmgr_mutex_unlock();
1287 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1288 _tbm_bufmgr_mutex_unlock();
1294 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1295 tbm_data_free data_free_func)
1297 tbm_user_data *data;
1299 _tbm_bufmgr_mutex_lock();
1301 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1302 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1304 /* check if the data according to the key exist if so, return false. */
1305 data = user_data_lookup(&bo->user_data_list, key);
1307 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1308 _tbm_bufmgr_mutex_unlock();
1312 data = user_data_create(key, data_free_func);
1314 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1315 _tbm_bufmgr_mutex_unlock();
1319 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1321 LIST_ADD(&data->item_link, &bo->user_data_list);
1323 _tbm_bufmgr_mutex_unlock();
1329 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1331 tbm_user_data *old_data;
1333 _tbm_bufmgr_mutex_lock();
1335 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1336 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1338 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1339 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1340 _tbm_bufmgr_mutex_unlock();
1344 old_data = user_data_lookup(&bo->user_data_list, key);
1346 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1347 _tbm_bufmgr_mutex_unlock();
1351 if (old_data->data && old_data->free_func)
1352 old_data->free_func(old_data->data);
1354 old_data->data = data;
1356 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1358 _tbm_bufmgr_mutex_unlock();
1364 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1366 tbm_user_data *old_data;
1368 _tbm_bufmgr_mutex_lock();
1370 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1371 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1373 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1374 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1375 _tbm_bufmgr_mutex_unlock();
1379 old_data = user_data_lookup(&bo->user_data_list, key);
1381 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1383 _tbm_bufmgr_mutex_unlock();
1387 *data = old_data->data;
1389 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1391 _tbm_bufmgr_mutex_unlock();
1397 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1399 tbm_user_data *old_data = (void *)0;
1401 _tbm_bufmgr_mutex_lock();
1403 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1404 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1406 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1407 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1408 _tbm_bufmgr_mutex_unlock();
1412 old_data = user_data_lookup(&bo->user_data_list, key);
1414 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1415 _tbm_bufmgr_mutex_unlock();
1419 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1421 user_data_delete(old_data);
1423 _tbm_bufmgr_mutex_unlock();
1429 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1431 int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1433 _tbm_bufmgr_mutex_lock();
1435 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1436 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1438 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1440 capabilities = bufmgr->capabilities;
1442 _tbm_bufmgr_mutex_unlock();
1444 return capabilities;
1448 tbm_bo_get_flags(tbm_bo bo)
1452 _tbm_bufmgr_mutex_lock();
1454 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1455 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1459 TBM_TRACE("bo(%p)\n", bo);
1461 _tbm_bufmgr_mutex_unlock();
1466 /* LCOV_EXCL_START */
1468 tbm_get_last_error(void)
1470 return tbm_last_error;
1474 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1476 tbm_bo bo = NULL, tmp_bo = NULL;
1478 tbm_surface_h surf = NULL, tmp_surf = NULL;
1481 char app_name[255] = {0,};
1482 unsigned int pid = 0;
1483 char title[255] = {0,};
1484 char data[255] = {0,};
1485 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1487 pthread_mutex_lock(&gLock);
1489 if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
1490 TBM_LOG_E("invalid bufmgr\n");
1491 pthread_mutex_unlock(&gLock);
1496 _tbm_util_get_appname_from_pid(getpid(), app_name);
1497 _tbm_util_get_appname_brief(app_name);
1498 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1499 app_name, getpid());
1500 memset(app_name, 0x0, 255 * sizeof(char));
1501 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1502 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1503 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1504 strncat(title, " ", 3);
1505 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1509 TBM_DEBUG("[tbm_surface information]\n");
1510 TBM_DEBUG("%s\n", title);
1511 /* show the tbm_surface information in surf_list */
1512 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1515 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1516 pid = _tbm_surface_internal_get_debug_pid(surf);
1518 /* if pid is null, set the self_pid */
1522 _tbm_util_get_appname_from_pid(pid, app_name);
1523 _tbm_util_get_appname_brief(app_name);
1525 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1532 surf->info.size / 1024,
1536 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1539 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1540 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1541 strncat(data, " ", 3);
1543 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1545 strncat(data, value, strlen(value) + 1);
1547 strncat(data, "none", 5);
1550 TBM_DEBUG("%s\n", data);
1552 for (i = 0; i < surf->num_bos; i++) {
1553 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1555 surf->bos[i]->ref_cnt,
1556 bufmgr->backend->bo_size(surf->bos[i]) / 1024);
1559 memset(app_name, 0x0, 255 * sizeof(char));
1562 TBM_DEBUG("no tbm_surfaces.\n");
1566 TBM_DEBUG("[tbm_bo information]\n");
1567 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1569 /* show the tbm_bo information in bo_list */
1570 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1571 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1572 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1576 bufmgr->backend->bo_size(bo) / 1024,
1583 TBM_DEBUG("no tbm_bos.\n");
1587 TBM_DEBUG("===============================================================\n");
1589 pthread_mutex_unlock(&gLock);
1593 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1595 _tbm_bufmgr_mutex_lock();
1597 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1598 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1601 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1605 _tbm_bufmgr_mutex_unlock();
1609 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1613 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1614 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1616 pthread_mutex_lock(&gLock);
1619 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1620 TBM_LOG_I("No tbm_surface.\n");
1621 pthread_mutex_unlock(&gLock);
1625 tbm_surface_internal_dump_start(path, w, h, count);
1627 } else if (onoff == 0) {
1628 tbm_surface_internal_dump_end();
1631 pthread_mutex_unlock(&gLock);
1635 pthread_mutex_unlock(&gLock);
1640 tbm_bufmgr_debug_dump_all(char *path)
1642 int w = 0, h = 0, count = 0;
1643 tbm_surface_h surface = NULL, tmp = NULL;
1645 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1646 TBM_LOG_D("path=%s\n", path);
1648 pthread_mutex_lock(&gLock);
1650 count = _tbm_util_get_max_surface_size(&w, &h);
1652 TBM_LOG_I("No tbm_surface.\n");
1653 pthread_mutex_unlock(&gLock);
1657 tbm_surface_internal_dump_start(path, w, h, count);
1659 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1660 tbm_surface_internal_dump_buffer(surface, "dump_all");
1663 tbm_surface_internal_dump_end();
1665 pthread_mutex_unlock(&gLock);
1670 /* internal function */
1672 _tbm_bufmgr_get_bufmgr(void)
1678 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1680 _tbm_bufmgr_mutex_lock();
1682 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1683 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1685 bo->surface = surface;
1687 _tbm_bufmgr_mutex_unlock();
1693 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1697 _tbm_bufmgr_mutex_lock();
1699 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1701 if (!bufmgr->backend->bufmgr_bind_native_display) {
1702 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1703 _tbm_bufmgr_mutex_unlock();
1707 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1709 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1710 _tbm_bufmgr_mutex_unlock();
1714 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1716 _tbm_bufmgr_mutex_unlock();
1720 /* LCOV_EXCL_STOP */