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"
42 #define DBG(...) {if (bDebug&0x1) TBM_LOG(__VA_ARGS__);}
43 #define DBG_LOCK(...) {if (bDebug&0x2) TBM_LOG(__VA_ARGS__);}
49 #define PREFIX_LIB "libtbm_"
50 #define SUFFIX_LIB ".so"
51 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
53 /* values to indicate unspecified fields in XF86ModReqInfo. */
54 #define MAJOR_UNSPEC 0xFF
55 #define MINOR_UNSPEC 0xFF
56 #define PATCH_UNSPEC 0xFFFF
57 #define ABI_VERS_UNSPEC 0xFFFFFFFF
59 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
60 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
61 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
62 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
63 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
71 pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
74 static __thread tbm_error_e tbm_last_error = TBM_ERROR_NONE;
77 _tbm_set_last_result(tbm_error_e err)
83 _tbm_util_get_appname_brief(char *brief)
87 char temp[255] = {0,};
90 token = strtok_r(brief, delim, &saveptr);
92 while (token != NULL) {
93 memset(temp, 0x00, 255 * sizeof(char));
94 strncpy(temp, token, 254 * sizeof(char));
95 token = strtok_r(NULL, delim, &saveptr);
98 snprintf(brief, sizeof(temp), "%s", temp);
102 _tbm_util_get_appname_from_pid(long pid, char *str)
107 char fn_cmdline[255] = {0,};
108 char cmdline[255] = {0,};
110 snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", app_pid);
112 fp = fopen(fn_cmdline, "r");
114 fprintf(stderr, "cannot file open /proc/%ld/cmdline", app_pid);
118 if (!fgets(cmdline, 255, fp)) {
119 fprintf(stderr, "fail to get appname for pid(%ld)\n", app_pid);
125 len = strlen(cmdline);
127 memset(cmdline, 0x00, 255);
131 snprintf(str, sizeof(cmdline), "%s", cmdline);
135 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
137 tbm_user_data *user_data = NULL;
138 tbm_user_data *old_data = NULL, *tmp = NULL;
140 if (!LIST_IS_EMPTY(user_data_list)) {
141 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, user_data_list, item_link) {
142 if (old_data->key == key) {
143 user_data = old_data;
153 *user_data_create(unsigned long key, tbm_data_free data_free_func)
155 tbm_user_data *user_data = NULL;
157 user_data = calloc(1, sizeof(tbm_user_data));
161 user_data->key = key;
162 user_data->free_func = data_free_func;
163 user_data->data = (void *)0;
169 user_data_delete(tbm_user_data *user_data)
171 if (user_data->data && user_data->free_func)
172 user_data->free_func(user_data->data);
174 LIST_DEL(&user_data->item_link);
180 _bo_lock(tbm_bo bo, int device, int opt)
182 tbm_bufmgr bufmgr = bo->bufmgr;
185 if (bufmgr->backend->bo_lock) {
186 ret = bufmgr->backend->bo_lock(bo, device, opt);
195 _bo_unlock(tbm_bo bo)
197 tbm_bufmgr bufmgr = bo->bufmgr;
199 if (bufmgr->backend->bo_unlock) {
200 bufmgr->backend->bo_unlock(bo);
205 _tbm_bo_lock(tbm_bo bo, int device, int opt)
207 tbm_bufmgr bufmgr = NULL;
216 /* do not try to lock the bo */
217 if (bufmgr->lock_type == LOCK_TRY_NEVER)
220 if (bo->lock_cnt < 0) {
221 TBM_LOG("[libtbm:%d] "
222 "error %s:%d bo:%p LOCK_CNT=%d\n",
223 getpid(), __func__, __LINE__, bo, bo->lock_cnt);
227 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
228 if (bo->lock_cnt == 0) {
229 pthread_mutex_unlock(&bufmgr->lock);
230 ret = _bo_lock(bo, device, opt);
231 pthread_mutex_lock(&bufmgr->lock);
236 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
237 pthread_mutex_unlock(&bufmgr->lock);
238 ret = _bo_lock(bo, device, opt);
239 pthread_mutex_lock(&bufmgr->lock);
243 TBM_LOG("[libtbm:%d] "
244 "error %s:%d bo:%p lock_type is wrong.\n",
245 getpid(), __func__, __LINE__, bo);
248 DBG_LOCK("[libtbm:%d] >> LOCK bo:%p(%d->%d)\n", getpid(),
249 bo, old, bo->lock_cnt);
255 _tbm_bo_unlock(tbm_bo bo)
257 tbm_bufmgr bufmgr = NULL;
266 /* do not try to unlock the bo */
267 if (bufmgr->lock_type == LOCK_TRY_NEVER)
271 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
272 if (bo->lock_cnt > 0) {
274 if (bo->lock_cnt == 0)
277 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
278 if (bo->lock_cnt > 0) {
283 TBM_LOG("[libtbm:%d] "
284 "error %s:%d bo:%p lock_type is wrong.\n",
285 getpid(), __func__, __LINE__, bo);
288 if (bo->lock_cnt < 0)
291 DBG_LOCK("[libtbm:%d] << unlock bo:%p(%d->%d)\n", getpid(),
292 bo, old, bo->lock_cnt);
296 _tbm_bo_is_valid(tbm_bo bo)
298 tbm_bo old_data = NULL, tmp = NULL;
303 if (!LIST_IS_EMPTY(&gBufMgr->bo_list)) {
304 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &gBufMgr->bo_list, item_link) {
314 _tbm_bo_ref(tbm_bo bo)
320 _tbm_bo_unref(tbm_bo bo)
322 tbm_bufmgr bufmgr = bo->bufmgr;
323 tbm_user_data *old_data = NULL, *tmp = NULL;
325 if (bo->ref_cnt <= 0)
329 if (bo->ref_cnt == 0) {
330 /* destory the user_data_list */
331 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
332 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
333 DBG("[libtbm:%d] free user_data\n",
335 user_data_delete(old_data);
339 if (bo->lock_cnt > 0) {
340 TBM_LOG("[libtbm:%d] "
341 "error %s:%d lock_cnt:%d\n",
342 getpid(), __func__, __LINE__, bo->lock_cnt);
346 /* call the bo_free */
347 bufmgr->backend->bo_free(bo);
350 LIST_DEL(&bo->item_link);
358 _check_version(TBMModuleVersionInfo *data)
363 abimaj = GET_ABI_MAJOR(data->abiversion);
364 abimin = GET_ABI_MINOR(data->abiversion);
367 "TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
368 getpid(), data->modname ? data->modname : "UNKNOWN!",
369 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
371 vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
372 vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
375 "TBM ABI version %d.%d\n",
376 getpid(), vermaj, vermin);
378 if (abimaj != vermaj) {
379 TBM_LOG("[libtbm:%d] "
380 "TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
381 getpid(), abimaj, vermaj);
383 } else if (abimin > vermin) {
384 TBM_LOG("[libtbm:%d] "
385 "TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
386 getpid(), abimin, vermin);
393 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
395 char path[PATH_MAX] = { 0, };
396 TBMModuleData *initdata = NULL;
399 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
401 module_data = dlopen(path, RTLD_LAZY);
403 TBM_LOG("[libtbm:%d] "
404 "failed to load module: %s(%s)\n",
405 getpid(), dlerror(), file);
409 initdata = dlsym(module_data, "tbmModuleData");
412 TBMModuleVersionInfo *vers;
414 vers = initdata->vers;
415 init = initdata->init;
418 if (!_check_version(vers)) {
419 dlclose(module_data);
423 TBM_LOG("[libtbm:%d] "
424 "Error: module does not supply version information.\n",
427 dlclose(module_data);
432 if (!init(bufmgr, fd)) {
433 TBM_LOG("[libtbm:%d] "
434 "Fail to init module(%s)\n",
436 dlclose(module_data);
440 if (!bufmgr->backend || !bufmgr->backend->priv) {
441 TBM_LOG("[libtbm:%d] "
442 "Error: module(%s) wrong operation. Check backend or backend's priv.\n",
444 dlclose(module_data);
448 TBM_LOG("[libtbm:%d] "
449 "Error: module does not supply init symbol.\n",
451 dlclose(module_data);
455 TBM_LOG("[libtbm:%d] "
456 "Error: module does not have data object.\n",
458 dlclose(module_data);
462 bufmgr->module_data = module_data;
465 "Success to load module(%s)\n",
472 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
474 struct dirent **namelist;
475 const char *p = NULL;
479 /* load bufmgr priv from default lib */
480 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
482 /* load bufmgr priv from configured path */
484 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
486 TBM_LOG("[libtbm:%d] "
488 getpid(), BUFMGR_MODULE_DIR);
491 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
492 p = strstr(namelist[n]->d_name, SUFFIX_LIB);
493 if (p && !strcmp(p, SUFFIX_LIB))
494 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
506 tbm_bufmgr_init(int fd)
510 pthread_mutex_lock(&gLock);
513 env = getenv("GEM_DEBUG");
516 TBM_LOG("GEM_DEBUG=%s\n", env);
522 /* initialize buffer manager */
524 gBufMgr->ref_count++;
526 DBG("[libtbm:%d] bufmgr ref: fd=%d, ref_count:%d\n",
527 getpid(), gBufMgr->fd, gBufMgr->ref_count);
528 pthread_mutex_unlock(&gLock);
532 DBG("[libtbm:%d] bufmgr init\n", getpid());
534 /* allocate bufmgr */
535 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
537 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
538 pthread_mutex_unlock(&gLock);
544 /* load bufmgr priv from env */
545 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
546 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
547 TBM_LOG("[libtbm:%d] error : Fail to load bufmgr backend\n", getpid());
551 pthread_mutex_unlock(&gLock);
555 /* log for tbm backend_flag */
556 DBG("[libtbm:%d] ", getpid());
557 DBG("backend flag:%x:", gBufMgr->backend->flags);
560 gBufMgr->ref_count = 1;
562 DBG("[libtbm:%d] create tizen bufmgr: ref_count:%d\n",
563 getpid(), gBufMgr->ref_count);
565 if (pthread_mutex_init(&gBufMgr->lock, NULL) != 0) {
566 _tbm_set_last_result(TBM_BO_ERROR_THREAD_INIT_FAILED);
567 gBufMgr->backend->bufmgr_deinit(gBufMgr->backend->priv);
568 tbm_backend_free(gBufMgr->backend);
569 dlclose(gBufMgr->module_data);
572 pthread_mutex_unlock(&gLock);
576 /* setup the lock_type */
577 env = getenv("BUFMGR_LOCK_TYPE");
578 if (env && !strcmp(env, "always"))
579 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
580 else if (env && !strcmp(env, "none"))
581 gBufMgr->lock_type = LOCK_TRY_NEVER;
582 else if (env && !strcmp(env, "once"))
583 gBufMgr->lock_type = LOCK_TRY_ONCE;
585 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
587 DBG("[libtbm:%d] BUFMGR_LOCK_TYPE=%s\n",
588 getpid(), env ? env : "default:once");
590 /* intialize bo_list */
591 LIST_INITHEAD(&gBufMgr->bo_list);
593 /* intialize surf_list */
594 LIST_INITHEAD(&gBufMgr->surf_list);
596 pthread_mutex_unlock(&gLock);
601 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
603 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
608 tbm_surface_h surf = NULL;
609 tbm_surface_h tmp_surf = NULL;
611 pthread_mutex_lock(&gLock);
614 if (bufmgr->ref_count > 0) {
615 TBM_LOG("[libtbm:%d] "
616 "tizen bufmgr destroy: bufmgr:%p, ref_count:%d\n",
617 getpid(), bufmgr, bufmgr->ref_count);
618 pthread_mutex_unlock(&gLock);
622 /* destroy bo_list */
623 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
624 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
625 TBM_LOG("[libtbm:%d] "
626 "Un-freed bo(%p, ref:%d)\n",
627 getpid(), bo, bo->ref_cnt);
633 /* destroy surf_list */
634 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
635 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
636 TBM_LOG("[libtbm:%d] "
637 "Destroy surf(%p)\n",
639 tbm_surface_destroy(surf);
643 /* destroy bufmgr priv */
644 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
645 bufmgr->backend->priv = NULL;
646 tbm_backend_free(bufmgr->backend);
647 bufmgr->backend = NULL;
649 pthread_mutex_destroy(&bufmgr->lock);
652 "tizen bufmgr destroy: bufmgr:%p\n",
655 dlclose(bufmgr->module_data);
664 pthread_mutex_unlock(&gLock);
668 tbm_bo_size(tbm_bo bo)
670 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
672 tbm_bufmgr bufmgr = bo->bufmgr;
675 pthread_mutex_lock(&bufmgr->lock);
677 size = bufmgr->backend->bo_size(bo);
679 pthread_mutex_unlock(&bufmgr->lock);
685 tbm_bo_ref(tbm_bo bo)
687 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
689 tbm_bufmgr bufmgr = bo->bufmgr;
691 pthread_mutex_lock(&bufmgr->lock);
695 pthread_mutex_unlock(&bufmgr->lock);
701 tbm_bo_unref(tbm_bo bo)
703 TBM_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
705 tbm_bufmgr bufmgr = bo->bufmgr;
707 pthread_mutex_lock(&bufmgr->lock);
711 pthread_mutex_unlock(&bufmgr->lock);
715 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
717 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
720 void *bo_priv = NULL;
722 bo = calloc(1, sizeof(struct _tbm_bo));
724 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
730 pthread_mutex_lock(&bufmgr->lock);
732 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
734 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
736 pthread_mutex_unlock(&bufmgr->lock);
744 LIST_INITHEAD(&bo->user_data_list);
746 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
748 pthread_mutex_unlock(&bufmgr->lock);
754 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
756 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
761 void *bo_priv = NULL;
763 pthread_mutex_lock(&bufmgr->lock);
765 bo = calloc(1, sizeof(struct _tbm_bo));
767 pthread_mutex_unlock(&bufmgr->lock);
773 bo_priv = bufmgr->backend->bo_import(bo, key);
775 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
777 pthread_mutex_unlock(&bufmgr->lock);
781 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
782 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
783 if (bo2->priv == bo_priv) {
785 "find bo(%p, ref:%d key:%d) in list\n",
786 getpid(), bo2, bo2->ref_cnt, key);
790 pthread_mutex_unlock(&bufmgr->lock);
799 if (bufmgr->backend->bo_get_flags)
800 bo->flags = bufmgr->backend->bo_get_flags(bo);
802 bo->flags = TBM_BO_DEFAULT;
804 LIST_INITHEAD(&bo->user_data_list);
806 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
808 pthread_mutex_unlock(&bufmgr->lock);
814 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
816 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
821 void *bo_priv = NULL;
823 pthread_mutex_lock(&bufmgr->lock);
825 bo = calloc(1, sizeof(struct _tbm_bo));
827 pthread_mutex_unlock(&bufmgr->lock);
833 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
835 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
837 pthread_mutex_unlock(&bufmgr->lock);
841 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
842 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
843 if (bo2->priv == bo_priv) {
845 "find bo(%p, ref:%d, fd:%d) in list\n",
846 getpid(), bo2, bo2->ref_cnt, fd);
850 pthread_mutex_unlock(&bufmgr->lock);
859 if (bufmgr->backend->bo_get_flags)
860 bo->flags = bufmgr->backend->bo_get_flags(bo);
862 bo->flags = TBM_BO_DEFAULT;
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_export(tbm_bo bo)
876 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
883 pthread_mutex_lock(&bufmgr->lock);
884 ret = bufmgr->backend->bo_export(bo);
886 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
887 pthread_mutex_unlock(&bufmgr->lock);
890 pthread_mutex_unlock(&bufmgr->lock);
896 tbm_bo_export_fd(tbm_bo bo)
898 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
905 pthread_mutex_lock(&bufmgr->lock);
906 ret = bufmgr->backend->bo_export_fd(bo);
908 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
909 pthread_mutex_unlock(&bufmgr->lock);
912 pthread_mutex_unlock(&bufmgr->lock);
918 tbm_bo_get_handle(tbm_bo bo, int device)
920 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
923 tbm_bo_handle bo_handle;
927 pthread_mutex_lock(&bufmgr->lock);
928 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
929 if (bo_handle.ptr == NULL) {
930 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
931 pthread_mutex_unlock(&bufmgr->lock);
932 return (tbm_bo_handle) NULL;
934 pthread_mutex_unlock(&bufmgr->lock);
940 tbm_bo_map(tbm_bo bo, int device, int opt)
942 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
945 tbm_bo_handle bo_handle;
949 pthread_mutex_lock(&bufmgr->lock);
951 if (!_tbm_bo_lock(bo, device, opt)) {
952 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
953 TBM_LOG("[libtbm:%d] "
954 "error %s:%d fail to lock bo:%p)\n",
955 getpid(), __func__, __LINE__, bo);
956 pthread_mutex_unlock(&bufmgr->lock);
957 return (tbm_bo_handle) NULL;
960 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
961 if (bo_handle.ptr == NULL) {
962 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
963 TBM_LOG("[libtbm:%d] "
964 "error %s:%d fail to map bo:%p\n",
965 getpid(), __func__, __LINE__, bo);
968 pthread_mutex_unlock(&bufmgr->lock);
969 return (tbm_bo_handle) NULL;
972 /* increase the map_count */
975 pthread_mutex_unlock(&bufmgr->lock);
981 tbm_bo_unmap(tbm_bo bo)
983 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
990 pthread_mutex_lock(&bufmgr->lock);
992 ret = bufmgr->backend->bo_unmap(bo);
995 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
996 pthread_mutex_unlock(&bufmgr->lock);
1000 /* decrease the map_count */
1005 pthread_mutex_unlock(&bufmgr->lock);
1011 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1013 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1014 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1018 pthread_mutex_lock(&bo1->bufmgr->lock);
1020 if (bo1->bufmgr->backend->bo_size(bo1) != bo2->bufmgr->backend->bo_size(bo2)) {
1021 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1022 pthread_mutex_unlock(&bo1->bufmgr->lock);
1027 bo1->priv = bo2->priv;
1030 pthread_mutex_unlock(&bo1->bufmgr->lock);
1036 tbm_bo_locked(tbm_bo bo)
1038 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1042 bufmgr = bo->bufmgr;
1044 if (bufmgr->lock_type == LOCK_TRY_NEVER)
1047 pthread_mutex_lock(&bufmgr->lock);
1049 if (bo->lock_cnt > 0) {
1050 pthread_mutex_unlock(&bufmgr->lock);
1054 pthread_mutex_unlock(&bufmgr->lock);
1060 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1061 tbm_data_free data_free_func)
1063 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1065 tbm_user_data *data;
1067 /* check if the data according to the key exist if so, return false. */
1068 data = user_data_lookup(&bo->user_data_list, key);
1070 TBM_LOG("[libtbm:%d] "
1071 "waring: %s:%d user data already exist. key:%ld\n",
1072 getpid(), __func__, __LINE__, key);
1076 data = user_data_create(key, data_free_func);
1080 LIST_ADD(&data->item_link, &bo->user_data_list);
1086 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1088 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1090 tbm_user_data *old_data;
1092 if (LIST_IS_EMPTY(&bo->user_data_list))
1095 old_data = user_data_lookup(&bo->user_data_list, key);
1099 if (old_data->data && old_data->free_func)
1100 old_data->free_func(old_data->data);
1102 old_data->data = data;
1108 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1110 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1112 tbm_user_data *old_data;
1114 if (!data || LIST_IS_EMPTY(&bo->user_data_list))
1117 old_data = user_data_lookup(&bo->user_data_list, key);
1123 *data = old_data->data;
1129 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1131 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1133 tbm_user_data *old_data = (void *)0;
1135 if (LIST_IS_EMPTY(&bo->user_data_list))
1138 old_data = user_data_lookup(&bo->user_data_list, key);
1142 user_data_delete(old_data);
1148 tbm_get_last_error(void)
1150 return tbm_last_error;
1154 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1156 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1158 unsigned int capability = TBM_BUFMGR_CAPABILITY_NONE;
1160 if (bufmgr->backend->bo_import && bufmgr->backend->bo_export)
1161 capability |= TBM_BUFMGR_CAPABILITY_SHARE_KEY;
1163 if (bufmgr->backend->bo_import_fd && bufmgr->backend->bo_export_fd)
1164 capability |= TBM_BUFMGR_CAPABILITY_SHARE_FD;
1170 tbm_bo_get_flags(tbm_bo bo)
1172 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1178 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1180 TBM_RETURN_IF_FAIL(bufmgr != NULL);
1181 tbm_bo bo = NULL, tmp_bo = NULL;
1184 tbm_surface_h surf = NULL, tmp_surf = NULL;
1187 char app_name[255] = {0,};
1188 unsigned int pid = 0;
1190 pthread_mutex_lock(&gLock);
1193 _tbm_util_get_appname_from_pid(getpid(), app_name);
1194 _tbm_util_get_appname_brief(app_name);
1195 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1196 app_name, getpid());
1197 memset(app_name, 0x0, 255 * sizeof(char));
1199 TBM_DEBUG("[tbm_surface information]\n");
1200 TBM_DEBUG("no surface refcnt width height bpp size num_bos num_planes flags format app_name\n");
1201 /* show the tbm_surface information in surf_list */
1202 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1203 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1204 pid = _tbm_surface_internal_get_debug_pid(surf);
1206 /* if pid is null, set the self_pid */
1210 _tbm_util_get_appname_from_pid(pid, app_name);
1211 _tbm_util_get_appname_brief(app_name);
1213 TBM_DEBUG("%-4d%-23p%-6d%-7d%-8d%-5d%-12d%-10d%-9d%-4d%-20s%s\n",
1220 surf->info.size / 1024,
1224 _tbm_surface_internal_format_to_str(surf->info.format),
1227 for (i = 0; i < surf->num_bos; i++) {
1228 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1230 surf->bos[i]->ref_cnt,
1231 tbm_bo_size(surf->bos[i]) / 1024);
1234 memset(app_name, 0x0, 255 * sizeof(char));
1237 TBM_DEBUG("no tbm_surfaces.\n");
1241 TBM_DEBUG("[tbm_bo information]\n");
1242 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1244 /* show the tbm_bo information in bo_list */
1245 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1246 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1247 TBM_DEBUG("%-4d%-11p %-6d%-12d%-9d%-9d%-4d%-11p\n",
1251 tbm_bo_size(bo) / 1024,
1258 TBM_DEBUG("no tbm_bos.\n");
1262 TBM_DEBUG("===============================================================\n");
1264 pthread_mutex_unlock(&gLock);
1269 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1271 TBM_LOG("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1272 TBM_LOG("Not implemented yet.\n");
1275 /* internal function */
1277 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1279 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1281 bo->surface = surface;
1287 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1289 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1293 pthread_mutex_lock(&bufmgr->lock);
1295 if (!bufmgr->backend->bufmgr_bind_native_display) {
1296 pthread_mutex_unlock(&bufmgr->lock);
1300 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1302 pthread_mutex_unlock(&bufmgr->lock);
1306 pthread_mutex_unlock(&bufmgr->lock);