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 pthread_mutex_lock(&bufmgr->lock);
857 bo = calloc(1, sizeof(struct _tbm_bo));
859 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
860 pthread_mutex_unlock(&bufmgr->lock);
868 bo_priv = bufmgr->backend->bo_import(bo, key);
870 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
871 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
873 pthread_mutex_unlock(&bufmgr->lock);
877 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
878 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
879 if (bo2->priv == bo_priv) {
880 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
881 bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
884 pthread_mutex_unlock(&bufmgr->lock);
893 if (bufmgr->backend->bo_get_flags)
894 bo->flags = bufmgr->backend->bo_get_flags(bo);
896 bo->flags = TBM_BO_DEFAULT;
898 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
899 bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
901 LIST_INITHEAD(&bo->user_data_list);
903 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
905 pthread_mutex_unlock(&bufmgr->lock);
911 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
913 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
918 void *bo_priv = NULL;
920 _tbm_util_check_bo_cnt(bufmgr);
922 pthread_mutex_lock(&bufmgr->lock);
924 bo = calloc(1, sizeof(struct _tbm_bo));
926 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
927 pthread_mutex_unlock(&bufmgr->lock);
935 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
937 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
938 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
940 pthread_mutex_unlock(&bufmgr->lock);
944 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
945 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
946 if (bo2->priv == bo_priv) {
947 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
948 bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
951 pthread_mutex_unlock(&bufmgr->lock);
960 if (bufmgr->backend->bo_get_flags)
961 bo->flags = bufmgr->backend->bo_get_flags(bo);
963 bo->flags = TBM_BO_DEFAULT;
965 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
966 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
968 LIST_INITHEAD(&bo->user_data_list);
970 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
972 pthread_mutex_unlock(&bufmgr->lock);
978 tbm_bo_export(tbm_bo bo)
980 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
987 pthread_mutex_lock(&bufmgr->lock);
989 ret = bufmgr->backend->bo_export(bo);
991 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
992 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
993 pthread_mutex_unlock(&bufmgr->lock);
997 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
999 pthread_mutex_unlock(&bufmgr->lock);
1005 tbm_bo_export_fd(tbm_bo bo)
1007 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1012 bufmgr = bo->bufmgr;
1014 pthread_mutex_lock(&bufmgr->lock);
1016 ret = bufmgr->backend->bo_export_fd(bo);
1018 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1019 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1020 pthread_mutex_unlock(&bufmgr->lock);
1024 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1026 pthread_mutex_unlock(&bufmgr->lock);
1032 tbm_bo_get_handle(tbm_bo bo, int device)
1034 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1037 tbm_bo_handle bo_handle;
1039 bufmgr = bo->bufmgr;
1041 pthread_mutex_lock(&bufmgr->lock);
1043 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1044 if (bo_handle.ptr == NULL) {
1045 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1046 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1047 pthread_mutex_unlock(&bufmgr->lock);
1048 return (tbm_bo_handle) NULL;
1051 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1053 pthread_mutex_unlock(&bufmgr->lock);
1059 tbm_bo_map(tbm_bo bo, int device, int opt)
1061 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1064 tbm_bo_handle bo_handle;
1066 bufmgr = bo->bufmgr;
1068 pthread_mutex_lock(&bufmgr->lock);
1070 if (!_tbm_bo_lock(bo, device, opt)) {
1071 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1072 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1073 pthread_mutex_unlock(&bufmgr->lock);
1074 return (tbm_bo_handle) NULL;
1077 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1078 if (bo_handle.ptr == NULL) {
1079 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1080 TBM_TRACE("error: fail to map bo:%p\n", bo);
1082 pthread_mutex_unlock(&bufmgr->lock);
1083 return (tbm_bo_handle) NULL;
1086 /* increase the map_count */
1089 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1091 pthread_mutex_unlock(&bufmgr->lock);
1097 tbm_bo_unmap(tbm_bo bo)
1099 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1104 bufmgr = bo->bufmgr;
1106 pthread_mutex_lock(&bufmgr->lock);
1108 ret = bufmgr->backend->bo_unmap(bo);
1110 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1111 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1112 pthread_mutex_unlock(&bufmgr->lock);
1116 /* decrease the map_count */
1119 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1123 pthread_mutex_unlock(&bufmgr->lock);
1129 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1131 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1132 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1136 pthread_mutex_lock(&bo1->bufmgr->lock);
1138 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1140 if (bo1->bufmgr->backend->bo_size(bo1) != bo2->bufmgr->backend->bo_size(bo2)) {
1141 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1142 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1143 pthread_mutex_unlock(&bo1->bufmgr->lock);
1147 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1150 bo1->priv = bo2->priv;
1153 pthread_mutex_unlock(&bo1->bufmgr->lock);
1159 tbm_bo_locked(tbm_bo bo)
1161 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1165 bufmgr = bo->bufmgr;
1167 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1168 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1172 pthread_mutex_lock(&bufmgr->lock);
1175 if (bo->lock_cnt > 0) {
1176 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1177 pthread_mutex_unlock(&bufmgr->lock);
1181 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1182 pthread_mutex_unlock(&bufmgr->lock);
1188 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1189 tbm_data_free data_free_func)
1191 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1193 tbm_user_data *data;
1195 /* check if the data according to the key exist if so, return false. */
1196 data = user_data_lookup(&bo->user_data_list, key);
1198 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1202 data = user_data_create(key, data_free_func);
1204 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1208 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1210 LIST_ADD(&data->item_link, &bo->user_data_list);
1216 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1218 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1220 tbm_user_data *old_data;
1222 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1223 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1227 old_data = user_data_lookup(&bo->user_data_list, key);
1229 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1233 if (old_data->data && old_data->free_func)
1234 old_data->free_func(old_data->data);
1236 old_data->data = data;
1238 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1244 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1246 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1248 tbm_user_data *old_data;
1250 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1251 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1255 old_data = user_data_lookup(&bo->user_data_list, key);
1257 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1262 *data = old_data->data;
1264 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1270 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1272 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1274 tbm_user_data *old_data = (void *)0;
1276 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1277 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1281 old_data = user_data_lookup(&bo->user_data_list, key);
1283 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1287 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1289 user_data_delete(old_data);
1295 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1297 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1299 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1301 return bufmgr->capabilities;
1305 tbm_bo_get_flags(tbm_bo bo)
1307 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1309 TBM_TRACE("bo(%p)\n", bo);
1314 /* LCOV_EXCL_START */
1316 tbm_get_last_error(void)
1318 return tbm_last_error;
1322 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1324 TBM_RETURN_IF_FAIL(bufmgr != NULL);
1325 tbm_bo bo = NULL, tmp_bo = NULL;
1328 tbm_surface_h surf = NULL, tmp_surf = NULL;
1331 char app_name[255] = {0,};
1332 unsigned int pid = 0;
1333 char title[255] = {0,};
1334 char data[255] = {0,};
1335 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1337 pthread_mutex_lock(&gLock);
1340 _tbm_util_get_appname_from_pid(getpid(), app_name);
1341 _tbm_util_get_appname_brief(app_name);
1342 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1343 app_name, getpid());
1344 memset(app_name, 0x0, 255 * sizeof(char));
1345 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1346 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1347 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1348 strncat(title, " ", 2);
1349 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1353 TBM_DEBUG("[tbm_surface information]\n");
1354 TBM_DEBUG("%s\n", title);
1355 /* show the tbm_surface information in surf_list */
1356 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1359 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1360 pid = _tbm_surface_internal_get_debug_pid(surf);
1362 /* if pid is null, set the self_pid */
1366 _tbm_util_get_appname_from_pid(pid, app_name);
1367 _tbm_util_get_appname_brief(app_name);
1369 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1376 surf->info.size / 1024,
1380 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1383 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1384 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1385 strncat(data, " ", 2);
1387 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1389 strncat(data, value, strlen(value) + 1);
1391 strncat(data, "none", strlen("none") + 1);
1394 TBM_DEBUG("%s\n", data);
1396 for (i = 0; i < surf->num_bos; i++) {
1397 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1399 surf->bos[i]->ref_cnt,
1400 tbm_bo_size(surf->bos[i]) / 1024);
1403 memset(app_name, 0x0, 255 * sizeof(char));
1406 TBM_DEBUG("no tbm_surfaces.\n");
1410 TBM_DEBUG("[tbm_bo information]\n");
1411 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1413 /* show the tbm_bo information in bo_list */
1414 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1415 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1416 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1420 tbm_bo_size(bo) / 1024,
1427 TBM_DEBUG("no tbm_bos.\n");
1431 TBM_DEBUG("===============================================================\n");
1433 pthread_mutex_unlock(&gLock);
1438 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1441 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1447 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1449 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1453 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1456 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1457 TBM_LOG_I("No tbm_surface.\n");
1461 tbm_surface_internal_dump_start(path, w, h, count);
1464 } else if (onoff == 0) {
1466 tbm_surface_internal_dump_end();
1477 tbm_bufmgr_debug_dump_all(char *path)
1479 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1481 TBM_LOG_D("path=%s\n", path);
1482 int w = 0, h = 0, count = 0;
1483 tbm_surface_h surface = NULL, tmp = NULL;
1485 count = _tbm_util_get_max_surface_size(&w, &h);
1487 TBM_LOG_I("No tbm_surface.\n");
1491 tbm_surface_internal_dump_start(path, w, h, count);
1493 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1494 tbm_surface_internal_dump_buffer(surface, "dump_all");
1497 tbm_surface_internal_dump_end();
1503 /* internal function */
1505 _tbm_bufmgr_get_bufmgr(void)
1511 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1513 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1515 bo->surface = surface;
1521 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1523 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1527 pthread_mutex_lock(&bufmgr->lock);
1529 if (!bufmgr->backend->bufmgr_bind_native_display) {
1530 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1531 pthread_mutex_unlock(&bufmgr->lock);
1535 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1537 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1538 pthread_mutex_unlock(&bufmgr->lock);
1542 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1544 pthread_mutex_unlock(&bufmgr->lock);
1548 /* LCOV_EXCL_STOP */