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 (gBufMgr == NULL) {
361 TBM_LOG_E("error tbm_bufmgr was deinited\n");
365 if (!LIST_IS_EMPTY(&gBufMgr->bo_list)) {
366 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &gBufMgr->bo_list, item_link) {
376 _tbm_bo_ref(tbm_bo bo)
382 _tbm_bo_unref(tbm_bo bo)
384 tbm_bufmgr bufmgr = bo->bufmgr;
385 tbm_user_data *old_data = NULL, *tmp = NULL;
387 if (bo->ref_cnt <= 0)
391 if (bo->ref_cnt == 0) {
392 /* destory the user_data_list */
393 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
394 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
395 DBG("free user_data\n");
396 user_data_delete(old_data);
400 if (bo->lock_cnt > 0) {
401 TBM_LOG_E("error lock_cnt:%d\n",
406 /* call the bo_free */
407 bufmgr->backend->bo_free(bo);
410 LIST_DEL(&bo->item_link);
419 /* LCOV_EXCL_START */
421 _check_version(TBMModuleVersionInfo *data)
426 abimaj = GET_ABI_MAJOR(data->abiversion);
427 abimin = GET_ABI_MINOR(data->abiversion);
429 DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
430 data->modname ? data->modname : "UNKNOWN!",
431 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
433 vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
434 vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
436 DBG("TBM ABI version %d.%d\n",
439 if (abimaj != vermaj) {
440 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
443 } else if (abimin > vermin) {
444 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
452 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
454 char path[PATH_MAX] = { 0, };
455 TBMModuleData *initdata = NULL;
458 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
460 module_data = dlopen(path, RTLD_LAZY);
462 TBM_LOG_E("failed to load module: %s(%s)\n",
467 initdata = dlsym(module_data, "tbmModuleData");
470 TBMModuleVersionInfo *vers;
472 vers = initdata->vers;
473 init = initdata->init;
476 if (!_check_version(vers)) {
477 dlclose(module_data);
481 TBM_LOG_E("Error: module does not supply version information.\n");
483 dlclose(module_data);
488 if (!init(bufmgr, fd)) {
489 TBM_LOG_E("Fail to init module(%s)\n",
491 dlclose(module_data);
495 if (!bufmgr->backend || !bufmgr->backend->priv) {
496 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n",
498 dlclose(module_data);
502 TBM_LOG_E("Error: module does not supply init symbol.\n");
503 dlclose(module_data);
507 TBM_LOG_E("Error: module does not have data object.\n");
508 dlclose(module_data);
512 bufmgr->module_data = module_data;
514 DBG("Success to load module(%s)\n",
521 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
523 struct dirent **namelist;
524 const char *p = NULL;
528 /* load bufmgr priv from default lib */
529 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
531 /* load bufmgr priv from configured path */
533 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
535 TBM_LOG_E("no files : %s\n",
539 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
540 p = strstr(namelist[n]->d_name, SUFFIX_LIB);
541 if (p && !strcmp(p, SUFFIX_LIB))
542 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
555 tbm_bufmgr_init(int fd)
559 pthread_mutex_lock(&gLock);
561 /* LCOV_EXCL_START */
563 env = getenv("TBM_DLOG");
566 TBM_LOG_D("TBM_DLOG=%s\n", env);
573 env = getenv("TBM_DEBUG");
576 TBM_LOG_D("TBM_DEBUG=%s\n", env);
583 env = getenv("TBM_TRACE");
586 TBM_LOG_D("TBM_TRACE=%s\n", env);
593 /* initialize buffer manager */
595 gBufMgr->ref_count++;
596 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
597 pthread_mutex_unlock(&gLock);
601 DBG("bufmgr init\n");
603 /* allocate bufmgr */
604 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
606 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
607 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
608 pthread_mutex_unlock(&gLock);
614 /* load bufmgr priv from env */
615 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
616 /* LCOV_EXCL_START */
617 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
618 TBM_LOG_E("error : Fail to load bufmgr backend\n");
621 pthread_mutex_unlock(&gLock);
626 /* log for tbm backend_flag */
627 DBG("backend flag:%x:", gBufMgr->backend->flags);
630 gBufMgr->ref_count = 1;
632 DBG("create tizen bufmgr:%p ref_count:%d\n",
633 gBufMgr, gBufMgr->ref_count);
635 if (pthread_mutex_init(&gBufMgr->lock, NULL) != 0) {
636 /* LCOV_EXCL_START */
637 _tbm_set_last_result(TBM_BO_ERROR_THREAD_INIT_FAILED);
638 gBufMgr->backend->bufmgr_deinit(gBufMgr->backend->priv);
639 tbm_backend_free(gBufMgr->backend);
640 dlclose(gBufMgr->module_data);
643 pthread_mutex_unlock(&gLock);
648 /* setup the lock_type */
649 env = getenv("BUFMGR_LOCK_TYPE");
650 if (env && !strcmp(env, "always"))
651 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
652 else if (env && !strcmp(env, "none"))
653 gBufMgr->lock_type = LOCK_TRY_NEVER;
654 else if (env && !strcmp(env, "once"))
655 gBufMgr->lock_type = LOCK_TRY_ONCE;
657 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
659 DBG("BUFMGR_LOCK_TYPE=%s\n",
660 env ? env : "default:once");
662 TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
664 /* intialize bo_list */
665 LIST_INITHEAD(&gBufMgr->bo_list);
667 /* intialize surf_list */
668 LIST_INITHEAD(&gBufMgr->surf_list);
670 /* intialize debug_key_list */
671 LIST_INITHEAD(&gBufMgr->debug_key_list);
673 pthread_mutex_unlock(&gLock);
678 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
680 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
685 tbm_surface_h surf = NULL;
686 tbm_surface_h tmp_surf = NULL;
688 pthread_mutex_lock(&gLock);
691 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
692 pthread_mutex_unlock(&gLock);
697 if (bufmgr->ref_count > 0) {
698 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
699 pthread_mutex_unlock(&gLock);
703 /* destroy bo_list */
704 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
705 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
706 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
713 /* destroy surf_list */
714 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
715 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
716 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
718 tbm_surface_destroy(surf);
722 /* destroy bufmgr priv */
723 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
724 bufmgr->backend->priv = NULL;
725 tbm_backend_free(bufmgr->backend);
726 bufmgr->backend = NULL;
728 pthread_mutex_destroy(&bufmgr->lock);
730 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
732 dlclose(bufmgr->module_data);
741 pthread_mutex_unlock(&gLock);
745 tbm_bo_size(tbm_bo bo)
747 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
749 tbm_bufmgr bufmgr = bo->bufmgr;
752 pthread_mutex_lock(&bufmgr->lock);
754 size = bufmgr->backend->bo_size(bo);
756 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
758 pthread_mutex_unlock(&bufmgr->lock);
764 tbm_bo_ref(tbm_bo bo)
766 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
768 tbm_bufmgr bufmgr = bo->bufmgr;
770 pthread_mutex_lock(&bufmgr->lock);
774 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
776 pthread_mutex_unlock(&bufmgr->lock);
782 tbm_bo_unref(tbm_bo bo)
784 TBM_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
786 tbm_bufmgr bufmgr = bo->bufmgr;
788 pthread_mutex_lock(&bufmgr->lock);
790 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
794 pthread_mutex_unlock(&bufmgr->lock);
798 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
800 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
803 void *bo_priv = NULL;
805 bo = calloc(1, sizeof(struct _tbm_bo));
807 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
808 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
812 _tbm_util_check_bo_cnt(bufmgr);
817 pthread_mutex_lock(&bufmgr->lock);
819 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
821 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
822 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
824 pthread_mutex_unlock(&bufmgr->lock);
832 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
834 LIST_INITHEAD(&bo->user_data_list);
836 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
838 pthread_mutex_unlock(&bufmgr->lock);
844 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
846 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
851 void *bo_priv = NULL;
853 _tbm_util_check_bo_cnt(bufmgr);
855 if (!bufmgr->backend->bo_import)
858 pthread_mutex_lock(&bufmgr->lock);
860 bo = calloc(1, sizeof(struct _tbm_bo));
862 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
863 pthread_mutex_unlock(&bufmgr->lock);
871 bo_priv = bufmgr->backend->bo_import(bo, key);
873 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
874 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
876 pthread_mutex_unlock(&bufmgr->lock);
880 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
881 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
882 if (bo2->priv == bo_priv) {
883 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
884 bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
887 pthread_mutex_unlock(&bufmgr->lock);
896 if (bufmgr->backend->bo_get_flags)
897 bo->flags = bufmgr->backend->bo_get_flags(bo);
899 bo->flags = TBM_BO_DEFAULT;
901 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
902 bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
904 LIST_INITHEAD(&bo->user_data_list);
906 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
908 pthread_mutex_unlock(&bufmgr->lock);
914 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
916 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
921 void *bo_priv = NULL;
923 _tbm_util_check_bo_cnt(bufmgr);
925 if (!bufmgr->backend->bo_import_fd)
928 pthread_mutex_lock(&bufmgr->lock);
930 bo = calloc(1, sizeof(struct _tbm_bo));
932 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
933 pthread_mutex_unlock(&bufmgr->lock);
941 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
943 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
944 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
946 pthread_mutex_unlock(&bufmgr->lock);
950 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
951 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
952 if (bo2->priv == bo_priv) {
953 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
954 bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
957 pthread_mutex_unlock(&bufmgr->lock);
966 if (bufmgr->backend->bo_get_flags)
967 bo->flags = bufmgr->backend->bo_get_flags(bo);
969 bo->flags = TBM_BO_DEFAULT;
971 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
972 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
974 LIST_INITHEAD(&bo->user_data_list);
976 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
978 pthread_mutex_unlock(&bufmgr->lock);
984 tbm_bo_export(tbm_bo bo)
986 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
993 if (!bufmgr->backend->bo_export)
996 pthread_mutex_lock(&bufmgr->lock);
998 ret = bufmgr->backend->bo_export(bo);
1000 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1001 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1002 pthread_mutex_unlock(&bufmgr->lock);
1006 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
1008 pthread_mutex_unlock(&bufmgr->lock);
1014 tbm_bo_export_fd(tbm_bo bo)
1016 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1021 bufmgr = bo->bufmgr;
1023 if (!bufmgr->backend->bo_export_fd)
1026 pthread_mutex_lock(&bufmgr->lock);
1028 ret = bufmgr->backend->bo_export_fd(bo);
1030 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1031 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1032 pthread_mutex_unlock(&bufmgr->lock);
1036 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1038 pthread_mutex_unlock(&bufmgr->lock);
1044 tbm_bo_get_handle(tbm_bo bo, int device)
1046 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1049 tbm_bo_handle bo_handle;
1051 bufmgr = bo->bufmgr;
1053 pthread_mutex_lock(&bufmgr->lock);
1055 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1056 if (bo_handle.ptr == NULL) {
1057 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1058 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1059 pthread_mutex_unlock(&bufmgr->lock);
1060 return (tbm_bo_handle) NULL;
1063 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1065 pthread_mutex_unlock(&bufmgr->lock);
1071 tbm_bo_map(tbm_bo bo, int device, int opt)
1073 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1076 tbm_bo_handle bo_handle;
1078 bufmgr = bo->bufmgr;
1080 pthread_mutex_lock(&bufmgr->lock);
1082 if (!_tbm_bo_lock(bo, device, opt)) {
1083 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1084 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1085 pthread_mutex_unlock(&bufmgr->lock);
1086 return (tbm_bo_handle) NULL;
1089 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1090 if (bo_handle.ptr == NULL) {
1091 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1092 TBM_TRACE("error: fail to map bo:%p\n", bo);
1094 pthread_mutex_unlock(&bufmgr->lock);
1095 return (tbm_bo_handle) NULL;
1098 /* increase the map_count */
1101 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1103 pthread_mutex_unlock(&bufmgr->lock);
1109 tbm_bo_unmap(tbm_bo bo)
1111 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1116 bufmgr = bo->bufmgr;
1118 pthread_mutex_lock(&bufmgr->lock);
1120 ret = bufmgr->backend->bo_unmap(bo);
1122 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1123 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1124 pthread_mutex_unlock(&bufmgr->lock);
1128 /* decrease the map_count */
1131 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1135 pthread_mutex_unlock(&bufmgr->lock);
1141 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1143 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1144 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1148 pthread_mutex_lock(&bo1->bufmgr->lock);
1150 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1152 if (bo1->bufmgr->backend->bo_size(bo1) != bo2->bufmgr->backend->bo_size(bo2)) {
1153 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1154 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1155 pthread_mutex_unlock(&bo1->bufmgr->lock);
1159 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1162 bo1->priv = bo2->priv;
1165 pthread_mutex_unlock(&bo1->bufmgr->lock);
1171 tbm_bo_locked(tbm_bo bo)
1173 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1177 bufmgr = bo->bufmgr;
1179 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1180 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1184 pthread_mutex_lock(&bufmgr->lock);
1187 if (bo->lock_cnt > 0) {
1188 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1189 pthread_mutex_unlock(&bufmgr->lock);
1193 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1194 pthread_mutex_unlock(&bufmgr->lock);
1200 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1201 tbm_data_free data_free_func)
1203 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1205 tbm_user_data *data;
1207 /* check if the data according to the key exist if so, return false. */
1208 data = user_data_lookup(&bo->user_data_list, key);
1210 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1214 data = user_data_create(key, data_free_func);
1216 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1220 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1222 LIST_ADD(&data->item_link, &bo->user_data_list);
1228 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1230 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1232 tbm_user_data *old_data;
1234 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1235 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1239 old_data = user_data_lookup(&bo->user_data_list, key);
1241 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1245 if (old_data->data && old_data->free_func)
1246 old_data->free_func(old_data->data);
1248 old_data->data = data;
1250 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1256 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1258 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1260 tbm_user_data *old_data;
1262 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1263 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1267 old_data = user_data_lookup(&bo->user_data_list, key);
1269 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1274 *data = old_data->data;
1276 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1282 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1284 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1286 tbm_user_data *old_data = (void *)0;
1288 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1289 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1293 old_data = user_data_lookup(&bo->user_data_list, key);
1295 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1299 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1301 user_data_delete(old_data);
1307 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1309 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1311 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1313 return bufmgr->capabilities;
1317 tbm_bo_get_flags(tbm_bo bo)
1319 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1321 TBM_TRACE("bo(%p)\n", bo);
1326 /* LCOV_EXCL_START */
1328 tbm_get_last_error(void)
1330 return tbm_last_error;
1334 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1336 TBM_RETURN_IF_FAIL(bufmgr != NULL);
1337 tbm_bo bo = NULL, tmp_bo = NULL;
1340 tbm_surface_h surf = NULL, tmp_surf = NULL;
1343 char app_name[255] = {0,};
1344 unsigned int pid = 0;
1345 char title[255] = {0,};
1346 char data[255] = {0,};
1347 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1349 pthread_mutex_lock(&gLock);
1352 _tbm_util_get_appname_from_pid(getpid(), app_name);
1353 _tbm_util_get_appname_brief(app_name);
1354 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1355 app_name, getpid());
1356 memset(app_name, 0x0, 255 * sizeof(char));
1357 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1358 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1359 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1360 strncat(title, " ", 2);
1361 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1365 TBM_DEBUG("[tbm_surface information]\n");
1366 TBM_DEBUG("%s\n", title);
1367 /* show the tbm_surface information in surf_list */
1368 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1371 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1372 pid = _tbm_surface_internal_get_debug_pid(surf);
1374 /* if pid is null, set the self_pid */
1378 _tbm_util_get_appname_from_pid(pid, app_name);
1379 _tbm_util_get_appname_brief(app_name);
1381 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1388 surf->info.size / 1024,
1392 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1395 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1396 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1397 strncat(data, " ", 2);
1399 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1401 strncat(data, value, strlen(value) + 1);
1403 strncat(data, "none", strlen("none") + 1);
1406 TBM_DEBUG("%s\n", data);
1408 for (i = 0; i < surf->num_bos; i++) {
1409 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1411 surf->bos[i]->ref_cnt,
1412 tbm_bo_size(surf->bos[i]) / 1024);
1415 memset(app_name, 0x0, 255 * sizeof(char));
1418 TBM_DEBUG("no tbm_surfaces.\n");
1422 TBM_DEBUG("[tbm_bo information]\n");
1423 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1425 /* show the tbm_bo information in bo_list */
1426 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1427 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1428 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1432 tbm_bo_size(bo) / 1024,
1439 TBM_DEBUG("no tbm_bos.\n");
1443 TBM_DEBUG("===============================================================\n");
1445 pthread_mutex_unlock(&gLock);
1450 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1453 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1459 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1461 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1465 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1468 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1469 TBM_LOG_I("No tbm_surface.\n");
1473 tbm_surface_internal_dump_start(path, w, h, count);
1476 } else if (onoff == 0) {
1478 tbm_surface_internal_dump_end();
1489 tbm_bufmgr_debug_dump_all(char *path)
1491 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1493 TBM_LOG_D("path=%s\n", path);
1494 int w = 0, h = 0, count = 0;
1495 tbm_surface_h surface = NULL, tmp = NULL;
1497 count = _tbm_util_get_max_surface_size(&w, &h);
1499 TBM_LOG_I("No tbm_surface.\n");
1503 tbm_surface_internal_dump_start(path, w, h, count);
1505 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1506 tbm_surface_internal_dump_buffer(surface, "dump_all");
1509 tbm_surface_internal_dump_end();
1515 /* internal function */
1517 _tbm_bufmgr_get_bufmgr(void)
1523 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1525 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1527 bo->surface = surface;
1533 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1535 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1539 pthread_mutex_lock(&bufmgr->lock);
1541 if (!bufmgr->backend->bufmgr_bind_native_display) {
1542 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1543 pthread_mutex_unlock(&bufmgr->lock);
1547 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1549 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1550 pthread_mutex_unlock(&bufmgr->lock);
1554 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1556 pthread_mutex_unlock(&bufmgr->lock);
1560 /* LCOV_EXCL_STOP */