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"
53 #define PREFIX_LIB "libtbm_"
54 #define SUFFIX_LIB ".so"
55 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
57 /* values to indicate unspecified fields in XF86ModReqInfo. */
58 #define MAJOR_UNSPEC 0xFF
59 #define MINOR_UNSPEC 0xFF
60 #define PATCH_UNSPEC 0xFFFF
61 #define ABI_VERS_UNSPEC 0xFFFFFFFF
63 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
64 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
65 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
66 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
67 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
75 pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
78 static __thread tbm_error_e tbm_last_error = TBM_ERROR_NONE;
81 _tbm_set_last_result(tbm_error_e err)
86 char * tbm_flag_to_str(int f)
90 if (f == TBM_BO_DEFAULT)
91 snprintf(str, 255, "DEFAULT\n");
93 if (f & TBM_BO_SCANOUT)
94 c = snprintf(&str[c], 255, "SCANOUT,");
95 if (f & TBM_BO_NONCACHABLE)
96 c = snprintf(&str[c], 255, "NONCACHABLE,");
98 c = snprintf(&str[c], 255, "WC");
103 /* LCOV_EXCL_START */
104 static int last_chk_bo_cnt = 0;
106 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
108 if (bufmgr->bo_cnt >= 500 && ((bufmgr->bo_cnt % 20) == 0)) {
109 if (bufmgr->bo_cnt > last_chk_bo_cnt) {
110 TBM_DEBUG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
111 tbm_bufmgr_debug_show(bufmgr);
112 last_chk_bo_cnt = bufmgr->bo_cnt;
118 _tbm_util_get_max_surface_size(int * w, int * h)
121 tbm_surface_h surface = NULL, tmp = NULL;
122 tbm_surface_info_s info;
130 if (!LIST_IS_EMPTY(&gBufMgr->surf_list)) {
131 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
132 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
134 if (*w < info.width) *w = info.width;
135 if (*h < info.height) *h = info.height;
144 _tbm_util_get_appname_brief(char *brief)
148 char temp[255] = {0,};
149 char *saveptr = NULL;
151 token = strtok_r(brief, delim, &saveptr);
153 while (token != NULL) {
154 memset(temp, 0x00, 255 * sizeof(char));
155 strncpy(temp, token, 254 * sizeof(char));
156 token = strtok_r(NULL, delim, &saveptr);
159 snprintf(brief, sizeof(temp), "%s", temp);
163 _tbm_util_get_appname_from_pid(long pid, char *str)
168 char fn_cmdline[255] = {0,};
169 char cmdline[255] = {0,};
171 snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", app_pid);
173 fp = fopen(fn_cmdline, "r");
175 fprintf(stderr, "cannot file open /proc/%ld/cmdline", app_pid);
179 if (!fgets(cmdline, 255, fp)) {
180 fprintf(stderr, "fail to get appname for pid(%ld)\n", app_pid);
186 len = strlen(cmdline);
188 memset(cmdline, 0x00, 255);
192 snprintf(str, sizeof(cmdline), "%s", cmdline);
197 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
199 tbm_user_data *user_data = NULL;
200 tbm_user_data *old_data = NULL, *tmp = NULL;
202 if (!LIST_IS_EMPTY(user_data_list)) {
203 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, user_data_list, item_link) {
204 if (old_data->key == key) {
205 user_data = old_data;
215 *user_data_create(unsigned long key, tbm_data_free data_free_func)
217 tbm_user_data *user_data = NULL;
219 user_data = calloc(1, sizeof(tbm_user_data));
223 user_data->key = key;
224 user_data->free_func = data_free_func;
225 user_data->data = (void *)0;
231 user_data_delete(tbm_user_data *user_data)
233 if (user_data->data && user_data->free_func)
234 user_data->free_func(user_data->data);
236 LIST_DEL(&user_data->item_link);
242 _bo_lock(tbm_bo bo, int device, int opt)
244 tbm_bufmgr bufmgr = bo->bufmgr;
247 if (bufmgr->backend->bo_lock)
248 ret = bufmgr->backend->bo_lock(bo, device, opt);
256 _bo_unlock(tbm_bo bo)
258 tbm_bufmgr bufmgr = bo->bufmgr;
260 if (bufmgr->backend->bo_unlock)
261 bufmgr->backend->bo_unlock(bo);
265 _tbm_bo_lock(tbm_bo bo, int device, int opt)
267 tbm_bufmgr bufmgr = NULL;
276 /* do not try to lock the bo */
277 if (bufmgr->lock_type == LOCK_TRY_NEVER)
280 if (bo->lock_cnt < 0) {
281 TBM_LOG_E("error bo:%p LOCK_CNT=%d\n",
286 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
287 if (bo->lock_cnt == 0) {
288 pthread_mutex_unlock(&bufmgr->lock);
289 ret = _bo_lock(bo, device, opt);
290 pthread_mutex_lock(&bufmgr->lock);
295 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
296 pthread_mutex_unlock(&bufmgr->lock);
297 ret = _bo_lock(bo, device, opt);
298 pthread_mutex_lock(&bufmgr->lock);
302 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
306 DBG_LOCK(">> LOCK bo:%p(%d->%d)\n",
307 bo, old, bo->lock_cnt);
313 _tbm_bo_unlock(tbm_bo bo)
315 tbm_bufmgr bufmgr = NULL;
324 /* do not try to unlock the bo */
325 if (bufmgr->lock_type == LOCK_TRY_NEVER)
329 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
330 if (bo->lock_cnt > 0) {
332 if (bo->lock_cnt == 0)
335 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
336 if (bo->lock_cnt > 0) {
341 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
345 if (bo->lock_cnt < 0)
348 DBG_LOCK(">> UNLOCK bo:%p(%d->%d)\n",
349 bo, old, bo->lock_cnt);
353 _tbm_bo_is_valid(tbm_bo bo)
355 tbm_bo old_data = NULL, tmp = NULL;
360 if (!LIST_IS_EMPTY(&gBufMgr->bo_list)) {
361 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &gBufMgr->bo_list, item_link) {
371 _tbm_bo_ref(tbm_bo bo)
377 _tbm_bo_unref(tbm_bo bo)
379 tbm_bufmgr bufmgr = bo->bufmgr;
380 tbm_user_data *old_data = NULL, *tmp = NULL;
382 if (bo->ref_cnt <= 0)
386 if (bo->ref_cnt == 0) {
387 /* destory the user_data_list */
388 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
389 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
390 DBG("free user_data\n");
391 user_data_delete(old_data);
395 if (bo->lock_cnt > 0) {
396 TBM_LOG_E("error lock_cnt:%d\n",
401 /* call the bo_free */
402 bufmgr->backend->bo_free(bo);
405 LIST_DEL(&bo->item_link);
414 /* LCOV_EXCL_START */
416 _check_version(TBMModuleVersionInfo *data)
421 abimaj = GET_ABI_MAJOR(data->abiversion);
422 abimin = GET_ABI_MINOR(data->abiversion);
424 DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
425 data->modname ? data->modname : "UNKNOWN!",
426 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
428 vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
429 vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
431 DBG("TBM ABI version %d.%d\n",
434 if (abimaj != vermaj) {
435 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
438 } else if (abimin > vermin) {
439 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
447 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
449 char path[PATH_MAX] = { 0, };
450 TBMModuleData *initdata = NULL;
453 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
455 module_data = dlopen(path, RTLD_LAZY);
457 TBM_LOG_E("failed to load module: %s(%s)\n",
462 initdata = dlsym(module_data, "tbmModuleData");
465 TBMModuleVersionInfo *vers;
467 vers = initdata->vers;
468 init = initdata->init;
471 if (!_check_version(vers)) {
472 dlclose(module_data);
476 TBM_LOG_E("Error: module does not supply version information.\n");
478 dlclose(module_data);
483 if (!init(bufmgr, fd)) {
484 TBM_LOG_E("Fail to init module(%s)\n",
486 dlclose(module_data);
490 if (!bufmgr->backend || !bufmgr->backend->priv) {
491 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n",
493 dlclose(module_data);
497 TBM_LOG_E("Error: module does not supply init symbol.\n");
498 dlclose(module_data);
502 TBM_LOG_E("Error: module does not have data object.\n");
503 dlclose(module_data);
507 bufmgr->module_data = module_data;
509 DBG("Success to load module(%s)\n",
516 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
518 struct dirent **namelist;
519 const char *p = NULL;
523 /* load bufmgr priv from default lib */
524 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
526 /* load bufmgr priv from configured path */
528 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
530 TBM_LOG_E("no files : %s\n",
534 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
535 p = strstr(namelist[n]->d_name, SUFFIX_LIB);
536 if (p && !strcmp(p, SUFFIX_LIB))
537 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
550 tbm_bufmgr_init(int fd)
554 pthread_mutex_lock(&gLock);
556 /* LCOV_EXCL_START */
558 env = getenv("TBM_DLOG");
561 TBM_LOG_D("TBM_DLOG=%s\n", env);
568 env = getenv("TBM_DEBUG");
571 TBM_LOG_D("TBM_DEBUG=%s\n", env);
578 env = getenv("TBM_TRACE");
581 TBM_LOG_D("TBM_TRACE=%s\n", env);
588 /* initialize buffer manager */
590 gBufMgr->ref_count++;
591 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
592 pthread_mutex_unlock(&gLock);
596 DBG("bufmgr init\n");
598 /* allocate bufmgr */
599 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
601 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
602 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
603 pthread_mutex_unlock(&gLock);
609 /* load bufmgr priv from env */
610 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
611 /* LCOV_EXCL_START */
612 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
613 TBM_LOG_E("error : Fail to load bufmgr backend\n");
616 pthread_mutex_unlock(&gLock);
621 /* log for tbm backend_flag */
622 DBG("backend flag:%x:", gBufMgr->backend->flags);
625 gBufMgr->ref_count = 1;
627 DBG("create tizen bufmgr:%p ref_count:%d\n",
628 gBufMgr, gBufMgr->ref_count);
630 if (pthread_mutex_init(&gBufMgr->lock, NULL) != 0) {
631 /* LCOV_EXCL_START */
632 _tbm_set_last_result(TBM_BO_ERROR_THREAD_INIT_FAILED);
633 gBufMgr->backend->bufmgr_deinit(gBufMgr->backend->priv);
634 tbm_backend_free(gBufMgr->backend);
635 dlclose(gBufMgr->module_data);
638 pthread_mutex_unlock(&gLock);
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);
673 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
675 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
680 tbm_surface_h surf = NULL;
681 tbm_surface_h tmp_surf = NULL;
683 pthread_mutex_lock(&gLock);
686 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
687 pthread_mutex_unlock(&gLock);
692 if (bufmgr->ref_count > 0) {
693 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
694 pthread_mutex_unlock(&gLock);
698 /* destroy bo_list */
699 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
700 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
701 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
708 /* destroy surf_list */
709 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
710 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
711 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
713 tbm_surface_destroy(surf);
717 /* destroy bufmgr priv */
718 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
719 bufmgr->backend->priv = NULL;
720 tbm_backend_free(bufmgr->backend);
721 bufmgr->backend = NULL;
723 pthread_mutex_destroy(&bufmgr->lock);
725 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
727 dlclose(bufmgr->module_data);
736 pthread_mutex_unlock(&gLock);
740 tbm_bo_size(tbm_bo bo)
742 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
744 tbm_bufmgr bufmgr = bo->bufmgr;
747 pthread_mutex_lock(&bufmgr->lock);
749 size = bufmgr->backend->bo_size(bo);
751 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
753 pthread_mutex_unlock(&bufmgr->lock);
759 tbm_bo_ref(tbm_bo bo)
761 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
763 tbm_bufmgr bufmgr = bo->bufmgr;
765 pthread_mutex_lock(&bufmgr->lock);
769 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
771 pthread_mutex_unlock(&bufmgr->lock);
777 tbm_bo_unref(tbm_bo bo)
779 TBM_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
781 tbm_bufmgr bufmgr = bo->bufmgr;
783 pthread_mutex_lock(&bufmgr->lock);
785 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
789 pthread_mutex_unlock(&bufmgr->lock);
793 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
795 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
798 void *bo_priv = NULL;
800 bo = calloc(1, sizeof(struct _tbm_bo));
802 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
803 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
807 _tbm_util_check_bo_cnt(bufmgr);
812 pthread_mutex_lock(&bufmgr->lock);
814 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
816 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
817 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
819 pthread_mutex_unlock(&bufmgr->lock);
827 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
829 LIST_INITHEAD(&bo->user_data_list);
831 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
833 pthread_mutex_unlock(&bufmgr->lock);
839 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
841 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
846 void *bo_priv = NULL;
848 _tbm_util_check_bo_cnt(bufmgr);
850 pthread_mutex_lock(&bufmgr->lock);
852 bo = calloc(1, sizeof(struct _tbm_bo));
854 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
855 pthread_mutex_unlock(&bufmgr->lock);
863 bo_priv = bufmgr->backend->bo_import(bo, key);
865 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
866 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
868 pthread_mutex_unlock(&bufmgr->lock);
872 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
873 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
874 if (bo2->priv == bo_priv) {
875 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
876 bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
879 pthread_mutex_unlock(&bufmgr->lock);
888 if (bufmgr->backend->bo_get_flags)
889 bo->flags = bufmgr->backend->bo_get_flags(bo);
891 bo->flags = TBM_BO_DEFAULT;
893 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
894 bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
896 LIST_INITHEAD(&bo->user_data_list);
898 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
900 pthread_mutex_unlock(&bufmgr->lock);
906 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
908 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
913 void *bo_priv = NULL;
915 _tbm_util_check_bo_cnt(bufmgr);
917 pthread_mutex_lock(&bufmgr->lock);
919 bo = calloc(1, sizeof(struct _tbm_bo));
921 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
922 pthread_mutex_unlock(&bufmgr->lock);
930 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
932 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
933 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
935 pthread_mutex_unlock(&bufmgr->lock);
939 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
940 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
941 if (bo2->priv == bo_priv) {
942 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
943 bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
946 pthread_mutex_unlock(&bufmgr->lock);
955 if (bufmgr->backend->bo_get_flags)
956 bo->flags = bufmgr->backend->bo_get_flags(bo);
958 bo->flags = TBM_BO_DEFAULT;
960 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
961 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
963 LIST_INITHEAD(&bo->user_data_list);
965 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
967 pthread_mutex_unlock(&bufmgr->lock);
973 tbm_bo_export(tbm_bo bo)
975 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
982 pthread_mutex_lock(&bufmgr->lock);
984 ret = bufmgr->backend->bo_export(bo);
986 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
987 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
988 pthread_mutex_unlock(&bufmgr->lock);
992 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
994 pthread_mutex_unlock(&bufmgr->lock);
1000 tbm_bo_export_fd(tbm_bo bo)
1002 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1007 bufmgr = bo->bufmgr;
1009 pthread_mutex_lock(&bufmgr->lock);
1011 ret = bufmgr->backend->bo_export_fd(bo);
1013 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1014 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1015 pthread_mutex_unlock(&bufmgr->lock);
1019 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1021 pthread_mutex_unlock(&bufmgr->lock);
1027 tbm_bo_get_handle(tbm_bo bo, int device)
1029 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1032 tbm_bo_handle bo_handle;
1034 bufmgr = bo->bufmgr;
1036 pthread_mutex_lock(&bufmgr->lock);
1038 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1039 if (bo_handle.ptr == NULL) {
1040 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1041 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1042 pthread_mutex_unlock(&bufmgr->lock);
1043 return (tbm_bo_handle) NULL;
1046 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1048 pthread_mutex_unlock(&bufmgr->lock);
1054 tbm_bo_map(tbm_bo bo, int device, int opt)
1056 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1059 tbm_bo_handle bo_handle;
1061 bufmgr = bo->bufmgr;
1063 pthread_mutex_lock(&bufmgr->lock);
1065 if (!_tbm_bo_lock(bo, device, opt)) {
1066 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1067 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1068 pthread_mutex_unlock(&bufmgr->lock);
1069 return (tbm_bo_handle) NULL;
1072 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1073 if (bo_handle.ptr == NULL) {
1074 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1075 TBM_TRACE("error: fail to map bo:%p\n", bo);
1077 pthread_mutex_unlock(&bufmgr->lock);
1078 return (tbm_bo_handle) NULL;
1081 /* increase the map_count */
1084 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1086 pthread_mutex_unlock(&bufmgr->lock);
1092 tbm_bo_unmap(tbm_bo bo)
1094 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1099 bufmgr = bo->bufmgr;
1101 pthread_mutex_lock(&bufmgr->lock);
1103 ret = bufmgr->backend->bo_unmap(bo);
1105 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1106 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1107 pthread_mutex_unlock(&bufmgr->lock);
1111 /* decrease the map_count */
1114 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1118 pthread_mutex_unlock(&bufmgr->lock);
1124 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1126 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1127 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1131 pthread_mutex_lock(&bo1->bufmgr->lock);
1133 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1135 if (bo1->bufmgr->backend->bo_size(bo1) != bo2->bufmgr->backend->bo_size(bo2)) {
1136 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1137 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1138 pthread_mutex_unlock(&bo1->bufmgr->lock);
1142 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1145 bo1->priv = bo2->priv;
1148 pthread_mutex_unlock(&bo1->bufmgr->lock);
1154 tbm_bo_locked(tbm_bo bo)
1156 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1160 bufmgr = bo->bufmgr;
1162 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1163 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1167 pthread_mutex_lock(&bufmgr->lock);
1170 if (bo->lock_cnt > 0) {
1171 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1172 pthread_mutex_unlock(&bufmgr->lock);
1176 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1177 pthread_mutex_unlock(&bufmgr->lock);
1183 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1184 tbm_data_free data_free_func)
1186 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1188 tbm_user_data *data;
1190 /* check if the data according to the key exist if so, return false. */
1191 data = user_data_lookup(&bo->user_data_list, key);
1193 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1197 data = user_data_create(key, data_free_func);
1199 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1203 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1205 LIST_ADD(&data->item_link, &bo->user_data_list);
1211 tbm_bo_set_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 (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);
1228 if (old_data->data && old_data->free_func)
1229 old_data->free_func(old_data->data);
1231 old_data->data = data;
1233 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1239 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1241 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1243 tbm_user_data *old_data;
1245 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1246 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1250 old_data = user_data_lookup(&bo->user_data_list, key);
1252 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1257 *data = old_data->data;
1259 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1265 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1267 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1269 tbm_user_data *old_data = (void *)0;
1271 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1272 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1276 old_data = user_data_lookup(&bo->user_data_list, key);
1278 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1282 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1284 user_data_delete(old_data);
1290 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1292 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1294 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1296 return bufmgr->capabilities;
1300 tbm_bo_get_flags(tbm_bo bo)
1302 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1304 TBM_TRACE("bo(%p)\n", bo);
1309 /* LCOV_EXCL_START */
1311 tbm_get_last_error(void)
1313 return tbm_last_error;
1317 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1319 TBM_RETURN_IF_FAIL(bufmgr != NULL);
1320 tbm_bo bo = NULL, tmp_bo = NULL;
1323 tbm_surface_h surf = NULL, tmp_surf = NULL;
1326 char app_name[255] = {0,};
1327 unsigned int pid = 0;
1328 char title[255] = {0,};
1329 char data[255] = {0,};
1330 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1332 pthread_mutex_lock(&gLock);
1335 _tbm_util_get_appname_from_pid(getpid(), app_name);
1336 _tbm_util_get_appname_brief(app_name);
1337 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1338 app_name, getpid());
1339 memset(app_name, 0x0, 255 * sizeof(char));
1340 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1341 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1342 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1343 strncat(title, " ", 2);
1344 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1348 TBM_DEBUG("[tbm_surface information]\n");
1349 TBM_DEBUG("%s\n", title);
1350 /* show the tbm_surface information in surf_list */
1351 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1354 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1355 pid = _tbm_surface_internal_get_debug_pid(surf);
1357 /* if pid is null, set the self_pid */
1361 _tbm_util_get_appname_from_pid(pid, app_name);
1362 _tbm_util_get_appname_brief(app_name);
1364 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1371 surf->info.size / 1024,
1375 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1378 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1379 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1380 strncat(data, " ", 2);
1382 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1384 strncat(data, value, strlen(value) + 1);
1386 strncat(data, "none", strlen("none") + 1);
1389 TBM_DEBUG("%s\n", data);
1391 for (i = 0; i < surf->num_bos; i++) {
1392 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1394 surf->bos[i]->ref_cnt,
1395 tbm_bo_size(surf->bos[i]) / 1024);
1398 memset(app_name, 0x0, 255 * sizeof(char));
1401 TBM_DEBUG("no tbm_surfaces.\n");
1405 TBM_DEBUG("[tbm_bo information]\n");
1406 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1408 /* show the tbm_bo information in bo_list */
1409 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1410 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1411 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1415 tbm_bo_size(bo) / 1024,
1422 TBM_DEBUG("no tbm_bos.\n");
1426 TBM_DEBUG("===============================================================\n");
1428 pthread_mutex_unlock(&gLock);
1433 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1436 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1442 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1444 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1448 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1451 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1452 TBM_LOG_I("No tbm_surface.\n");
1456 tbm_surface_internal_dump_start(path, w, h, count);
1459 } else if (onoff == 0) {
1461 tbm_surface_internal_dump_end();
1472 tbm_bufmgr_debug_dump_all(char *path)
1474 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1476 TBM_LOG_D("path=%s\n", path);
1477 int w = 0, h = 0, count = 0;
1478 tbm_surface_h surface = NULL, tmp = NULL;
1480 count = _tbm_util_get_max_surface_size(&w, &h);
1482 TBM_LOG_I("No tbm_surface.\n");
1486 tbm_surface_internal_dump_start(path, w, h, count);
1488 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1489 tbm_surface_internal_dump_buffer(surface, "dump_all");
1492 tbm_surface_internal_dump_end();
1498 /* internal function */
1500 _tbm_bufmgr_get_bufmgr(void)
1506 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1508 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1510 bo->surface = surface;
1516 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1518 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1522 pthread_mutex_lock(&bufmgr->lock);
1524 if (!bufmgr->backend->bufmgr_bind_native_display) {
1525 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1526 pthread_mutex_unlock(&bufmgr->lock);
1530 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1532 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1533 pthread_mutex_unlock(&bufmgr->lock);
1537 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1539 pthread_mutex_unlock(&bufmgr->lock);
1543 /* LCOV_EXCL_STOP */