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 PREFIX_LIB "libtbm_"
61 #define SUFFIX_LIB ".so"
62 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
64 /* values to indicate unspecified fields in XF86ModReqInfo. */
65 #define MAJOR_UNSPEC 0xFF
66 #define MINOR_UNSPEC 0xFF
67 #define PATCH_UNSPEC 0xFFFF
68 #define ABI_VERS_UNSPEC 0xFFFFFFFF
70 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
71 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
72 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
73 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
74 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
77 #define TBM_BUFMGR_RETURN_IF_FAIL(cond) {\
79 TBM_LOG_E("'%s' failed.\n", #cond);\
80 _tbm_bufmgr_mutex_unlock();\
85 #define TBM_BUFMGR_RETURN_VAL_IF_FAIL(cond, val) {\
87 TBM_LOG_E("'%s' failed.\n", #cond);\
88 _tbm_bufmgr_mutex_unlock();\
100 _tbm_set_last_result(tbm_error_e err)
102 tbm_last_error = err;
106 _tbm_bufmgr_mutex_init(void)
108 static bool tbm_bufmgr_mutex_init = false;
110 if (tbm_bufmgr_mutex_init)
113 if (pthread_mutex_init(&tbm_bufmgr_lock, NULL)) {
114 TBM_LOG_E("fail: tbm_bufmgr mutex init\n");
118 tbm_bufmgr_mutex_init = true;
124 _tbm_bufmgr_mutex_lock(void)
126 if (!_tbm_bufmgr_mutex_init())
129 pthread_mutex_lock(&tbm_bufmgr_lock);
133 _tbm_bufmgr_mutex_unlock(void)
135 pthread_mutex_unlock(&tbm_bufmgr_lock);
138 char * tbm_flag_to_str(int f)
140 static char str[255];
142 if (f == TBM_BO_DEFAULT)
143 snprintf(str, 255, "DEFAULT\n");
145 if (f & TBM_BO_SCANOUT)
146 c = snprintf(&str[c], 255, "SCANOUT,");
147 if (f & TBM_BO_NONCACHABLE)
148 c = snprintf(&str[c], 255, "NONCACHABLE,");
150 c = snprintf(&str[c], 255, "WC");
155 /* LCOV_EXCL_START */
156 static int last_chk_bo_cnt = 0;
158 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
160 if (bufmgr->bo_cnt >= 500 && ((bufmgr->bo_cnt % 20) == 0)) {
161 if (bufmgr->bo_cnt > last_chk_bo_cnt) {
162 TBM_DEBUG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
163 tbm_bufmgr_debug_show(bufmgr);
164 last_chk_bo_cnt = bufmgr->bo_cnt;
170 _tbm_util_get_max_surface_size(int * w, int * h)
173 tbm_surface_h surface = NULL, tmp = NULL;
174 tbm_surface_info_s info;
182 if (!LIST_IS_EMPTY(&gBufMgr->surf_list)) {
183 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
184 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
186 if (*w < info.width) *w = info.width;
187 if (*h < info.height) *h = info.height;
196 _tbm_util_get_appname_brief(char *brief)
200 char temp[255] = {0,};
201 char *saveptr = NULL;
203 token = strtok_r(brief, delim, &saveptr);
205 while (token != NULL) {
206 memset(temp, 0x00, 255 * sizeof(char));
207 strncpy(temp, token, 254 * sizeof(char));
208 token = strtok_r(NULL, delim, &saveptr);
211 snprintf(brief, sizeof(temp), "%s", temp);
215 _tbm_util_get_appname_from_pid(long pid, char *str)
220 char fn_cmdline[255] = {0,};
221 char cmdline[255] = {0,};
223 snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", app_pid);
225 fp = fopen(fn_cmdline, "r");
227 fprintf(stderr, "cannot file open /proc/%ld/cmdline", app_pid);
231 if (!fgets(cmdline, 255, fp)) {
232 fprintf(stderr, "fail to get appname for pid(%ld)\n", app_pid);
238 len = strlen(cmdline);
240 memset(cmdline, 0x00, 255);
244 snprintf(str, sizeof(cmdline), "%s", cmdline);
249 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
251 tbm_user_data *user_data = NULL;
252 tbm_user_data *old_data = NULL, *tmp = NULL;
254 if (!LIST_IS_EMPTY(user_data_list)) {
255 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, user_data_list, item_link) {
256 if (old_data->key == key) {
257 user_data = old_data;
267 *user_data_create(unsigned long key, tbm_data_free data_free_func)
269 tbm_user_data *user_data = NULL;
271 user_data = calloc(1, sizeof(tbm_user_data));
275 user_data->key = key;
276 user_data->free_func = data_free_func;
277 user_data->data = (void *)0;
283 user_data_delete(tbm_user_data *user_data)
285 if (user_data->data && user_data->free_func)
286 user_data->free_func(user_data->data);
288 LIST_DEL(&user_data->item_link);
294 _bo_lock(tbm_bo bo, int device, int opt)
296 tbm_bufmgr bufmgr = bo->bufmgr;
299 if (bufmgr->backend->bo_lock)
300 ret = bufmgr->backend->bo_lock(bo, device, opt);
308 _bo_unlock(tbm_bo bo)
310 tbm_bufmgr bufmgr = bo->bufmgr;
312 if (bufmgr->backend->bo_unlock)
313 bufmgr->backend->bo_unlock(bo);
317 _tbm_bo_lock(tbm_bo bo, int device, int opt)
319 tbm_bufmgr bufmgr = NULL;
328 /* do not try to lock the bo */
329 if (bufmgr->lock_type == LOCK_TRY_NEVER)
332 if (bo->lock_cnt < 0) {
333 TBM_LOG_E("error bo:%p LOCK_CNT=%d\n",
338 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
339 if (bo->lock_cnt == 0) {
340 _tbm_bufmgr_mutex_unlock();
341 ret = _bo_lock(bo, device, opt);
342 _tbm_bufmgr_mutex_lock();
347 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
348 _tbm_bufmgr_mutex_unlock();
349 ret = _bo_lock(bo, device, opt);
350 _tbm_bufmgr_mutex_lock();
354 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
358 DBG_LOCK(">> LOCK bo:%p(%d->%d)\n",
359 bo, old, bo->lock_cnt);
365 _tbm_bo_unlock(tbm_bo bo)
367 tbm_bufmgr bufmgr = NULL;
376 /* do not try to unlock the bo */
377 if (bufmgr->lock_type == LOCK_TRY_NEVER)
381 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
382 if (bo->lock_cnt > 0) {
384 if (bo->lock_cnt == 0)
387 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
388 if (bo->lock_cnt > 0) {
393 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
397 if (bo->lock_cnt < 0)
400 DBG_LOCK(">> UNLOCK bo:%p(%d->%d)\n",
401 bo, old, bo->lock_cnt);
405 _tbm_bo_is_valid(tbm_bo bo)
407 tbm_bo old_data = NULL, tmp = NULL;
412 if (gBufMgr == NULL) {
413 TBM_LOG_E("error tbm_bufmgr was deinited\n");
417 if (!LIST_IS_EMPTY(&gBufMgr->bo_list)) {
418 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &gBufMgr->bo_list, item_link) {
427 /* LCOV_EXCL_START */
429 _check_version(TBMModuleVersionInfo *data)
434 abimaj = GET_ABI_MAJOR(data->abiversion);
435 abimin = GET_ABI_MINOR(data->abiversion);
437 DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
438 data->modname ? data->modname : "UNKNOWN!",
439 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
441 vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
442 vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
444 DBG("TBM ABI version %d.%d\n",
447 if (abimaj != vermaj) {
448 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
451 } else if (abimin > vermin) {
452 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
460 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
462 char path[PATH_MAX] = { 0, };
463 TBMModuleData *initdata = NULL;
466 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
468 module_data = dlopen(path, RTLD_LAZY);
470 TBM_LOG_E("failed to load module: %s(%s)\n",
475 initdata = dlsym(module_data, "tbmModuleData");
478 TBMModuleVersionInfo *vers;
480 vers = initdata->vers;
481 init = initdata->init;
484 if (!_check_version(vers)) {
485 dlclose(module_data);
489 TBM_LOG_E("Error: module does not supply version information.\n");
491 dlclose(module_data);
496 if (!init(bufmgr, fd)) {
497 TBM_LOG_E("Fail to init module(%s)\n",
499 dlclose(module_data);
503 if (!bufmgr->backend || !bufmgr->backend->priv) {
504 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n",
506 dlclose(module_data);
510 TBM_LOG_E("Error: module does not supply init symbol.\n");
511 dlclose(module_data);
515 TBM_LOG_E("Error: module does not have data object.\n");
516 dlclose(module_data);
520 bufmgr->module_data = module_data;
522 DBG("Success to load module(%s)\n",
529 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
531 struct dirent **namelist;
532 const char *p = NULL;
536 /* load bufmgr priv from default lib */
537 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
539 /* load bufmgr priv from configured path */
541 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
543 TBM_LOG_E("no files : %s\n",
547 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
548 p = strstr(namelist[n]->d_name, SUFFIX_LIB);
549 if (p && !strcmp(p, SUFFIX_LIB))
550 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
563 tbm_bufmgr_init(int fd)
567 pthread_mutex_lock(&gLock);
569 /* LCOV_EXCL_START */
571 env = getenv("TBM_DLOG");
574 TBM_LOG_D("TBM_DLOG=%s\n", env);
581 env = getenv("TBM_DEBUG");
584 TBM_LOG_D("TBM_DEBUG=%s\n", env);
591 env = getenv("TBM_TRACE");
594 TBM_LOG_D("TBM_TRACE=%s\n", env);
601 /* initialize buffer manager */
603 gBufMgr->ref_count++;
604 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
605 pthread_mutex_unlock(&gLock);
609 DBG("bufmgr init\n");
611 /* allocate bufmgr */
612 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
614 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
615 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
616 pthread_mutex_unlock(&gLock);
622 /* load bufmgr priv from env */
623 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
624 /* LCOV_EXCL_START */
625 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
626 TBM_LOG_E("error : Fail to load bufmgr backend\n");
629 pthread_mutex_unlock(&gLock);
634 /* log for tbm backend_flag */
635 DBG("backend flag:%x:", gBufMgr->backend->flags);
638 gBufMgr->ref_count = 1;
640 DBG("create tizen bufmgr:%p ref_count:%d\n",
641 gBufMgr, gBufMgr->ref_count);
643 /* setup the lock_type */
644 env = getenv("BUFMGR_LOCK_TYPE");
645 if (env && !strcmp(env, "always"))
646 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
647 else if (env && !strcmp(env, "none"))
648 gBufMgr->lock_type = LOCK_TRY_NEVER;
649 else if (env && !strcmp(env, "once"))
650 gBufMgr->lock_type = LOCK_TRY_ONCE;
652 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
654 DBG("BUFMGR_LOCK_TYPE=%s\n",
655 env ? env : "default:once");
657 TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
659 /* intialize bo_list */
660 LIST_INITHEAD(&gBufMgr->bo_list);
662 /* intialize surf_list */
663 LIST_INITHEAD(&gBufMgr->surf_list);
665 /* intialize debug_key_list */
666 LIST_INITHEAD(&gBufMgr->debug_key_list);
668 pthread_mutex_unlock(&gLock);
674 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
676 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
681 tbm_surface_h surf = NULL;
682 tbm_surface_h tmp_surf = NULL;
684 pthread_mutex_lock(&gLock);
687 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
688 pthread_mutex_unlock(&gLock);
693 if (bufmgr->ref_count > 0) {
694 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
695 pthread_mutex_unlock(&gLock);
699 /* destroy bo_list */
700 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
701 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
702 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
709 /* destroy surf_list */
710 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
711 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
712 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
714 tbm_surface_destroy(surf);
718 /* destroy bufmgr priv */
719 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
720 bufmgr->backend->priv = NULL;
721 tbm_backend_free(bufmgr->backend);
722 bufmgr->backend = NULL;
724 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
726 dlclose(bufmgr->module_data);
735 pthread_mutex_unlock(&gLock);
739 tbm_bo_size(tbm_bo bo)
741 tbm_bufmgr bufmgr = NULL;
744 _tbm_bufmgr_mutex_lock();
746 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
747 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
751 size = bufmgr->backend->bo_size(bo);
753 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
755 _tbm_bufmgr_mutex_unlock();
761 tbm_bo_ref(tbm_bo bo)
763 _tbm_bufmgr_mutex_lock();
765 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
766 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
770 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
772 _tbm_bufmgr_mutex_unlock();
778 tbm_bo_unref(tbm_bo bo)
780 tbm_bufmgr bufmgr = NULL;
781 tbm_user_data *old_data = NULL, *tmp = NULL;
783 _tbm_bufmgr_mutex_lock();
785 TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
786 TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
790 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
792 if (bo->ref_cnt <= 0) {
793 _tbm_bufmgr_mutex_unlock();
798 if (bo->ref_cnt == 0) {
799 /* destory the user_data_list */
800 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
801 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
802 DBG("free user_data\n");
803 user_data_delete(old_data);
807 if (bo->lock_cnt > 0) {
808 TBM_LOG_E("error lock_cnt:%d\n",
813 /* call the bo_free */
814 bufmgr->backend->bo_free(bo);
817 LIST_DEL(&bo->item_link);
823 _tbm_bufmgr_mutex_unlock();
827 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
830 void *bo_priv = NULL;
832 _tbm_bufmgr_mutex_lock();
834 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
835 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
836 TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
838 bo = calloc(1, sizeof(struct _tbm_bo));
840 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
841 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
842 _tbm_bufmgr_mutex_unlock();
846 _tbm_util_check_bo_cnt(bufmgr);
851 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
853 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
854 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
856 _tbm_bufmgr_mutex_unlock();
864 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
866 LIST_INITHEAD(&bo->user_data_list);
868 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
870 _tbm_bufmgr_mutex_unlock();
876 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
881 void *bo_priv = NULL;
883 _tbm_bufmgr_mutex_lock();
885 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
886 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
888 if (!bufmgr->backend->bo_import) {
889 _tbm_bufmgr_mutex_unlock();
893 _tbm_util_check_bo_cnt(bufmgr);
895 bo = calloc(1, sizeof(struct _tbm_bo));
897 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
898 _tbm_bufmgr_mutex_unlock();
906 bo_priv = bufmgr->backend->bo_import(bo, key);
908 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
909 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
911 _tbm_bufmgr_mutex_unlock();
915 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
916 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
917 if (bo2->priv == bo_priv) {
918 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
919 bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
922 _tbm_bufmgr_mutex_unlock();
931 if (bufmgr->backend->bo_get_flags)
932 bo->flags = bufmgr->backend->bo_get_flags(bo);
934 bo->flags = TBM_BO_DEFAULT;
936 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
937 bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
939 LIST_INITHEAD(&bo->user_data_list);
941 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
943 _tbm_bufmgr_mutex_unlock();
949 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
954 void *bo_priv = NULL;
956 _tbm_bufmgr_mutex_lock();
958 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
959 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
961 if (!bufmgr->backend->bo_import_fd) {
962 _tbm_bufmgr_mutex_unlock();
966 _tbm_util_check_bo_cnt(bufmgr);
968 bo = calloc(1, sizeof(struct _tbm_bo));
970 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
971 _tbm_bufmgr_mutex_unlock();
979 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
981 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
982 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
984 _tbm_bufmgr_mutex_unlock();
988 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
989 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
990 if (bo2->priv == bo_priv) {
991 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
992 bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
995 _tbm_bufmgr_mutex_unlock();
1004 if (bufmgr->backend->bo_get_flags)
1005 bo->flags = bufmgr->backend->bo_get_flags(bo);
1007 bo->flags = TBM_BO_DEFAULT;
1009 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1010 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
1012 LIST_INITHEAD(&bo->user_data_list);
1014 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1016 _tbm_bufmgr_mutex_unlock();
1022 tbm_bo_export(tbm_bo bo)
1024 tbm_bufmgr bufmgr = NULL;
1027 _tbm_bufmgr_mutex_lock();
1029 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1030 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1034 if (!bufmgr->backend->bo_export) {
1035 _tbm_bufmgr_mutex_unlock();
1039 ret = bufmgr->backend->bo_export(bo);
1041 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1042 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1043 _tbm_bufmgr_mutex_unlock();
1047 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
1049 _tbm_bufmgr_mutex_unlock();
1055 tbm_bo_export_fd(tbm_bo bo)
1057 tbm_bufmgr bufmgr = NULL;
1060 _tbm_bufmgr_mutex_lock();
1062 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1063 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1067 if (!bufmgr->backend->bo_export_fd) {
1068 _tbm_bufmgr_mutex_unlock();
1072 ret = bufmgr->backend->bo_export_fd(bo);
1074 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1075 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1076 _tbm_bufmgr_mutex_unlock();
1080 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1082 _tbm_bufmgr_mutex_unlock();
1088 tbm_bo_get_handle(tbm_bo bo, int device)
1090 tbm_bufmgr bufmgr = NULL;
1091 tbm_bo_handle bo_handle;
1093 _tbm_bufmgr_mutex_lock();
1095 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1096 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1100 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1101 if (bo_handle.ptr == NULL) {
1102 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1103 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1104 _tbm_bufmgr_mutex_unlock();
1105 return (tbm_bo_handle) NULL;
1108 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1110 _tbm_bufmgr_mutex_unlock();
1116 tbm_bo_map(tbm_bo bo, int device, int opt)
1118 tbm_bufmgr bufmgr = NULL;
1119 tbm_bo_handle bo_handle;
1121 _tbm_bufmgr_mutex_lock();
1123 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1124 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1128 if (!_tbm_bo_lock(bo, device, opt)) {
1129 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1130 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1131 _tbm_bufmgr_mutex_unlock();
1132 return (tbm_bo_handle) NULL;
1135 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1136 if (bo_handle.ptr == NULL) {
1137 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1138 TBM_TRACE("error: fail to map bo:%p\n", bo);
1140 _tbm_bufmgr_mutex_unlock();
1141 return (tbm_bo_handle) NULL;
1144 /* increase the map_count */
1147 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1149 _tbm_bufmgr_mutex_unlock();
1155 tbm_bo_unmap(tbm_bo bo)
1157 tbm_bufmgr bufmgr = NULL;
1160 _tbm_bufmgr_mutex_lock();
1162 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1163 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1167 ret = bufmgr->backend->bo_unmap(bo);
1169 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1170 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1171 _tbm_bufmgr_mutex_unlock();
1175 /* decrease the map_count */
1178 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1182 _tbm_bufmgr_mutex_unlock();
1188 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1190 tbm_bufmgr bufmgr = NULL;
1193 _tbm_bufmgr_mutex_lock();
1195 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1196 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1197 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1201 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1203 if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1204 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1205 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1206 _tbm_bufmgr_mutex_unlock();
1210 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1213 bo1->priv = bo2->priv;
1216 _tbm_bufmgr_mutex_unlock();
1222 tbm_bo_locked(tbm_bo bo)
1224 tbm_bufmgr bufmgr = NULL;
1226 _tbm_bufmgr_mutex_lock();
1228 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1229 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1233 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1234 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1235 _tbm_bufmgr_mutex_unlock();
1239 if (bo->lock_cnt > 0) {
1240 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1241 _tbm_bufmgr_mutex_unlock();
1245 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1246 _tbm_bufmgr_mutex_unlock();
1252 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1253 tbm_data_free data_free_func)
1255 tbm_user_data *data;
1257 _tbm_bufmgr_mutex_lock();
1259 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1260 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1262 /* check if the data according to the key exist if so, return false. */
1263 data = user_data_lookup(&bo->user_data_list, key);
1265 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1266 _tbm_bufmgr_mutex_unlock();
1270 data = user_data_create(key, data_free_func);
1272 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1273 _tbm_bufmgr_mutex_unlock();
1277 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1279 LIST_ADD(&data->item_link, &bo->user_data_list);
1281 _tbm_bufmgr_mutex_unlock();
1287 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1289 tbm_user_data *old_data;
1291 _tbm_bufmgr_mutex_lock();
1293 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1294 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1296 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1297 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1298 _tbm_bufmgr_mutex_unlock();
1302 old_data = user_data_lookup(&bo->user_data_list, key);
1304 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1305 _tbm_bufmgr_mutex_unlock();
1309 if (old_data->data && old_data->free_func)
1310 old_data->free_func(old_data->data);
1312 old_data->data = data;
1314 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1316 _tbm_bufmgr_mutex_unlock();
1322 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1324 tbm_user_data *old_data;
1326 _tbm_bufmgr_mutex_lock();
1328 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1329 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1331 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1332 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1333 _tbm_bufmgr_mutex_unlock();
1337 old_data = user_data_lookup(&bo->user_data_list, key);
1339 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1341 _tbm_bufmgr_mutex_unlock();
1345 *data = old_data->data;
1347 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1349 _tbm_bufmgr_mutex_unlock();
1355 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1357 tbm_user_data *old_data = (void *)0;
1359 _tbm_bufmgr_mutex_lock();
1361 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1362 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1364 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1365 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1366 _tbm_bufmgr_mutex_unlock();
1370 old_data = user_data_lookup(&bo->user_data_list, key);
1372 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1373 _tbm_bufmgr_mutex_unlock();
1377 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1379 user_data_delete(old_data);
1381 _tbm_bufmgr_mutex_unlock();
1387 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1389 int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1391 _tbm_bufmgr_mutex_lock();
1393 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1394 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1396 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1398 capabilities = bufmgr->capabilities;
1400 _tbm_bufmgr_mutex_unlock();
1402 return capabilities;
1406 tbm_bo_get_flags(tbm_bo bo)
1410 _tbm_bufmgr_mutex_lock();
1412 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1413 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1417 TBM_TRACE("bo(%p)\n", bo);
1419 _tbm_bufmgr_mutex_unlock();
1424 /* LCOV_EXCL_START */
1426 tbm_get_last_error(void)
1428 return tbm_last_error;
1432 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1434 tbm_bo bo = NULL, tmp_bo = NULL;
1436 tbm_surface_h surf = NULL, tmp_surf = NULL;
1439 char app_name[255] = {0,};
1440 unsigned int pid = 0;
1441 char title[255] = {0,};
1442 char data[255] = {0,};
1443 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1445 _tbm_bufmgr_mutex_lock();
1447 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1448 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1451 _tbm_util_get_appname_from_pid(getpid(), app_name);
1452 _tbm_util_get_appname_brief(app_name);
1453 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1454 app_name, getpid());
1455 memset(app_name, 0x0, 255 * sizeof(char));
1456 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1457 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1458 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1459 strncat(title, " ", 2);
1460 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1464 TBM_DEBUG("[tbm_surface information]\n");
1465 TBM_DEBUG("%s\n", title);
1466 /* show the tbm_surface information in surf_list */
1467 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1470 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1471 pid = _tbm_surface_internal_get_debug_pid(surf);
1473 /* if pid is null, set the self_pid */
1477 _tbm_util_get_appname_from_pid(pid, app_name);
1478 _tbm_util_get_appname_brief(app_name);
1480 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1487 surf->info.size / 1024,
1491 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1494 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1495 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1496 strncat(data, " ", 2);
1498 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1500 strncat(data, value, strlen(value) + 1);
1502 strncat(data, "none", strlen("none") + 1);
1505 TBM_DEBUG("%s\n", data);
1507 for (i = 0; i < surf->num_bos; i++) {
1508 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1510 surf->bos[i]->ref_cnt,
1511 tbm_bo_size(surf->bos[i]) / 1024);
1514 memset(app_name, 0x0, 255 * sizeof(char));
1517 TBM_DEBUG("no tbm_surfaces.\n");
1521 TBM_DEBUG("[tbm_bo information]\n");
1522 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1524 /* show the tbm_bo information in bo_list */
1525 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1526 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1527 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1531 tbm_bo_size(bo) / 1024,
1538 TBM_DEBUG("no tbm_bos.\n");
1542 TBM_DEBUG("===============================================================\n");
1544 _tbm_bufmgr_mutex_unlock();
1548 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1550 _tbm_bufmgr_mutex_lock();
1552 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1553 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1556 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1560 _tbm_bufmgr_mutex_unlock();
1564 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1568 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1569 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1571 pthread_mutex_lock(&gLock);
1574 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1575 TBM_LOG_I("No tbm_surface.\n");
1576 pthread_mutex_unlock(&gLock);
1580 tbm_surface_internal_dump_start(path, w, h, count);
1582 } else if (onoff == 0) {
1583 tbm_surface_internal_dump_end();
1586 pthread_mutex_unlock(&gLock);
1590 pthread_mutex_unlock(&gLock);
1595 tbm_bufmgr_debug_dump_all(char *path)
1597 int w = 0, h = 0, count = 0;
1598 tbm_surface_h surface = NULL, tmp = NULL;
1600 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1601 TBM_LOG_D("path=%s\n", path);
1603 pthread_mutex_lock(&gLock);
1605 count = _tbm_util_get_max_surface_size(&w, &h);
1607 TBM_LOG_I("No tbm_surface.\n");
1608 pthread_mutex_unlock(&gLock);
1612 tbm_surface_internal_dump_start(path, w, h, count);
1614 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1615 tbm_surface_internal_dump_buffer(surface, "dump_all");
1618 tbm_surface_internal_dump_end();
1620 pthread_mutex_unlock(&gLock);
1625 /* internal function */
1627 _tbm_bufmgr_get_bufmgr(void)
1633 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1635 _tbm_bufmgr_mutex_lock();
1637 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1638 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1640 bo->surface = surface;
1642 _tbm_bufmgr_mutex_unlock();
1648 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1652 _tbm_bufmgr_mutex_lock();
1654 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1656 if (!bufmgr->backend->bufmgr_bind_native_display) {
1657 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1658 _tbm_bufmgr_mutex_unlock();
1662 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1664 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1665 _tbm_bufmgr_mutex_unlock();
1669 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1671 _tbm_bufmgr_mutex_unlock();
1675 /* LCOV_EXCL_STOP */