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 pthread_mutex_unlock(&gLock);
642 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
644 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
649 tbm_surface_h surf = NULL;
650 tbm_surface_h tmp_surf = NULL;
652 pthread_mutex_lock(&gLock);
655 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
656 pthread_mutex_unlock(&gLock);
661 if (bufmgr->ref_count > 0) {
662 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
663 pthread_mutex_unlock(&gLock);
667 /* destroy bo_list */
668 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
669 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
670 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
677 /* destroy surf_list */
678 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
679 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
680 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
682 tbm_surface_destroy(surf);
686 /* destroy bufmgr priv */
687 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
688 bufmgr->backend->priv = NULL;
689 tbm_backend_free(bufmgr->backend);
690 bufmgr->backend = NULL;
692 pthread_mutex_destroy(&bufmgr->lock);
694 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
696 dlclose(bufmgr->module_data);
705 pthread_mutex_unlock(&gLock);
709 tbm_bo_size(tbm_bo bo)
711 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
713 tbm_bufmgr bufmgr = bo->bufmgr;
716 pthread_mutex_lock(&bufmgr->lock);
718 size = bufmgr->backend->bo_size(bo);
720 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
722 pthread_mutex_unlock(&bufmgr->lock);
728 tbm_bo_ref(tbm_bo bo)
730 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
732 tbm_bufmgr bufmgr = bo->bufmgr;
734 pthread_mutex_lock(&bufmgr->lock);
738 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
740 pthread_mutex_unlock(&bufmgr->lock);
746 tbm_bo_unref(tbm_bo bo)
748 TBM_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
750 tbm_bufmgr bufmgr = bo->bufmgr;
752 pthread_mutex_lock(&bufmgr->lock);
754 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
758 pthread_mutex_unlock(&bufmgr->lock);
762 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
764 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
767 void *bo_priv = NULL;
769 bo = calloc(1, sizeof(struct _tbm_bo));
771 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
772 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
776 _tbm_util_check_bo_cnt(bufmgr);
781 pthread_mutex_lock(&bufmgr->lock);
783 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
785 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
786 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
788 pthread_mutex_unlock(&bufmgr->lock);
796 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
798 LIST_INITHEAD(&bo->user_data_list);
800 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
802 pthread_mutex_unlock(&bufmgr->lock);
808 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
810 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
815 void *bo_priv = NULL;
817 _tbm_util_check_bo_cnt(bufmgr);
819 pthread_mutex_lock(&bufmgr->lock);
821 bo = calloc(1, sizeof(struct _tbm_bo));
823 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
824 pthread_mutex_unlock(&bufmgr->lock);
832 bo_priv = bufmgr->backend->bo_import(bo, key);
834 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
835 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
837 pthread_mutex_unlock(&bufmgr->lock);
841 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
842 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
843 if (bo2->priv == bo_priv) {
844 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
845 bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
848 pthread_mutex_unlock(&bufmgr->lock);
857 if (bufmgr->backend->bo_get_flags)
858 bo->flags = bufmgr->backend->bo_get_flags(bo);
860 bo->flags = TBM_BO_DEFAULT;
862 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
863 bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
865 LIST_INITHEAD(&bo->user_data_list);
867 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
869 pthread_mutex_unlock(&bufmgr->lock);
875 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
877 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
882 void *bo_priv = NULL;
884 _tbm_util_check_bo_cnt(bufmgr);
886 pthread_mutex_lock(&bufmgr->lock);
888 bo = calloc(1, sizeof(struct _tbm_bo));
890 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
891 pthread_mutex_unlock(&bufmgr->lock);
899 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
901 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
902 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
904 pthread_mutex_unlock(&bufmgr->lock);
908 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
909 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
910 if (bo2->priv == bo_priv) {
911 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
912 bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
915 pthread_mutex_unlock(&bufmgr->lock);
924 if (bufmgr->backend->bo_get_flags)
925 bo->flags = bufmgr->backend->bo_get_flags(bo);
927 bo->flags = TBM_BO_DEFAULT;
929 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
930 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
932 LIST_INITHEAD(&bo->user_data_list);
934 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
936 pthread_mutex_unlock(&bufmgr->lock);
942 tbm_bo_export(tbm_bo bo)
944 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
951 pthread_mutex_lock(&bufmgr->lock);
953 ret = bufmgr->backend->bo_export(bo);
955 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
956 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
957 pthread_mutex_unlock(&bufmgr->lock);
961 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
963 pthread_mutex_unlock(&bufmgr->lock);
969 tbm_bo_export_fd(tbm_bo bo)
971 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
978 pthread_mutex_lock(&bufmgr->lock);
980 ret = bufmgr->backend->bo_export_fd(bo);
982 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
983 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
984 pthread_mutex_unlock(&bufmgr->lock);
988 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
990 pthread_mutex_unlock(&bufmgr->lock);
996 tbm_bo_get_handle(tbm_bo bo, int device)
998 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1001 tbm_bo_handle bo_handle;
1003 bufmgr = bo->bufmgr;
1005 pthread_mutex_lock(&bufmgr->lock);
1007 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1008 if (bo_handle.ptr == NULL) {
1009 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1010 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1011 pthread_mutex_unlock(&bufmgr->lock);
1012 return (tbm_bo_handle) NULL;
1015 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1017 pthread_mutex_unlock(&bufmgr->lock);
1023 tbm_bo_map(tbm_bo bo, int device, int opt)
1025 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1028 tbm_bo_handle bo_handle;
1030 bufmgr = bo->bufmgr;
1032 pthread_mutex_lock(&bufmgr->lock);
1034 if (!_tbm_bo_lock(bo, device, opt)) {
1035 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1036 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1037 pthread_mutex_unlock(&bufmgr->lock);
1038 return (tbm_bo_handle) NULL;
1041 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1042 if (bo_handle.ptr == NULL) {
1043 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1044 TBM_TRACE("error: fail to map bo:%p\n", bo);
1046 pthread_mutex_unlock(&bufmgr->lock);
1047 return (tbm_bo_handle) NULL;
1050 /* increase the map_count */
1053 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1055 pthread_mutex_unlock(&bufmgr->lock);
1061 tbm_bo_unmap(tbm_bo bo)
1063 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1068 bufmgr = bo->bufmgr;
1070 pthread_mutex_lock(&bufmgr->lock);
1072 ret = bufmgr->backend->bo_unmap(bo);
1074 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1075 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1076 pthread_mutex_unlock(&bufmgr->lock);
1080 /* decrease the map_count */
1083 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1087 pthread_mutex_unlock(&bufmgr->lock);
1093 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1095 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1096 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1100 pthread_mutex_lock(&bo1->bufmgr->lock);
1102 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1104 if (bo1->bufmgr->backend->bo_size(bo1) != bo2->bufmgr->backend->bo_size(bo2)) {
1105 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1106 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1107 pthread_mutex_unlock(&bo1->bufmgr->lock);
1111 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1114 bo1->priv = bo2->priv;
1117 pthread_mutex_unlock(&bo1->bufmgr->lock);
1123 tbm_bo_locked(tbm_bo bo)
1125 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1129 bufmgr = bo->bufmgr;
1131 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1132 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1136 pthread_mutex_lock(&bufmgr->lock);
1139 if (bo->lock_cnt > 0) {
1140 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1141 pthread_mutex_unlock(&bufmgr->lock);
1145 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1146 pthread_mutex_unlock(&bufmgr->lock);
1152 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1153 tbm_data_free data_free_func)
1155 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1157 tbm_user_data *data;
1159 /* check if the data according to the key exist if so, return false. */
1160 data = user_data_lookup(&bo->user_data_list, key);
1162 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1166 data = user_data_create(key, data_free_func);
1168 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1172 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1174 LIST_ADD(&data->item_link, &bo->user_data_list);
1180 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1182 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1184 tbm_user_data *old_data;
1186 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1187 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1191 old_data = user_data_lookup(&bo->user_data_list, key);
1193 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1197 if (old_data->data && old_data->free_func)
1198 old_data->free_func(old_data->data);
1200 old_data->data = data;
1202 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1208 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1210 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1212 tbm_user_data *old_data;
1214 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1215 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1219 old_data = user_data_lookup(&bo->user_data_list, key);
1221 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1226 *data = old_data->data;
1228 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1234 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1236 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1238 tbm_user_data *old_data = (void *)0;
1240 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1241 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1245 old_data = user_data_lookup(&bo->user_data_list, key);
1247 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1251 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1253 user_data_delete(old_data);
1259 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1261 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1263 unsigned int capability = TBM_BUFMGR_CAPABILITY_NONE;
1265 if (bufmgr->backend->bo_import && bufmgr->backend->bo_export)
1266 capability |= TBM_BUFMGR_CAPABILITY_SHARE_KEY;
1268 if (bufmgr->backend->bo_import_fd && bufmgr->backend->bo_export_fd)
1269 capability |= TBM_BUFMGR_CAPABILITY_SHARE_FD;
1271 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, capability);
1277 tbm_bo_get_flags(tbm_bo bo)
1279 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1281 TBM_TRACE("bo(%p)\n", bo);
1286 /* LCOV_EXCL_START */
1288 tbm_get_last_error(void)
1290 return tbm_last_error;
1294 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1296 TBM_RETURN_IF_FAIL(bufmgr != NULL);
1297 tbm_bo bo = NULL, tmp_bo = NULL;
1300 tbm_surface_h surf = NULL, tmp_surf = NULL;
1303 char app_name[255] = {0,};
1304 unsigned int pid = 0;
1306 pthread_mutex_lock(&gLock);
1309 _tbm_util_get_appname_from_pid(getpid(), app_name);
1310 _tbm_util_get_appname_brief(app_name);
1311 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1312 app_name, getpid());
1313 memset(app_name, 0x0, 255 * sizeof(char));
1315 TBM_DEBUG("[tbm_surface information]\n");
1316 TBM_DEBUG("no surface refcnt width height bpp size num_bos num_planes flags format app_name\n");
1317 /* show the tbm_surface information in surf_list */
1318 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1319 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1320 pid = _tbm_surface_internal_get_debug_pid(surf);
1322 /* if pid is null, set the self_pid */
1326 _tbm_util_get_appname_from_pid(pid, app_name);
1327 _tbm_util_get_appname_brief(app_name);
1329 TBM_DEBUG("%-4d%-23p%-6d%-7d%-8d%-5d%-12d%-10d%-9d%-4d%-20s%s\n",
1336 surf->info.size / 1024,
1340 _tbm_surface_internal_format_to_str(surf->info.format),
1343 for (i = 0; i < surf->num_bos; i++) {
1344 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1346 surf->bos[i]->ref_cnt,
1347 tbm_bo_size(surf->bos[i]) / 1024);
1350 memset(app_name, 0x0, 255 * sizeof(char));
1353 TBM_DEBUG("no tbm_surfaces.\n");
1357 TBM_DEBUG("[tbm_bo information]\n");
1358 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1360 /* show the tbm_bo information in bo_list */
1361 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1362 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1363 TBM_DEBUG("%-4d%-11p %-6d%-12d%-9d%-9d%-4d%-11p\n",
1367 tbm_bo_size(bo) / 1024,
1374 TBM_DEBUG("no tbm_bos.\n");
1378 TBM_DEBUG("===============================================================\n");
1380 pthread_mutex_unlock(&gLock);
1385 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1388 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1393 /* internal function */
1395 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1397 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1399 bo->surface = surface;
1405 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1407 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1411 pthread_mutex_lock(&bufmgr->lock);
1413 if (!bufmgr->backend->bufmgr_bind_native_display) {
1414 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1415 pthread_mutex_unlock(&bufmgr->lock);
1419 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1421 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1422 pthread_mutex_unlock(&bufmgr->lock);
1426 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1428 pthread_mutex_unlock(&bufmgr->lock);
1432 /* LCOV_EXCL_STOP */