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"
51 #define PREFIX_LIB "libtbm_"
52 #define SUFFIX_LIB ".so"
53 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
55 /* values to indicate unspecified fields in XF86ModReqInfo. */
56 #define MAJOR_UNSPEC 0xFF
57 #define MINOR_UNSPEC 0xFF
58 #define PATCH_UNSPEC 0xFFFF
59 #define ABI_VERS_UNSPEC 0xFFFFFFFF
61 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
62 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
63 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
64 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
65 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
73 pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
76 static __thread tbm_error_e tbm_last_error = TBM_ERROR_NONE;
79 _tbm_set_last_result(tbm_error_e err)
84 char * tbm_flag_to_str(int f)
88 if (f == TBM_BO_DEFAULT)
89 snprintf(str, 255, "DEFAULT\n");
91 if (f & TBM_BO_SCANOUT)
92 c = snprintf(&str[c], 255, "SCANOUT,");
93 if (f & TBM_BO_NONCACHABLE)
94 c = snprintf(&str[c], 255, "NONCACHABLE,");
96 c = snprintf(&str[c], 255, "WC");
101 /* LCOV_EXCL_START */
102 static int last_chk_bo_cnt = 0;
104 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
106 if (bufmgr->bo_cnt >= 500 && ((bufmgr->bo_cnt % 20) == 0)) {
107 if (bufmgr->bo_cnt > last_chk_bo_cnt) {
108 TBM_DEBUG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
109 tbm_bufmgr_debug_show(bufmgr);
110 last_chk_bo_cnt = bufmgr->bo_cnt;
116 _tbm_util_get_appname_brief(char *brief)
120 char temp[255] = {0,};
121 char *saveptr = NULL;
123 token = strtok_r(brief, delim, &saveptr);
125 while (token != NULL) {
126 memset(temp, 0x00, 255 * sizeof(char));
127 strncpy(temp, token, 254 * sizeof(char));
128 token = strtok_r(NULL, delim, &saveptr);
131 snprintf(brief, sizeof(temp), "%s", temp);
135 _tbm_util_get_appname_from_pid(long pid, char *str)
140 char fn_cmdline[255] = {0,};
141 char cmdline[255] = {0,};
143 snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", app_pid);
145 fp = fopen(fn_cmdline, "r");
147 fprintf(stderr, "cannot file open /proc/%ld/cmdline", app_pid);
151 if (!fgets(cmdline, 255, fp)) {
152 fprintf(stderr, "fail to get appname for pid(%ld)\n", app_pid);
158 len = strlen(cmdline);
160 memset(cmdline, 0x00, 255);
164 snprintf(str, sizeof(cmdline), "%s", cmdline);
169 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
171 tbm_user_data *user_data = NULL;
172 tbm_user_data *old_data = NULL, *tmp = NULL;
174 if (!LIST_IS_EMPTY(user_data_list)) {
175 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, user_data_list, item_link) {
176 if (old_data->key == key) {
177 user_data = old_data;
187 *user_data_create(unsigned long key, tbm_data_free data_free_func)
189 tbm_user_data *user_data = NULL;
191 user_data = calloc(1, sizeof(tbm_user_data));
195 user_data->key = key;
196 user_data->free_func = data_free_func;
197 user_data->data = (void *)0;
203 user_data_delete(tbm_user_data *user_data)
205 if (user_data->data && user_data->free_func)
206 user_data->free_func(user_data->data);
208 LIST_DEL(&user_data->item_link);
214 _bo_lock(tbm_bo bo, int device, int opt)
216 tbm_bufmgr bufmgr = bo->bufmgr;
219 if (bufmgr->backend->bo_lock)
220 ret = bufmgr->backend->bo_lock(bo, device, opt);
228 _bo_unlock(tbm_bo bo)
230 tbm_bufmgr bufmgr = bo->bufmgr;
232 if (bufmgr->backend->bo_unlock)
233 bufmgr->backend->bo_unlock(bo);
237 _tbm_bo_lock(tbm_bo bo, int device, int opt)
239 tbm_bufmgr bufmgr = NULL;
248 /* do not try to lock the bo */
249 if (bufmgr->lock_type == LOCK_TRY_NEVER)
252 if (bo->lock_cnt < 0) {
253 TBM_LOG_E("error bo:%p LOCK_CNT=%d\n",
258 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
259 if (bo->lock_cnt == 0) {
260 pthread_mutex_unlock(&bufmgr->lock);
261 ret = _bo_lock(bo, device, opt);
262 pthread_mutex_lock(&bufmgr->lock);
267 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
268 pthread_mutex_unlock(&bufmgr->lock);
269 ret = _bo_lock(bo, device, opt);
270 pthread_mutex_lock(&bufmgr->lock);
274 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
278 DBG_LOCK(">> LOCK bo:%p(%d->%d)\n",
279 bo, old, bo->lock_cnt);
285 _tbm_bo_unlock(tbm_bo bo)
287 tbm_bufmgr bufmgr = NULL;
296 /* do not try to unlock the bo */
297 if (bufmgr->lock_type == LOCK_TRY_NEVER)
301 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
302 if (bo->lock_cnt > 0) {
304 if (bo->lock_cnt == 0)
307 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
308 if (bo->lock_cnt > 0) {
313 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
317 if (bo->lock_cnt < 0)
320 DBG_LOCK(">> UNLOCK bo:%p(%d->%d)\n",
321 bo, old, bo->lock_cnt);
325 _tbm_bo_is_valid(tbm_bo bo)
327 tbm_bo old_data = NULL, tmp = NULL;
332 if (!LIST_IS_EMPTY(&gBufMgr->bo_list)) {
333 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &gBufMgr->bo_list, item_link) {
343 _tbm_bo_ref(tbm_bo bo)
349 _tbm_bo_unref(tbm_bo bo)
351 tbm_bufmgr bufmgr = bo->bufmgr;
352 tbm_user_data *old_data = NULL, *tmp = NULL;
354 if (bo->ref_cnt <= 0)
358 if (bo->ref_cnt == 0) {
359 /* destory the user_data_list */
360 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
361 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
362 DBG("free user_data\n");
363 user_data_delete(old_data);
367 if (bo->lock_cnt > 0) {
368 TBM_LOG_E("error lock_cnt:%d\n",
373 /* call the bo_free */
374 bufmgr->backend->bo_free(bo);
377 LIST_DEL(&bo->item_link);
386 /* LCOV_EXCL_START */
388 _check_version(TBMModuleVersionInfo *data)
393 abimaj = GET_ABI_MAJOR(data->abiversion);
394 abimin = GET_ABI_MINOR(data->abiversion);
396 DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
397 data->modname ? data->modname : "UNKNOWN!",
398 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
400 vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
401 vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
403 DBG("TBM ABI version %d.%d\n",
406 if (abimaj != vermaj) {
407 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
410 } else if (abimin > vermin) {
411 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
419 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
421 char path[PATH_MAX] = { 0, };
422 TBMModuleData *initdata = NULL;
425 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
427 module_data = dlopen(path, RTLD_LAZY);
429 TBM_LOG_E("failed to load module: %s(%s)\n",
434 initdata = dlsym(module_data, "tbmModuleData");
437 TBMModuleVersionInfo *vers;
439 vers = initdata->vers;
440 init = initdata->init;
443 if (!_check_version(vers)) {
444 dlclose(module_data);
448 TBM_LOG_E("Error: module does not supply version information.\n");
450 dlclose(module_data);
455 if (!init(bufmgr, fd)) {
456 TBM_LOG_E("Fail to init module(%s)\n",
458 dlclose(module_data);
462 if (!bufmgr->backend || !bufmgr->backend->priv) {
463 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n",
465 dlclose(module_data);
469 TBM_LOG_E("Error: module does not supply init symbol.\n");
470 dlclose(module_data);
474 TBM_LOG_E("Error: module does not have data object.\n");
475 dlclose(module_data);
479 bufmgr->module_data = module_data;
481 DBG("Success to load module(%s)\n",
488 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
490 struct dirent **namelist;
491 const char *p = NULL;
495 /* load bufmgr priv from default lib */
496 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
498 /* load bufmgr priv from configured path */
500 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
502 TBM_LOG_E("no files : %s\n",
506 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
507 p = strstr(namelist[n]->d_name, SUFFIX_LIB);
508 if (p && !strcmp(p, SUFFIX_LIB))
509 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
522 tbm_bufmgr_init(int fd)
526 pthread_mutex_lock(&gLock);
528 /* LCOV_EXCL_START */
530 env = getenv("TBM_DLOG");
533 TBM_LOG_D("TBM_DLOG=%s\n", env);
540 env = getenv("TBM_DEBUG");
543 TBM_LOG_D("TBM_DEBUG=%s\n", env);
550 env = getenv("TBM_TRACE");
553 TBM_LOG_D("TBM_TRACE=%s\n", env);
560 /* initialize buffer manager */
562 gBufMgr->ref_count++;
563 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
564 pthread_mutex_unlock(&gLock);
568 DBG("bufmgr init\n");
570 /* allocate bufmgr */
571 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
573 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
574 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
575 pthread_mutex_unlock(&gLock);
581 /* load bufmgr priv from env */
582 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
583 /* LCOV_EXCL_START */
584 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
585 TBM_LOG_E("error : Fail to load bufmgr backend\n");
588 pthread_mutex_unlock(&gLock);
593 /* log for tbm backend_flag */
594 DBG("backend flag:%x:", gBufMgr->backend->flags);
597 gBufMgr->ref_count = 1;
599 DBG("create tizen bufmgr:%p ref_count:%d\n",
600 gBufMgr, gBufMgr->ref_count);
602 if (pthread_mutex_init(&gBufMgr->lock, NULL) != 0) {
603 /* LCOV_EXCL_START */
604 _tbm_set_last_result(TBM_BO_ERROR_THREAD_INIT_FAILED);
605 gBufMgr->backend->bufmgr_deinit(gBufMgr->backend->priv);
606 tbm_backend_free(gBufMgr->backend);
607 dlclose(gBufMgr->module_data);
610 pthread_mutex_unlock(&gLock);
615 /* setup the lock_type */
616 env = getenv("BUFMGR_LOCK_TYPE");
617 if (env && !strcmp(env, "always"))
618 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
619 else if (env && !strcmp(env, "none"))
620 gBufMgr->lock_type = LOCK_TRY_NEVER;
621 else if (env && !strcmp(env, "once"))
622 gBufMgr->lock_type = LOCK_TRY_ONCE;
624 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
626 DBG("BUFMGR_LOCK_TYPE=%s\n",
627 env ? env : "default:once");
629 TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
631 /* intialize bo_list */
632 LIST_INITHEAD(&gBufMgr->bo_list);
634 /* intialize surf_list */
635 LIST_INITHEAD(&gBufMgr->surf_list);
637 /* intialize debug_key_list */
638 LIST_INITHEAD(&gBufMgr->debug_key_list);
640 pthread_mutex_unlock(&gLock);
645 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
647 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
652 tbm_surface_h surf = NULL;
653 tbm_surface_h tmp_surf = NULL;
655 pthread_mutex_lock(&gLock);
658 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
659 pthread_mutex_unlock(&gLock);
664 if (bufmgr->ref_count > 0) {
665 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
666 pthread_mutex_unlock(&gLock);
670 /* destroy bo_list */
671 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
672 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
673 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
680 /* destroy surf_list */
681 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
682 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
683 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
685 tbm_surface_destroy(surf);
689 /* destroy bufmgr priv */
690 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
691 bufmgr->backend->priv = NULL;
692 tbm_backend_free(bufmgr->backend);
693 bufmgr->backend = NULL;
695 pthread_mutex_destroy(&bufmgr->lock);
697 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
699 dlclose(bufmgr->module_data);
708 pthread_mutex_unlock(&gLock);
712 tbm_bo_size(tbm_bo bo)
714 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
716 tbm_bufmgr bufmgr = bo->bufmgr;
719 pthread_mutex_lock(&bufmgr->lock);
721 size = bufmgr->backend->bo_size(bo);
723 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
725 pthread_mutex_unlock(&bufmgr->lock);
731 tbm_bo_ref(tbm_bo bo)
733 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
735 tbm_bufmgr bufmgr = bo->bufmgr;
737 pthread_mutex_lock(&bufmgr->lock);
741 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
743 pthread_mutex_unlock(&bufmgr->lock);
749 tbm_bo_unref(tbm_bo bo)
751 TBM_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
753 tbm_bufmgr bufmgr = bo->bufmgr;
755 pthread_mutex_lock(&bufmgr->lock);
757 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
761 pthread_mutex_unlock(&bufmgr->lock);
765 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
767 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
770 void *bo_priv = NULL;
772 bo = calloc(1, sizeof(struct _tbm_bo));
774 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
775 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
779 _tbm_util_check_bo_cnt(bufmgr);
784 pthread_mutex_lock(&bufmgr->lock);
786 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
788 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
789 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
791 pthread_mutex_unlock(&bufmgr->lock);
799 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
801 LIST_INITHEAD(&bo->user_data_list);
803 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
805 pthread_mutex_unlock(&bufmgr->lock);
811 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
813 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
818 void *bo_priv = NULL;
820 _tbm_util_check_bo_cnt(bufmgr);
822 pthread_mutex_lock(&bufmgr->lock);
824 bo = calloc(1, sizeof(struct _tbm_bo));
826 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
827 pthread_mutex_unlock(&bufmgr->lock);
835 bo_priv = bufmgr->backend->bo_import(bo, key);
837 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
838 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
840 pthread_mutex_unlock(&bufmgr->lock);
844 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
845 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
846 if (bo2->priv == bo_priv) {
847 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
848 bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
851 pthread_mutex_unlock(&bufmgr->lock);
860 if (bufmgr->backend->bo_get_flags)
861 bo->flags = bufmgr->backend->bo_get_flags(bo);
863 bo->flags = TBM_BO_DEFAULT;
865 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
866 bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
868 LIST_INITHEAD(&bo->user_data_list);
870 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
872 pthread_mutex_unlock(&bufmgr->lock);
878 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
880 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
885 void *bo_priv = NULL;
887 _tbm_util_check_bo_cnt(bufmgr);
889 pthread_mutex_lock(&bufmgr->lock);
891 bo = calloc(1, sizeof(struct _tbm_bo));
893 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
894 pthread_mutex_unlock(&bufmgr->lock);
902 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
904 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
905 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
907 pthread_mutex_unlock(&bufmgr->lock);
911 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
912 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
913 if (bo2->priv == bo_priv) {
914 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
915 bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
918 pthread_mutex_unlock(&bufmgr->lock);
927 if (bufmgr->backend->bo_get_flags)
928 bo->flags = bufmgr->backend->bo_get_flags(bo);
930 bo->flags = TBM_BO_DEFAULT;
932 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
933 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
935 LIST_INITHEAD(&bo->user_data_list);
937 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
939 pthread_mutex_unlock(&bufmgr->lock);
945 tbm_bo_export(tbm_bo bo)
947 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
954 pthread_mutex_lock(&bufmgr->lock);
956 ret = bufmgr->backend->bo_export(bo);
958 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
959 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
960 pthread_mutex_unlock(&bufmgr->lock);
964 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
966 pthread_mutex_unlock(&bufmgr->lock);
972 tbm_bo_export_fd(tbm_bo bo)
974 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
981 pthread_mutex_lock(&bufmgr->lock);
983 ret = bufmgr->backend->bo_export_fd(bo);
985 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
986 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
987 pthread_mutex_unlock(&bufmgr->lock);
991 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
993 pthread_mutex_unlock(&bufmgr->lock);
999 tbm_bo_get_handle(tbm_bo bo, int device)
1001 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1004 tbm_bo_handle bo_handle;
1006 bufmgr = bo->bufmgr;
1008 pthread_mutex_lock(&bufmgr->lock);
1010 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1011 if (bo_handle.ptr == NULL) {
1012 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1013 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1014 pthread_mutex_unlock(&bufmgr->lock);
1015 return (tbm_bo_handle) NULL;
1018 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1020 pthread_mutex_unlock(&bufmgr->lock);
1026 tbm_bo_map(tbm_bo bo, int device, int opt)
1028 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1031 tbm_bo_handle bo_handle;
1033 bufmgr = bo->bufmgr;
1035 pthread_mutex_lock(&bufmgr->lock);
1037 if (!_tbm_bo_lock(bo, device, opt)) {
1038 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1039 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1040 pthread_mutex_unlock(&bufmgr->lock);
1041 return (tbm_bo_handle) NULL;
1044 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1045 if (bo_handle.ptr == NULL) {
1046 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1047 TBM_TRACE("error: fail to map bo:%p\n", bo);
1049 pthread_mutex_unlock(&bufmgr->lock);
1050 return (tbm_bo_handle) NULL;
1053 /* increase the map_count */
1056 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1058 pthread_mutex_unlock(&bufmgr->lock);
1064 tbm_bo_unmap(tbm_bo bo)
1066 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1071 bufmgr = bo->bufmgr;
1073 pthread_mutex_lock(&bufmgr->lock);
1075 ret = bufmgr->backend->bo_unmap(bo);
1077 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1078 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1079 pthread_mutex_unlock(&bufmgr->lock);
1083 /* decrease the map_count */
1086 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1090 pthread_mutex_unlock(&bufmgr->lock);
1096 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1098 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1099 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1103 pthread_mutex_lock(&bo1->bufmgr->lock);
1105 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1107 if (bo1->bufmgr->backend->bo_size(bo1) != bo2->bufmgr->backend->bo_size(bo2)) {
1108 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1109 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1110 pthread_mutex_unlock(&bo1->bufmgr->lock);
1114 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1117 bo1->priv = bo2->priv;
1120 pthread_mutex_unlock(&bo1->bufmgr->lock);
1126 tbm_bo_locked(tbm_bo bo)
1128 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1132 bufmgr = bo->bufmgr;
1134 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1135 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1139 pthread_mutex_lock(&bufmgr->lock);
1142 if (bo->lock_cnt > 0) {
1143 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1144 pthread_mutex_unlock(&bufmgr->lock);
1148 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1149 pthread_mutex_unlock(&bufmgr->lock);
1155 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1156 tbm_data_free data_free_func)
1158 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1160 tbm_user_data *data;
1162 /* check if the data according to the key exist if so, return false. */
1163 data = user_data_lookup(&bo->user_data_list, key);
1165 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1169 data = user_data_create(key, data_free_func);
1171 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1175 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1177 LIST_ADD(&data->item_link, &bo->user_data_list);
1183 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1185 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1187 tbm_user_data *old_data;
1189 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1190 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1194 old_data = user_data_lookup(&bo->user_data_list, key);
1196 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1200 if (old_data->data && old_data->free_func)
1201 old_data->free_func(old_data->data);
1203 old_data->data = data;
1205 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1211 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1213 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1215 tbm_user_data *old_data;
1217 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1218 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1222 old_data = user_data_lookup(&bo->user_data_list, key);
1224 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1229 *data = old_data->data;
1231 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1237 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1239 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1241 tbm_user_data *old_data = (void *)0;
1243 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1244 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1248 old_data = user_data_lookup(&bo->user_data_list, key);
1250 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1254 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1256 user_data_delete(old_data);
1262 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1264 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1266 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1268 return bufmgr->capabilities;
1272 tbm_bo_get_flags(tbm_bo bo)
1274 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1276 TBM_TRACE("bo(%p)\n", bo);
1281 /* LCOV_EXCL_START */
1283 tbm_get_last_error(void)
1285 return tbm_last_error;
1289 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1291 TBM_RETURN_IF_FAIL(bufmgr != NULL);
1292 tbm_bo bo = NULL, tmp_bo = NULL;
1295 tbm_surface_h surf = NULL, tmp_surf = NULL;
1298 char app_name[255] = {0,};
1299 unsigned int pid = 0;
1300 char title[255] = {0,};
1301 char data[255] = {0,};
1302 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1304 pthread_mutex_lock(&gLock);
1307 _tbm_util_get_appname_from_pid(getpid(), app_name);
1308 _tbm_util_get_appname_brief(app_name);
1309 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1310 app_name, getpid());
1311 memset(app_name, 0x0, 255 * sizeof(char));
1312 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1313 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1314 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1315 strncat(title, " ", 2);
1316 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1320 TBM_DEBUG("[tbm_surface information]\n");
1321 TBM_DEBUG("%s\n", title);
1322 /* show the tbm_surface information in surf_list */
1323 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1326 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1327 pid = _tbm_surface_internal_get_debug_pid(surf);
1329 /* if pid is null, set the self_pid */
1333 _tbm_util_get_appname_from_pid(pid, app_name);
1334 _tbm_util_get_appname_brief(app_name);
1336 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1343 surf->info.size / 1024,
1347 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1350 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1351 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1352 strncat(data, " ", 2);
1354 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1356 strncat(data, value, strlen(value) + 1);
1358 strncat(data, "none", strlen("none") + 1);
1361 TBM_DEBUG("%s\n", data);
1363 for (i = 0; i < surf->num_bos; i++) {
1364 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1366 surf->bos[i]->ref_cnt,
1367 tbm_bo_size(surf->bos[i]) / 1024);
1370 memset(app_name, 0x0, 255 * sizeof(char));
1373 TBM_DEBUG("no tbm_surfaces.\n");
1377 TBM_DEBUG("[tbm_bo information]\n");
1378 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1380 /* show the tbm_bo information in bo_list */
1381 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1382 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1383 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1387 tbm_bo_size(bo) / 1024,
1394 TBM_DEBUG("no tbm_bos.\n");
1398 TBM_DEBUG("===============================================================\n");
1400 pthread_mutex_unlock(&gLock);
1405 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1408 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1413 /* internal function */
1415 _tbm_bufmgr_get_bufmgr(void)
1421 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1423 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1425 bo->surface = surface;
1431 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1433 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1437 pthread_mutex_lock(&bufmgr->lock);
1439 if (!bufmgr->backend->bufmgr_bind_native_display) {
1440 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1441 pthread_mutex_unlock(&bufmgr->lock);
1445 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1447 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1448 pthread_mutex_unlock(&bufmgr->lock);
1452 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1454 pthread_mutex_unlock(&bufmgr->lock);
1458 /* LCOV_EXCL_STOP */