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) {
87 if (f == TBM_BO_DEFAULT)
88 snprintf(str, 255, "DEFAULT\n");
90 if (f & TBM_BO_SCANOUT)
91 c = snprintf(&str[c], 255, "SCANOUT,");
92 if (f & TBM_BO_NONCACHABLE)
93 c = snprintf(&str[c], 255, "NONCACHABLE,");
95 c = snprintf(&str[c], 255, "WC");
100 /* LCOV_EXCL_START */
101 static int last_chk_bo_cnt = 0;
103 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
105 if (bufmgr->bo_cnt >= 500 && ((bufmgr->bo_cnt % 20) == 0)) {
106 if (bufmgr->bo_cnt > last_chk_bo_cnt) {
107 TBM_DEBUG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
108 tbm_bufmgr_debug_show(bufmgr);
109 last_chk_bo_cnt = bufmgr->bo_cnt;
115 _tbm_util_get_appname_brief(char *brief)
119 char temp[255] = {0,};
120 char *saveptr = NULL;
122 token = strtok_r(brief, delim, &saveptr);
124 while (token != NULL) {
125 memset(temp, 0x00, 255 * sizeof(char));
126 strncpy(temp, token, 254 * sizeof(char));
127 token = strtok_r(NULL, delim, &saveptr);
130 snprintf(brief, sizeof(temp), "%s", temp);
134 _tbm_util_get_appname_from_pid(long pid, char *str)
139 char fn_cmdline[255] = {0,};
140 char cmdline[255] = {0,};
142 snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", app_pid);
144 fp = fopen(fn_cmdline, "r");
146 fprintf(stderr, "cannot file open /proc/%ld/cmdline", app_pid);
150 if (!fgets(cmdline, 255, fp)) {
151 fprintf(stderr, "fail to get appname for pid(%ld)\n", app_pid);
157 len = strlen(cmdline);
159 memset(cmdline, 0x00, 255);
163 snprintf(str, sizeof(cmdline), "%s", cmdline);
168 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
170 tbm_user_data *user_data = NULL;
171 tbm_user_data *old_data = NULL, *tmp = NULL;
173 if (!LIST_IS_EMPTY(user_data_list)) {
174 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, user_data_list, item_link) {
175 if (old_data->key == key) {
176 user_data = old_data;
186 *user_data_create(unsigned long key, tbm_data_free data_free_func)
188 tbm_user_data *user_data = NULL;
190 user_data = calloc(1, sizeof(tbm_user_data));
194 user_data->key = key;
195 user_data->free_func = data_free_func;
196 user_data->data = (void *)0;
202 user_data_delete(tbm_user_data *user_data)
204 if (user_data->data && user_data->free_func)
205 user_data->free_func(user_data->data);
207 LIST_DEL(&user_data->item_link);
213 _bo_lock(tbm_bo bo, int device, int opt)
215 tbm_bufmgr bufmgr = bo->bufmgr;
218 if (bufmgr->backend->bo_lock)
219 ret = bufmgr->backend->bo_lock(bo, device, opt);
227 _bo_unlock(tbm_bo bo)
229 tbm_bufmgr bufmgr = bo->bufmgr;
231 if (bufmgr->backend->bo_unlock)
232 bufmgr->backend->bo_unlock(bo);
236 _tbm_bo_lock(tbm_bo bo, int device, int opt)
238 tbm_bufmgr bufmgr = NULL;
247 /* do not try to lock the bo */
248 if (bufmgr->lock_type == LOCK_TRY_NEVER)
251 if (bo->lock_cnt < 0) {
252 TBM_LOG_E("error bo:%p LOCK_CNT=%d\n",
257 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
258 if (bo->lock_cnt == 0) {
259 pthread_mutex_unlock(&bufmgr->lock);
260 ret = _bo_lock(bo, device, opt);
261 pthread_mutex_lock(&bufmgr->lock);
266 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
267 pthread_mutex_unlock(&bufmgr->lock);
268 ret = _bo_lock(bo, device, opt);
269 pthread_mutex_lock(&bufmgr->lock);
273 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
277 DBG_LOCK(">> LOCK bo:%p(%d->%d)\n",
278 bo, old, bo->lock_cnt);
284 _tbm_bo_unlock(tbm_bo bo)
286 tbm_bufmgr bufmgr = NULL;
295 /* do not try to unlock the bo */
296 if (bufmgr->lock_type == LOCK_TRY_NEVER)
300 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
301 if (bo->lock_cnt > 0) {
303 if (bo->lock_cnt == 0)
306 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
307 if (bo->lock_cnt > 0) {
312 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
316 if (bo->lock_cnt < 0)
319 DBG_LOCK(">> UNLOCK bo:%p(%d->%d)\n",
320 bo, old, bo->lock_cnt);
324 _tbm_bo_is_valid(tbm_bo bo)
326 tbm_bo old_data = NULL, tmp = NULL;
331 if (!LIST_IS_EMPTY(&gBufMgr->bo_list)) {
332 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &gBufMgr->bo_list, item_link) {
342 _tbm_bo_ref(tbm_bo bo)
348 _tbm_bo_unref(tbm_bo bo)
350 tbm_bufmgr bufmgr = bo->bufmgr;
351 tbm_user_data *old_data = NULL, *tmp = NULL;
353 if (bo->ref_cnt <= 0)
357 if (bo->ref_cnt == 0) {
358 /* destory the user_data_list */
359 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
360 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
361 DBG("free user_data\n");
362 user_data_delete(old_data);
366 if (bo->lock_cnt > 0) {
367 TBM_LOG_E("error lock_cnt:%d\n",
372 /* call the bo_free */
373 bufmgr->backend->bo_free(bo);
376 LIST_DEL(&bo->item_link);
385 /* LCOV_EXCL_START */
387 _check_version(TBMModuleVersionInfo *data)
392 abimaj = GET_ABI_MAJOR(data->abiversion);
393 abimin = GET_ABI_MINOR(data->abiversion);
395 DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
396 data->modname ? data->modname : "UNKNOWN!",
397 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
399 vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
400 vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
402 DBG("TBM ABI version %d.%d\n",
405 if (abimaj != vermaj) {
406 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
409 } else if (abimin > vermin) {
410 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
418 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
420 char path[PATH_MAX] = { 0, };
421 TBMModuleData *initdata = NULL;
424 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
426 module_data = dlopen(path, RTLD_LAZY);
428 TBM_LOG_E("failed to load module: %s(%s)\n",
433 initdata = dlsym(module_data, "tbmModuleData");
436 TBMModuleVersionInfo *vers;
438 vers = initdata->vers;
439 init = initdata->init;
442 if (!_check_version(vers)) {
443 dlclose(module_data);
447 TBM_LOG_E("Error: module does not supply version information.\n");
449 dlclose(module_data);
454 if (!init(bufmgr, fd)) {
455 TBM_LOG_E("Fail to init module(%s)\n",
457 dlclose(module_data);
461 if (!bufmgr->backend || !bufmgr->backend->priv) {
462 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n",
464 dlclose(module_data);
468 TBM_LOG_E("Error: module does not supply init symbol.\n");
469 dlclose(module_data);
473 TBM_LOG_E("Error: module does not have data object.\n");
474 dlclose(module_data);
478 bufmgr->module_data = module_data;
480 DBG("Success to load module(%s)\n",
487 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
489 struct dirent **namelist;
490 const char *p = NULL;
494 /* load bufmgr priv from default lib */
495 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
497 /* load bufmgr priv from configured path */
499 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
501 TBM_LOG_E("no files : %s\n",
505 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
506 p = strstr(namelist[n]->d_name, SUFFIX_LIB);
507 if (p && !strcmp(p, SUFFIX_LIB))
508 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
521 tbm_bufmgr_init(int fd)
525 pthread_mutex_lock(&gLock);
527 /* LCOV_EXCL_START */
529 env = getenv("TBM_DLOG");
532 TBM_LOG_D("TBM_DLOG=%s\n", env);
539 env = getenv("TBM_DEBUG");
542 TBM_LOG_D("TBM_DEBUG=%s\n", env);
549 env = getenv("TBM_TRACE");
552 TBM_LOG_D("TBM_TRACE=%s\n", env);
559 /* initialize buffer manager */
561 gBufMgr->ref_count++;
562 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
563 pthread_mutex_unlock(&gLock);
567 DBG("bufmgr init\n");
569 /* allocate bufmgr */
570 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
572 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
573 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
574 pthread_mutex_unlock(&gLock);
580 /* load bufmgr priv from env */
581 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
582 /* LCOV_EXCL_START */
583 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
584 TBM_LOG_E("error : Fail to load bufmgr backend\n");
587 pthread_mutex_unlock(&gLock);
592 /* log for tbm backend_flag */
593 DBG("backend flag:%x:", gBufMgr->backend->flags);
596 gBufMgr->ref_count = 1;
598 DBG("create tizen bufmgr:%p ref_count:%d\n",
599 gBufMgr, gBufMgr->ref_count);
601 if (pthread_mutex_init(&gBufMgr->lock, NULL) != 0) {
602 /* LCOV_EXCL_START */
603 _tbm_set_last_result(TBM_BO_ERROR_THREAD_INIT_FAILED);
604 gBufMgr->backend->bufmgr_deinit(gBufMgr->backend->priv);
605 tbm_backend_free(gBufMgr->backend);
606 dlclose(gBufMgr->module_data);
609 pthread_mutex_unlock(&gLock);
614 /* setup the lock_type */
615 env = getenv("BUFMGR_LOCK_TYPE");
616 if (env && !strcmp(env, "always"))
617 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
618 else if (env && !strcmp(env, "none"))
619 gBufMgr->lock_type = LOCK_TRY_NEVER;
620 else if (env && !strcmp(env, "once"))
621 gBufMgr->lock_type = LOCK_TRY_ONCE;
623 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
625 DBG("BUFMGR_LOCK_TYPE=%s\n",
626 env ? env : "default:once");
628 TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
630 /* intialize bo_list */
631 LIST_INITHEAD(&gBufMgr->bo_list);
633 /* intialize surf_list */
634 LIST_INITHEAD(&gBufMgr->surf_list);
636 pthread_mutex_unlock(&gLock);
641 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
643 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
648 tbm_surface_h surf = NULL;
649 tbm_surface_h tmp_surf = NULL;
651 pthread_mutex_lock(&gLock);
654 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
655 pthread_mutex_unlock(&gLock);
660 if (bufmgr->ref_count > 0) {
661 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
662 pthread_mutex_unlock(&gLock);
666 /* destroy bo_list */
667 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
668 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
669 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
676 /* destroy surf_list */
677 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
678 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
679 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
681 tbm_surface_destroy(surf);
685 /* destroy bufmgr priv */
686 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
687 bufmgr->backend->priv = NULL;
688 tbm_backend_free(bufmgr->backend);
689 bufmgr->backend = NULL;
691 pthread_mutex_destroy(&bufmgr->lock);
693 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
695 dlclose(bufmgr->module_data);
704 pthread_mutex_unlock(&gLock);
708 tbm_bo_size(tbm_bo bo)
710 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
712 tbm_bufmgr bufmgr = bo->bufmgr;
715 pthread_mutex_lock(&bufmgr->lock);
717 size = bufmgr->backend->bo_size(bo);
719 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
721 pthread_mutex_unlock(&bufmgr->lock);
727 tbm_bo_ref(tbm_bo bo)
729 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
731 tbm_bufmgr bufmgr = bo->bufmgr;
733 pthread_mutex_lock(&bufmgr->lock);
737 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
739 pthread_mutex_unlock(&bufmgr->lock);
745 tbm_bo_unref(tbm_bo bo)
747 TBM_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
749 tbm_bufmgr bufmgr = bo->bufmgr;
751 pthread_mutex_lock(&bufmgr->lock);
753 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
757 pthread_mutex_unlock(&bufmgr->lock);
761 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
763 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
766 void *bo_priv = NULL;
768 bo = calloc(1, sizeof(struct _tbm_bo));
770 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
771 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
775 _tbm_util_check_bo_cnt(bufmgr);
780 pthread_mutex_lock(&bufmgr->lock);
782 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
784 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
785 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
787 pthread_mutex_unlock(&bufmgr->lock);
795 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
797 LIST_INITHEAD(&bo->user_data_list);
799 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
801 pthread_mutex_unlock(&bufmgr->lock);
807 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
809 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
814 void *bo_priv = NULL;
816 _tbm_util_check_bo_cnt(bufmgr);
818 pthread_mutex_lock(&bufmgr->lock);
820 bo = calloc(1, sizeof(struct _tbm_bo));
822 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
823 pthread_mutex_unlock(&bufmgr->lock);
831 bo_priv = bufmgr->backend->bo_import(bo, key);
833 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
834 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
836 pthread_mutex_unlock(&bufmgr->lock);
840 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
841 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
842 if (bo2->priv == bo_priv) {
843 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
844 bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
847 pthread_mutex_unlock(&bufmgr->lock);
856 if (bufmgr->backend->bo_get_flags)
857 bo->flags = bufmgr->backend->bo_get_flags(bo);
859 bo->flags = TBM_BO_DEFAULT;
861 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
862 bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
864 LIST_INITHEAD(&bo->user_data_list);
866 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
868 pthread_mutex_unlock(&bufmgr->lock);
874 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
876 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
881 void *bo_priv = NULL;
883 _tbm_util_check_bo_cnt(bufmgr);
885 pthread_mutex_lock(&bufmgr->lock);
887 bo = calloc(1, sizeof(struct _tbm_bo));
889 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
890 pthread_mutex_unlock(&bufmgr->lock);
898 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
900 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
901 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
903 pthread_mutex_unlock(&bufmgr->lock);
907 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
908 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
909 if (bo2->priv == bo_priv) {
910 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
911 bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
914 pthread_mutex_unlock(&bufmgr->lock);
923 if (bufmgr->backend->bo_get_flags)
924 bo->flags = bufmgr->backend->bo_get_flags(bo);
926 bo->flags = TBM_BO_DEFAULT;
928 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
929 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
931 LIST_INITHEAD(&bo->user_data_list);
933 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
935 pthread_mutex_unlock(&bufmgr->lock);
941 tbm_bo_export(tbm_bo bo)
943 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
950 pthread_mutex_lock(&bufmgr->lock);
952 ret = bufmgr->backend->bo_export(bo);
954 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
955 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
956 pthread_mutex_unlock(&bufmgr->lock);
960 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
962 pthread_mutex_unlock(&bufmgr->lock);
968 tbm_bo_export_fd(tbm_bo bo)
970 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
977 pthread_mutex_lock(&bufmgr->lock);
979 ret = bufmgr->backend->bo_export_fd(bo);
981 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
982 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
983 pthread_mutex_unlock(&bufmgr->lock);
987 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
989 pthread_mutex_unlock(&bufmgr->lock);
995 tbm_bo_get_handle(tbm_bo bo, int device)
997 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1000 tbm_bo_handle bo_handle;
1002 bufmgr = bo->bufmgr;
1004 pthread_mutex_lock(&bufmgr->lock);
1006 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1007 if (bo_handle.ptr == NULL) {
1008 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1009 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1010 pthread_mutex_unlock(&bufmgr->lock);
1011 return (tbm_bo_handle) NULL;
1014 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1016 pthread_mutex_unlock(&bufmgr->lock);
1022 tbm_bo_map(tbm_bo bo, int device, int opt)
1024 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1027 tbm_bo_handle bo_handle;
1029 bufmgr = bo->bufmgr;
1031 pthread_mutex_lock(&bufmgr->lock);
1033 if (!_tbm_bo_lock(bo, device, opt)) {
1034 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1035 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1036 pthread_mutex_unlock(&bufmgr->lock);
1037 return (tbm_bo_handle) NULL;
1040 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1041 if (bo_handle.ptr == NULL) {
1042 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1043 TBM_TRACE("error: fail to map bo:%p\n", bo);
1045 pthread_mutex_unlock(&bufmgr->lock);
1046 return (tbm_bo_handle) NULL;
1049 /* increase the map_count */
1052 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1054 pthread_mutex_unlock(&bufmgr->lock);
1060 tbm_bo_unmap(tbm_bo bo)
1062 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1067 bufmgr = bo->bufmgr;
1069 pthread_mutex_lock(&bufmgr->lock);
1071 ret = bufmgr->backend->bo_unmap(bo);
1073 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1074 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1075 pthread_mutex_unlock(&bufmgr->lock);
1079 /* decrease the map_count */
1082 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1086 pthread_mutex_unlock(&bufmgr->lock);
1092 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1094 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1095 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1099 pthread_mutex_lock(&bo1->bufmgr->lock);
1101 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1103 if (bo1->bufmgr->backend->bo_size(bo1) != bo2->bufmgr->backend->bo_size(bo2)) {
1104 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1105 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1106 pthread_mutex_unlock(&bo1->bufmgr->lock);
1110 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1113 bo1->priv = bo2->priv;
1116 pthread_mutex_unlock(&bo1->bufmgr->lock);
1122 tbm_bo_locked(tbm_bo bo)
1124 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1128 bufmgr = bo->bufmgr;
1130 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1131 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1135 pthread_mutex_lock(&bufmgr->lock);
1138 if (bo->lock_cnt > 0) {
1139 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1140 pthread_mutex_unlock(&bufmgr->lock);
1144 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1145 pthread_mutex_unlock(&bufmgr->lock);
1151 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1152 tbm_data_free data_free_func)
1154 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1156 tbm_user_data *data;
1158 /* check if the data according to the key exist if so, return false. */
1159 data = user_data_lookup(&bo->user_data_list, key);
1161 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1165 data = user_data_create(key, data_free_func);
1167 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1171 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1173 LIST_ADD(&data->item_link, &bo->user_data_list);
1179 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1181 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1183 tbm_user_data *old_data;
1185 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1186 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1190 old_data = user_data_lookup(&bo->user_data_list, key);
1192 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1196 if (old_data->data && old_data->free_func)
1197 old_data->free_func(old_data->data);
1199 old_data->data = data;
1201 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1207 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1209 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1211 tbm_user_data *old_data;
1213 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1214 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1218 old_data = user_data_lookup(&bo->user_data_list, key);
1220 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1225 *data = old_data->data;
1227 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1233 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1235 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1237 tbm_user_data *old_data = (void *)0;
1239 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1240 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1244 old_data = user_data_lookup(&bo->user_data_list, key);
1246 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1250 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1252 user_data_delete(old_data);
1258 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1260 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1262 unsigned int capability = TBM_BUFMGR_CAPABILITY_NONE;
1264 if (bufmgr->backend->bo_import && bufmgr->backend->bo_export)
1265 capability |= TBM_BUFMGR_CAPABILITY_SHARE_KEY;
1267 if (bufmgr->backend->bo_import_fd && bufmgr->backend->bo_export_fd)
1268 capability |= TBM_BUFMGR_CAPABILITY_SHARE_FD;
1270 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, capability);
1276 tbm_bo_get_flags(tbm_bo bo)
1278 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1280 TBM_TRACE("bo(%p)\n", bo);
1285 /* LCOV_EXCL_START */
1287 tbm_get_last_error(void)
1289 return tbm_last_error;
1293 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1295 TBM_RETURN_IF_FAIL(bufmgr != NULL);
1296 tbm_bo bo = NULL, tmp_bo = NULL;
1299 tbm_surface_h surf = NULL, tmp_surf = NULL;
1302 char app_name[255] = {0,};
1303 unsigned int pid = 0;
1305 pthread_mutex_lock(&gLock);
1308 _tbm_util_get_appname_from_pid(getpid(), app_name);
1309 _tbm_util_get_appname_brief(app_name);
1310 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1311 app_name, getpid());
1312 memset(app_name, 0x0, 255 * sizeof(char));
1314 TBM_DEBUG("[tbm_surface information]\n");
1315 TBM_DEBUG("no surface refcnt width height bpp size num_bos num_planes flags format app_name\n");
1316 /* show the tbm_surface information in surf_list */
1317 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1318 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1319 pid = _tbm_surface_internal_get_debug_pid(surf);
1321 /* if pid is null, set the self_pid */
1325 _tbm_util_get_appname_from_pid(pid, app_name);
1326 _tbm_util_get_appname_brief(app_name);
1328 TBM_DEBUG("%-4d%-23p%-6d%-7d%-8d%-5d%-12d%-10d%-9d%-4d%-20s%s\n",
1335 surf->info.size / 1024,
1339 _tbm_surface_internal_format_to_str(surf->info.format),
1342 for (i = 0; i < surf->num_bos; i++) {
1343 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1345 surf->bos[i]->ref_cnt,
1346 tbm_bo_size(surf->bos[i]) / 1024);
1349 memset(app_name, 0x0, 255 * sizeof(char));
1352 TBM_DEBUG("no tbm_surfaces.\n");
1356 TBM_DEBUG("[tbm_bo information]\n");
1357 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1359 /* show the tbm_bo information in bo_list */
1360 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1361 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1362 TBM_DEBUG("%-4d%-11p %-6d%-12d%-9d%-9d%-4d%-11p\n",
1366 tbm_bo_size(bo) / 1024,
1373 TBM_DEBUG("no tbm_bos.\n");
1377 TBM_DEBUG("===============================================================\n");
1379 pthread_mutex_unlock(&gLock);
1384 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1387 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1392 /* internal function */
1394 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1396 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1398 bo->surface = surface;
1404 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1406 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1410 pthread_mutex_lock(&bufmgr->lock);
1412 if (!bufmgr->backend->bufmgr_bind_native_display) {
1413 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1414 pthread_mutex_unlock(&bufmgr->lock);
1418 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1420 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1421 pthread_mutex_unlock(&bufmgr->lock);
1425 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1427 pthread_mutex_unlock(&bufmgr->lock);
1431 /* LCOV_EXCL_STOP */