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 surf_list */
666 LIST_INITHEAD(&gBufMgr->surf_queue_list);
668 /* intialize debug_key_list */
669 LIST_INITHEAD(&gBufMgr->debug_key_list);
671 pthread_mutex_unlock(&gLock);
677 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
679 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
684 tbm_surface_h surf = NULL;
685 tbm_surface_h tmp_surf = NULL;
687 pthread_mutex_lock(&gLock);
690 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
691 pthread_mutex_unlock(&gLock);
696 if (bufmgr->ref_count > 0) {
697 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
698 pthread_mutex_unlock(&gLock);
702 /* destroy bo_list */
703 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
704 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
705 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
712 /* destroy surf_list */
713 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
714 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
715 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
717 tbm_surface_destroy(surf);
721 /* destroy bufmgr priv */
722 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
723 bufmgr->backend->priv = NULL;
724 tbm_backend_free(bufmgr->backend);
725 bufmgr->backend = NULL;
727 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
729 dlclose(bufmgr->module_data);
738 pthread_mutex_unlock(&gLock);
742 tbm_bo_size(tbm_bo bo)
744 tbm_bufmgr bufmgr = NULL;
747 _tbm_bufmgr_mutex_lock();
749 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
750 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
754 size = bufmgr->backend->bo_size(bo);
756 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
758 _tbm_bufmgr_mutex_unlock();
764 tbm_bo_ref(tbm_bo bo)
766 _tbm_bufmgr_mutex_lock();
768 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
769 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
773 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
775 _tbm_bufmgr_mutex_unlock();
781 tbm_bo_unref(tbm_bo bo)
783 tbm_bufmgr bufmgr = NULL;
784 tbm_user_data *old_data = NULL, *tmp = NULL;
786 _tbm_bufmgr_mutex_lock();
788 TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
789 TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
793 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
795 if (bo->ref_cnt <= 0) {
796 _tbm_bufmgr_mutex_unlock();
801 if (bo->ref_cnt == 0) {
802 /* destory the user_data_list */
803 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
804 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
805 DBG("free user_data\n");
806 user_data_delete(old_data);
810 if (bo->lock_cnt > 0) {
811 TBM_LOG_E("error lock_cnt:%d\n",
816 /* call the bo_free */
817 bufmgr->backend->bo_free(bo);
820 LIST_DEL(&bo->item_link);
826 _tbm_bufmgr_mutex_unlock();
830 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
833 void *bo_priv = NULL;
835 _tbm_bufmgr_mutex_lock();
837 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
838 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
839 TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
841 bo = calloc(1, sizeof(struct _tbm_bo));
843 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
844 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
845 _tbm_bufmgr_mutex_unlock();
849 _tbm_util_check_bo_cnt(bufmgr);
854 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
856 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
857 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
859 _tbm_bufmgr_mutex_unlock();
867 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
869 LIST_INITHEAD(&bo->user_data_list);
871 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
873 _tbm_bufmgr_mutex_unlock();
879 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
884 void *bo_priv = NULL;
886 _tbm_bufmgr_mutex_lock();
888 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
889 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
891 if (!bufmgr->backend->bo_import) {
892 _tbm_bufmgr_mutex_unlock();
896 _tbm_util_check_bo_cnt(bufmgr);
898 bo = calloc(1, sizeof(struct _tbm_bo));
900 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
901 _tbm_bufmgr_mutex_unlock();
909 bo_priv = bufmgr->backend->bo_import(bo, key);
911 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
912 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
914 _tbm_bufmgr_mutex_unlock();
918 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
919 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
920 if (bo2->priv == bo_priv) {
921 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
922 bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
925 _tbm_bufmgr_mutex_unlock();
934 if (bufmgr->backend->bo_get_flags)
935 bo->flags = bufmgr->backend->bo_get_flags(bo);
937 bo->flags = TBM_BO_DEFAULT;
939 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
940 bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
942 LIST_INITHEAD(&bo->user_data_list);
944 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
946 _tbm_bufmgr_mutex_unlock();
952 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
957 void *bo_priv = NULL;
959 _tbm_bufmgr_mutex_lock();
961 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
962 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
964 if (!bufmgr->backend->bo_import_fd) {
965 _tbm_bufmgr_mutex_unlock();
969 _tbm_util_check_bo_cnt(bufmgr);
971 bo = calloc(1, sizeof(struct _tbm_bo));
973 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
974 _tbm_bufmgr_mutex_unlock();
982 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
984 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
985 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
987 _tbm_bufmgr_mutex_unlock();
991 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
992 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
993 if (bo2->priv == bo_priv) {
994 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
995 bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
998 _tbm_bufmgr_mutex_unlock();
1007 if (bufmgr->backend->bo_get_flags)
1008 bo->flags = bufmgr->backend->bo_get_flags(bo);
1010 bo->flags = TBM_BO_DEFAULT;
1012 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1013 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
1015 LIST_INITHEAD(&bo->user_data_list);
1017 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1019 _tbm_bufmgr_mutex_unlock();
1025 tbm_bo_export(tbm_bo bo)
1027 tbm_bufmgr bufmgr = NULL;
1030 _tbm_bufmgr_mutex_lock();
1032 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1033 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1037 if (!bufmgr->backend->bo_export) {
1038 _tbm_bufmgr_mutex_unlock();
1042 ret = bufmgr->backend->bo_export(bo);
1044 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1045 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1046 _tbm_bufmgr_mutex_unlock();
1050 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
1052 _tbm_bufmgr_mutex_unlock();
1058 tbm_bo_export_fd(tbm_bo bo)
1060 tbm_bufmgr bufmgr = NULL;
1063 _tbm_bufmgr_mutex_lock();
1065 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), -1);
1066 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1070 if (!bufmgr->backend->bo_export_fd) {
1071 _tbm_bufmgr_mutex_unlock();
1075 ret = bufmgr->backend->bo_export_fd(bo);
1077 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1078 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1079 _tbm_bufmgr_mutex_unlock();
1083 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1085 _tbm_bufmgr_mutex_unlock();
1091 tbm_bo_get_handle(tbm_bo bo, int device)
1093 tbm_bufmgr bufmgr = NULL;
1094 tbm_bo_handle bo_handle;
1096 _tbm_bufmgr_mutex_lock();
1098 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1099 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1103 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1104 if (bo_handle.ptr == NULL) {
1105 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1106 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1107 _tbm_bufmgr_mutex_unlock();
1108 return (tbm_bo_handle) NULL;
1111 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1113 _tbm_bufmgr_mutex_unlock();
1119 tbm_bo_map(tbm_bo bo, int device, int opt)
1121 tbm_bufmgr bufmgr = NULL;
1122 tbm_bo_handle bo_handle;
1124 _tbm_bufmgr_mutex_lock();
1126 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1127 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1131 if (!_tbm_bo_lock(bo, device, opt)) {
1132 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1133 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1134 _tbm_bufmgr_mutex_unlock();
1135 return (tbm_bo_handle) NULL;
1138 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1139 if (bo_handle.ptr == NULL) {
1140 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1141 TBM_TRACE("error: fail to map bo:%p\n", bo);
1143 _tbm_bufmgr_mutex_unlock();
1144 return (tbm_bo_handle) NULL;
1147 /* increase the map_count */
1150 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1152 _tbm_bufmgr_mutex_unlock();
1158 tbm_bo_unmap(tbm_bo bo)
1160 tbm_bufmgr bufmgr = NULL;
1163 _tbm_bufmgr_mutex_lock();
1165 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1166 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1170 ret = bufmgr->backend->bo_unmap(bo);
1172 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1173 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1174 _tbm_bufmgr_mutex_unlock();
1178 /* decrease the map_count */
1181 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1185 _tbm_bufmgr_mutex_unlock();
1191 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1193 tbm_bufmgr bufmgr = NULL;
1196 _tbm_bufmgr_mutex_lock();
1198 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1199 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1200 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1204 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1206 if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1207 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1208 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1209 _tbm_bufmgr_mutex_unlock();
1213 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1216 bo1->priv = bo2->priv;
1219 _tbm_bufmgr_mutex_unlock();
1225 tbm_bo_locked(tbm_bo bo)
1227 tbm_bufmgr bufmgr = NULL;
1229 _tbm_bufmgr_mutex_lock();
1231 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1232 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1236 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1237 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1238 _tbm_bufmgr_mutex_unlock();
1242 if (bo->lock_cnt > 0) {
1243 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1244 _tbm_bufmgr_mutex_unlock();
1248 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1249 _tbm_bufmgr_mutex_unlock();
1255 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1256 tbm_data_free data_free_func)
1258 tbm_user_data *data;
1260 _tbm_bufmgr_mutex_lock();
1262 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1263 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1265 /* check if the data according to the key exist if so, return false. */
1266 data = user_data_lookup(&bo->user_data_list, key);
1268 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1269 _tbm_bufmgr_mutex_unlock();
1273 data = user_data_create(key, data_free_func);
1275 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1276 _tbm_bufmgr_mutex_unlock();
1280 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1282 LIST_ADD(&data->item_link, &bo->user_data_list);
1284 _tbm_bufmgr_mutex_unlock();
1290 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1292 tbm_user_data *old_data;
1294 _tbm_bufmgr_mutex_lock();
1296 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1297 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1299 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1300 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1301 _tbm_bufmgr_mutex_unlock();
1305 old_data = user_data_lookup(&bo->user_data_list, key);
1307 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1308 _tbm_bufmgr_mutex_unlock();
1312 if (old_data->data && old_data->free_func)
1313 old_data->free_func(old_data->data);
1315 old_data->data = data;
1317 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1319 _tbm_bufmgr_mutex_unlock();
1325 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1327 tbm_user_data *old_data;
1329 _tbm_bufmgr_mutex_lock();
1331 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1332 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1334 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1335 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1336 _tbm_bufmgr_mutex_unlock();
1340 old_data = user_data_lookup(&bo->user_data_list, key);
1342 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1344 _tbm_bufmgr_mutex_unlock();
1348 *data = old_data->data;
1350 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1352 _tbm_bufmgr_mutex_unlock();
1358 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1360 tbm_user_data *old_data = (void *)0;
1362 _tbm_bufmgr_mutex_lock();
1364 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1365 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1367 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1368 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1369 _tbm_bufmgr_mutex_unlock();
1373 old_data = user_data_lookup(&bo->user_data_list, key);
1375 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1376 _tbm_bufmgr_mutex_unlock();
1380 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1382 user_data_delete(old_data);
1384 _tbm_bufmgr_mutex_unlock();
1390 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1392 int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1394 _tbm_bufmgr_mutex_lock();
1396 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1397 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1399 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1401 capabilities = bufmgr->capabilities;
1403 _tbm_bufmgr_mutex_unlock();
1405 return capabilities;
1409 tbm_bo_get_flags(tbm_bo bo)
1413 _tbm_bufmgr_mutex_lock();
1415 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1416 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1420 TBM_TRACE("bo(%p)\n", bo);
1422 _tbm_bufmgr_mutex_unlock();
1427 /* LCOV_EXCL_START */
1429 tbm_get_last_error(void)
1431 return tbm_last_error;
1435 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1437 tbm_bo bo = NULL, tmp_bo = NULL;
1439 tbm_surface_h surf = NULL, tmp_surf = NULL;
1442 char app_name[255] = {0,};
1443 unsigned int pid = 0;
1444 char title[255] = {0,};
1445 char data[255] = {0,};
1446 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1448 pthread_mutex_lock(&gLock);
1450 if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
1451 TBM_LOG_E("invalid bufmgr\n");
1452 pthread_mutex_unlock(&gLock);
1457 _tbm_util_get_appname_from_pid(getpid(), app_name);
1458 _tbm_util_get_appname_brief(app_name);
1459 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1460 app_name, getpid());
1461 memset(app_name, 0x0, 255 * sizeof(char));
1462 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1463 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1464 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1465 strncat(title, " ", 3);
1466 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1470 TBM_DEBUG("[tbm_surface information]\n");
1471 TBM_DEBUG("%s\n", title);
1472 /* show the tbm_surface information in surf_list */
1473 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1476 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1477 pid = _tbm_surface_internal_get_debug_pid(surf);
1479 /* if pid is null, set the self_pid */
1483 _tbm_util_get_appname_from_pid(pid, app_name);
1484 _tbm_util_get_appname_brief(app_name);
1486 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1493 surf->info.size / 1024,
1497 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1500 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1501 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1502 strncat(data, " ", 3);
1504 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1506 strncat(data, value, strlen(value) + 1);
1508 strncat(data, "none", 5);
1511 TBM_DEBUG("%s\n", data);
1513 for (i = 0; i < surf->num_bos; i++) {
1514 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1516 surf->bos[i]->ref_cnt,
1517 tbm_bo_size(surf->bos[i]) / 1024);
1520 memset(app_name, 0x0, 255 * sizeof(char));
1523 TBM_DEBUG("no tbm_surfaces.\n");
1527 TBM_DEBUG("[tbm_bo information]\n");
1528 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1530 /* show the tbm_bo information in bo_list */
1531 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1532 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1533 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1537 tbm_bo_size(bo) / 1024,
1544 TBM_DEBUG("no tbm_bos.\n");
1548 TBM_DEBUG("===============================================================\n");
1550 pthread_mutex_unlock(&gLock);
1554 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1556 _tbm_bufmgr_mutex_lock();
1558 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1559 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1562 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1566 _tbm_bufmgr_mutex_unlock();
1570 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1574 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1575 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1577 pthread_mutex_lock(&gLock);
1580 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1581 TBM_LOG_I("No tbm_surface.\n");
1582 pthread_mutex_unlock(&gLock);
1586 tbm_surface_internal_dump_start(path, w, h, count);
1588 } else if (onoff == 0) {
1589 tbm_surface_internal_dump_end();
1592 pthread_mutex_unlock(&gLock);
1596 pthread_mutex_unlock(&gLock);
1601 tbm_bufmgr_debug_dump_all(char *path)
1603 int w = 0, h = 0, count = 0;
1604 tbm_surface_h surface = NULL, tmp = NULL;
1606 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1607 TBM_LOG_D("path=%s\n", path);
1609 pthread_mutex_lock(&gLock);
1611 count = _tbm_util_get_max_surface_size(&w, &h);
1613 TBM_LOG_I("No tbm_surface.\n");
1614 pthread_mutex_unlock(&gLock);
1618 tbm_surface_internal_dump_start(path, w, h, count);
1620 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1621 tbm_surface_internal_dump_buffer(surface, "dump_all");
1624 tbm_surface_internal_dump_end();
1626 pthread_mutex_unlock(&gLock);
1631 /* internal function */
1633 _tbm_bufmgr_get_bufmgr(void)
1639 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1641 _tbm_bufmgr_mutex_lock();
1643 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1644 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1646 bo->surface = surface;
1648 _tbm_bufmgr_mutex_unlock();
1654 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1658 _tbm_bufmgr_mutex_lock();
1660 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1662 if (!bufmgr->backend->bufmgr_bind_native_display) {
1663 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1664 _tbm_bufmgr_mutex_unlock();
1668 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1670 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1671 _tbm_bufmgr_mutex_unlock();
1675 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1677 _tbm_bufmgr_mutex_unlock();
1681 /* LCOV_EXCL_STOP */