1 /**************************************************************************
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
37 #include <sys/ioctl.h>
38 #include <sys/types.h>
46 #include "tbm_bufmgr.h"
47 #include "tbm_bufmgr_tgl.h"
48 #include "tbm_bufmgr_backend.h"
49 #include "tbm_bufmgr_int.h"
54 static int bDebug = 0;
55 #define DBG(...) if(bDebug&0x1) TBM_LOG (__VA_ARGS__)
56 #define DBG_LOCK(...) if(bDebug&0x2) TBM_LOG (__VA_ARGS__)
63 #define TBM_RETURN_IF_FAIL(cond) {\
65 TBM_LOG ("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
69 #define TBM_RETURN_VAL_IF_FAIL(cond, val) {\
71 TBM_LOG ("[%s] : '%s' failed.\n", __FUNCTION__, #cond);\
77 #define RETURN_CHECK_FLAG(cond) {\
82 #define RETURN_VAL_CHECK_FLAG(cond, val) {\
89 /* check validation */
90 #define TBM_BUFMGR_IS_VALID(mgr) (mgr && \
92 mgr->link.next->prev == &mgr->link)
93 #define TBM_BO_IS_VALID(bo) (bo && \
94 TBM_BUFMGR_IS_VALID(bo->bufmgr) && \
95 bo->item_link.next && \
96 bo->item_link.next->prev == &bo->item_link)
98 #define TBM_ALL_CTRL_BACKEND_VALID(flags) \
99 ((flags&TBM_CACHE_CTRL_BACKEND) &&\
100 (flags&TBM_LOCK_CTRL_BACKEND))
101 #define TBM_CACHE_CTRL_BACKEND_VALID(flags) \
102 (flags&TBM_CACHE_CTRL_BACKEND)
103 #define TBM_LOCK_CTRL_BACKEND_VALID(flags) \
104 (flags&TBM_LOCK_CTRL_BACKEND)
106 #define PREFIX_LIB "libtbm_"
107 #define SUFFIX_LIB ".so"
108 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
110 #define BO_IS_CACHEABLE(bo) ((bo->flags & TBM_BO_NONCACHABLE)?0:1)
111 #define DEVICE_IS_CACHE_AWARE(device) ((device == TBM_DEVICE_CPU)?(1):(0))
114 #define GLOBAL_KEY ((unsigned int)(-1))
115 #define INITIAL_KEY ((unsigned int)(-2))
117 #define CACHE_OP_CREATE (-1)
118 #define CACHE_OP_ATTACH (-2)
119 #define CACHE_OP_IMPORT (-3)
121 /* values to indicate unspecified fields in XF86ModReqInfo. */
122 #define MAJOR_UNSPEC 0xFF
123 #define MINOR_UNSPEC 0xFF
124 #define PATCH_UNSPEC 0xFFFF
125 #define ABI_VERS_UNSPEC 0xFFFFFFFF
127 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
128 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
129 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
130 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
131 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
141 DEVICE_CA, /* cache aware device */
142 DEVICE_CO /* cache oblivious device */
149 tbm_data_free free_func ;
151 /* link of user_data */
152 struct list_head item_link;
156 static struct list_head *gBufMgrs = NULL;
160 _tgl_init (int fd, unsigned int key)
162 struct tgl_attribute attr;
166 attr.timeout_ms = 1000;
168 err = ioctl (fd, TGL_IOC_INIT_LOCK, &attr);
171 TBM_LOG ( "[libtbm:%d] "
172 "error(%s) %s:%d key:%d\n",
173 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
181 _tgl_destroy (int fd, unsigned int key)
184 err = ioctl (fd, TGL_IOC_DESTROY_LOCK, key);
187 TBM_LOG ( "[libtbm:%d] "
188 "error(%s) %s:%d key:%d\n",
189 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
197 _tgl_lock (int fd, unsigned int key)
200 err = ioctl (fd, TGL_IOC_LOCK_LOCK, key);
203 TBM_LOG ("[libtbm:%d] "
204 "error(%s) %s:%d key:%d\n",
205 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
213 _tgl_unlock (int fd, unsigned int key)
216 err = ioctl (fd, TGL_IOC_UNLOCK_LOCK, key);
219 TBM_LOG ("[libtbm:%d] "
220 "error(%s) %s:%d key:%d\n",
221 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
229 _tgl_set_data (int fd, unsigned int key, unsigned int val)
232 struct tgl_user_data arg;
236 err = ioctl (fd, TGL_IOC_SET_DATA, &arg);
239 TBM_LOG ("[libtbm:%d] "
240 "error(%s) %s:%d key:%d\n",
241 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
248 static inline unsigned int
249 _tgl_get_data (int fd, unsigned int key, unsigned int *locked)
252 struct tgl_user_data arg = {0,};
255 err = ioctl (fd, TGL_IOC_GET_DATA, &arg);
258 TBM_LOG ("[libtbm:%d] "
259 "error(%s) %s:%d key:%d\n",
260 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
265 *locked = arg.locked;
270 static tbm_user_data *
271 _user_data_lookup (struct list_head *user_data_list, unsigned long key)
273 tbm_user_data *user_data = NULL;
274 tbm_user_data *old_data = NULL, *tmp = NULL;
276 if (!LIST_IS_EMPTY (user_data_list))
278 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, user_data_list, item_link)
280 if (old_data->key == key)
282 user_data = old_data;
291 static tbm_user_data *
292 _user_data_create (unsigned long key, tbm_data_free data_free_func)
294 tbm_user_data * user_data = NULL;
296 user_data = calloc (1, sizeof (tbm_user_data));
300 user_data->key = key;
301 user_data->free_func = data_free_func;
302 user_data->data = (void *)0;
308 _user_data_delete (tbm_user_data *user_data)
310 if (user_data->data && user_data->free_func)
311 user_data->free_func(user_data->data);
313 LIST_DEL (&user_data->item_link);
319 _bo_lock (tbm_bo bo, int device, int opt)
321 tbm_bufmgr bufmgr = bo->bufmgr;
324 if (TBM_LOCK_CTRL_BACKEND_VALID(bufmgr->backend->flags))
326 if (bufmgr->backend->bo_lock2)
328 /* use bo_lock2 backend lock */
329 ret = bufmgr->backend->bo_lock2 (bo, device, opt);
331 else if (bufmgr->backend->bo_lock)
333 /* use bo_lock backend lock */
334 ret = bufmgr->backend->bo_lock (bo);
337 TBM_LOG ("[libtbm:%d] "
338 "error %s:%d no backend lock functions\n",
339 getpid(), __FUNCTION__, __LINE__);
343 /* use tizen global lock */
344 ret = _tgl_lock (bufmgr->lock_fd, bo->tgl_key);
351 _bo_unlock (tbm_bo bo)
353 tbm_bufmgr bufmgr = bo->bufmgr;
355 if (TBM_LOCK_CTRL_BACKEND_VALID(bufmgr->backend->flags))
357 if (bufmgr->backend->bo_unlock)
359 /* use backend unlock */
360 bufmgr->backend->bo_unlock (bo);
363 TBM_LOG ("[libtbm:%d] "
364 "error %s:%d no backend unlock functions\n",
365 getpid(), __FUNCTION__, __LINE__);
369 /* use tizen global unlock */
370 _tgl_unlock (bufmgr->lock_fd, bo->tgl_key);
375 _tbm_bo_init_state (tbm_bo bo, int opt)
377 tbm_bufmgr bufmgr = bo->bufmgr;
378 tbm_bo_cache_state cache_state;
380 RETURN_VAL_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
385 case CACHE_OP_CREATE: /*Create*/
386 if (bo->tgl_key == INITIAL_KEY)
387 bo->tgl_key = bufmgr->backend->bo_get_global_key (bo);
389 _tgl_init (bufmgr->lock_fd, bo->tgl_key);
391 cache_state.data.isCacheable = BO_IS_CACHEABLE(bo);
392 cache_state.data.isDirtied = DEVICE_NONE;
393 cache_state.data.isCached = 0;
394 cache_state.data.cntFlush = 0;
396 _tgl_set_data (bufmgr->lock_fd, bo->tgl_key, cache_state.val);
398 case CACHE_OP_IMPORT: /*Import*/
399 if (bo->tgl_key == INITIAL_KEY)
400 bo->tgl_key = bufmgr->backend->bo_get_global_key (bo);
402 _tgl_init (bufmgr->lock_fd, bo->tgl_key);
412 _tbm_bo_destroy_state (tbm_bo bo)
414 tbm_bufmgr bufmgr = bo->bufmgr;
416 RETURN_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags));
418 _tgl_destroy (bufmgr->lock_fd, bo->tgl_key);
422 _tbm_bo_set_state (tbm_bo bo, int device, int opt)
424 tbm_bufmgr bufmgr = bo->bufmgr;
426 unsigned short cntFlush = 0;
427 unsigned int is_locked;
429 RETURN_VAL_CHECK_FLAG (TBM_CACHE_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
431 /* get cache state of a bo */
432 bo->cache_state.val = _tgl_get_data (bufmgr->lock_fd, bo->tgl_key, &is_locked);
434 if (!bo->cache_state.data.isCacheable)
437 /* get global cache flush count */
438 cntFlush = (unsigned short)_tgl_get_data (bufmgr->lock_fd, GLOBAL_KEY, NULL);
440 if (DEVICE_IS_CACHE_AWARE (device))
442 if (bo->cache_state.data.isDirtied == DEVICE_CO &&
443 bo->cache_state.data.isCached)
445 need_flush = TBM_CACHE_INV;
448 bo->cache_state.data.isCached = 1;
449 if (opt & TBM_OPTION_WRITE)
450 bo->cache_state.data.isDirtied = DEVICE_CA;
452 bo->cache_state.data.isDirtied = DEVICE_NONE;
456 if (bo->cache_state.data.isDirtied == DEVICE_CA &&
457 bo->cache_state.data.isCached &&
458 bo->cache_state.data.cntFlush == cntFlush)
460 need_flush = TBM_CACHE_CLN | TBM_CACHE_ALL;
463 if (opt & TBM_OPTION_WRITE)
464 bo->cache_state.data.isDirtied = DEVICE_CO;
466 bo->cache_state.data.isDirtied = DEVICE_NONE;
471 /* call backend cache flush */
472 bufmgr->backend->bo_cache_flush (bo, need_flush);
474 /* set global cache flush count */
475 if (need_flush & TBM_CACHE_ALL)
476 _tgl_set_data (bufmgr->lock_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
478 DBG ("[libtbm:%d] \tcache(%d,%d,%d)....flush:0x%x, cntFlush(%d)\n", getpid(),
479 bo->cache_state.data.isCacheable,
480 bo->cache_state.data.isCached,
481 bo->cache_state.data.isDirtied,
482 need_flush, cntFlush);
489 _tbm_bo_save_state (tbm_bo bo)
491 tbm_bufmgr bufmgr = bo->bufmgr;
492 unsigned short cntFlush = 0;
494 RETURN_CHECK_FLAG (TBM_CACHE_CTRL_BACKEND_VALID(bufmgr->backend->flags));
496 /* get global cache flush count */
497 cntFlush = (unsigned short)_tgl_get_data (bufmgr->lock_fd, GLOBAL_KEY, NULL);
499 /* save global cache flush count */
500 bo->cache_state.data.cntFlush = cntFlush;
501 _tgl_set_data(bufmgr->lock_fd, bo->tgl_key, bo->cache_state.val);
506 _tbm_bo_lock (tbm_bo bo, int device, int opt)
508 tbm_bufmgr bufmgr = NULL;
517 /* do not try to lock the bo */
518 if (bufmgr->lock_type == LOCK_TRY_NEVER)
521 if (bo->lock_cnt < 0)
523 TBM_LOG ("[libtbm:%d] "
524 "error %s:%d bo:%p(%d) LOCK_CNT=%d\n",
525 getpid(), __FUNCTION__, __LINE__, bo, bo->tgl_key, bo->lock_cnt);
529 if (bufmgr->lock_type == LOCK_TRY_ONCE)
531 if (bo->lock_cnt == 0)
533 pthread_mutex_unlock (&bufmgr->lock);
534 ret = _bo_lock (bo, device, opt);
535 pthread_mutex_lock (&bufmgr->lock);
540 else if (bufmgr->lock_type == LOCK_TRY_ALWAYS)
542 pthread_mutex_unlock (&bufmgr->lock);
543 ret = _bo_lock (bo, device, opt);
544 pthread_mutex_lock (&bufmgr->lock);
549 TBM_LOG ("[libtbm:%d] "
550 "error %s:%d bo:%p lock_type is wrong.\n",
551 getpid(), __FUNCTION__, __LINE__, bo);
553 DBG_LOCK ("[libtbm:%d] >> LOCK bo:%p(%d, %d->%d)\n", getpid(),
554 bo, bo->tgl_key, old, bo->lock_cnt);
560 _tbm_bo_unlock (tbm_bo bo)
562 tbm_bufmgr bufmgr = NULL;
571 /* do not try to unlock the bo */
572 if (bufmgr->lock_type == LOCK_TRY_NEVER)
576 if (bufmgr->lock_type == LOCK_TRY_ONCE)
578 if (bo->lock_cnt > 0)
581 if (bo->lock_cnt == 0)
585 else if (bufmgr->lock_type == LOCK_TRY_ALWAYS)
587 if (bo->lock_cnt > 0)
594 TBM_LOG ("[libtbm:%d] "
595 "error %s:%d bo:%p lock_type is wrong.\n",
596 getpid(), __FUNCTION__, __LINE__, bo);
598 if (bo->lock_cnt < 0)
601 DBG_LOCK ("[libtbm:%d] << unlock bo:%p(%d, %d->%d)\n", getpid(),
602 bo, bo->tgl_key, old, bo->lock_cnt);
607 _tbm_bo_ref (tbm_bo bo)
613 _tbm_bo_unref (tbm_bo bo)
615 tbm_bufmgr bufmgr = bo->bufmgr;
616 tbm_user_data *old_data = NULL, *tmp = NULL;
618 if (bo->ref_cnt <= 0)
622 if (bo->ref_cnt == 0)
624 /* destory the user_data_list */
625 if (!LIST_IS_EMPTY (&bo->user_data_list))
627 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, &bo->user_data_list, item_link)
629 DBG ("[libtbm:%d] free user_data \n", getpid());
630 _user_data_delete (old_data);
634 if (bo->lock_cnt > 0)
636 TBM_LOG ("[libtbm:%d] "
637 "error %s:%d lock_cnt:%d\n",
638 getpid(), __FUNCTION__, __LINE__, bo->lock_cnt);
642 /* Destroy Global Lock */
643 _tbm_bo_destroy_state (bo);
645 /* call the bo_free */
646 bufmgr->backend->bo_free (bo);
649 LIST_DEL (&bo->item_link);
657 _tbm_bufmgr_init_state (tbm_bufmgr bufmgr)
659 RETURN_VAL_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
661 bufmgr->lock_fd = open (tgl_devfile, O_RDWR);
663 if(bufmgr->lock_fd < 0)
665 bufmgr->lock_fd = open (tgl_devfile1, O_RDWR);
666 if(bufmgr->lock_fd < 0)
669 TBM_LOG ("[libtbm:%d] "
670 "error: Fail to open global_lock:%s\n",
671 getpid(), tgl_devfile);
676 if (!_tgl_init(bufmgr->lock_fd, GLOBAL_KEY))
678 TBM_LOG ("[libtbm:%d] "
679 "error: Fail to initialize the tgl\n",
688 _tbm_bufmgr_destroy_state (tbm_bufmgr bufmgr)
690 RETURN_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags));
692 close (bufmgr->lock_fd);
696 _check_version (TBMModuleVersionInfo *data)
701 abimaj = GET_ABI_MAJOR (data->abiversion);
702 abimin = GET_ABI_MINOR (data->abiversion);
704 TBM_LOG ("[libtbm:%d] "
705 "TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
706 getpid(), data->modname ? data->modname : "UNKNOWN!",
707 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
709 vermaj = GET_ABI_MAJOR (TBM_ABI_VERSION);
710 vermin = GET_ABI_MINOR (TBM_ABI_VERSION);
712 DBG ("[libtbm:%d] " "TBM ABI version %d.%d\n", getpid(), vermaj, vermin);
714 if (abimaj != vermaj)
716 TBM_LOG ("[libtbm:%d] "
717 "TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
718 getpid(), abimaj, vermaj);
721 else if (abimin > vermin)
723 TBM_LOG ("[libtbm:%d] "
724 "TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
725 getpid(), abimin, vermin);
732 _tbm_bufmgr_load_module (tbm_bufmgr bufmgr, int fd, const char *file)
734 char path[PATH_MAX] = {0,};
735 TBMModuleData *initdata = NULL;
738 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
740 module_data = dlopen (path, RTLD_LAZY);
743 TBM_LOG ("[libtbm:%d] "
744 "failed to load module: %s(%s)\n",
745 getpid(), dlerror(), file);
749 initdata = dlsym (module_data, "tbmModuleData");
753 TBMModuleVersionInfo *vers;
755 vers = initdata->vers;
756 init = initdata->init;
760 if (!_check_version (vers))
762 dlclose (module_data);
768 TBM_LOG ("[libtbm:%d] "
769 "Error: module does not supply version information.\n",
772 dlclose (module_data);
778 if(!init (bufmgr, fd))
780 TBM_LOG ("[libtbm:%d] "
781 "Fail to init module(%s)\n",
783 dlclose (module_data);
789 TBM_LOG ("[libtbm:%d] "
790 "Error: module does not supply init symbol.\n", getpid());
791 dlclose (module_data);
797 TBM_LOG ("[libtbm:%d] "
798 "Error: module does not have data object.\n", getpid());
799 dlclose (module_data);
803 bufmgr->module_data = module_data;
805 TBM_LOG ("[libtbm:%d] "
806 "Success to load module(%s)\n", getpid(), file);
811 static int _tbm_load_module (tbm_bufmgr bufmgr, int fd)
813 struct dirent **namelist;
814 const char *p = NULL;
818 /* load bufmgr priv from default lib */
819 ret = _tbm_bufmgr_load_module (bufmgr, fd, DEFAULT_LIB);
821 /* load bufmgr priv from configured path */
824 n = scandir (BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
826 TBM_LOG ("[libtbm:%d] "
827 "no files : %s\n", getpid(), BUFMGR_MODULE_DIR);
832 if (!ret && strstr (namelist[n]->d_name, PREFIX_LIB))
834 p = strstr (namelist[n]->d_name, SUFFIX_LIB);
835 if (!strcmp (p, SUFFIX_LIB))
837 ret = _tbm_bufmgr_load_module (bufmgr, fd, namelist[n]->d_name);
850 tbm_bufmgr_init (int fd)
853 tbm_bufmgr bufmgr = NULL;
856 env = getenv("GEM_DEBUG");
860 TBM_LOG ("GEM_DEBUG=%s\n", env);
866 /* initialize buffer manager */
872 gBufMgrs = malloc(sizeof(struct list_head));
873 LIST_INITHEAD(gBufMgrs);
877 LIST_FOR_EACH_ENTRY(bufmgr, gBufMgrs, link)
882 TBM_LOG ("[libtbm:%d] bufmgr ref: fd=%d, ref_count:%d\n",
883 getpid(), fd, bufmgr->ref_count);
889 TBM_LOG ("[libtbm:%d] bufmgr init: fd=%d\n", getpid(), fd);
891 /* allocate bufmgr */
892 bufmgr = calloc (1, sizeof(struct _tbm_bufmgr));
896 /* load bufmgr priv from env */
897 if (!_tbm_load_module(bufmgr, fd))
899 TBM_LOG ("[libtbm:%d] "
900 "error : Fail to load bufmgr backend\n",
907 bufmgr->ref_count = 1;
910 TBM_LOG ("[libtbm:%d] create tizen bufmgr: ref_count:%d\n",
911 getpid(), bufmgr->ref_count);
913 if (pthread_mutex_init (&bufmgr->lock, NULL) != 0)
915 bufmgr->backend->bufmgr_deinit (bufmgr);
921 /* intialize the tizen global status */
922 if (!_tbm_bufmgr_init_state (bufmgr))
924 TBM_LOG ("[libtbm:%d] "
925 "error: Fail to init state\n",
927 bufmgr->backend->bufmgr_deinit (bufmgr);
933 /* setup the lock_type */
934 env = getenv ("BUFMGR_LOCK_TYPE");
935 if (env && !strcmp (env, "always"))
936 bufmgr->lock_type = LOCK_TRY_ALWAYS;
937 else if(env && !strcmp(env, "none"))
938 bufmgr->lock_type = LOCK_TRY_NEVER;
940 bufmgr->lock_type = LOCK_TRY_ONCE;
941 DBG ("[libtbm:%d] BUFMGR_LOCK_TYPE=%s\n", getpid(), env?env:"default:once");
943 /* setup the map_cache */
944 env = getenv ("BUFMGR_MAP_CACHE");
945 if (env && !strcmp (env, "false"))
946 bufmgr->use_map_cache = 0;
948 bufmgr->use_map_cache = 1;
949 DBG ("[libtbm:%d] BUFMGR_MAP_CACHE=%s\n", getpid(), env?env:"default:true");
951 /* intialize bo_list */
952 LIST_INITHEAD (&bufmgr->bo_list);
954 /* add bufmgr to the gBufMgrs */
955 LIST_ADD(&bufmgr->link, gBufMgrs);
961 tbm_bufmgr_deinit (tbm_bufmgr bufmgr)
963 TBM_RETURN_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr));
969 if (bufmgr->ref_count > 0)
971 TBM_LOG ("[libtbm:%d] "
972 "tizen bufmgr destroy: bufmgr:%p, ref_cnt:%d\n",
973 getpid(), bufmgr, bufmgr->ref_count);
977 /* destroy bo_list */
978 if(!LIST_IS_EMPTY (&bufmgr->bo_list))
980 LIST_FOR_EACH_ENTRY_SAFE (bo, tmp, &bufmgr->bo_list, item_link)
982 TBM_LOG ("[libtbm:%d] "
983 "Un-freed bo(%p, ref:%d) \n",
984 getpid(), bo, bo->ref_cnt);
990 /* destroy the tizen global status */
991 _tbm_bufmgr_destroy_state (bufmgr);
993 /* destroy bufmgr priv */
994 bufmgr->backend->bufmgr_deinit (bufmgr->backend->priv);
995 bufmgr->backend->priv = NULL;
996 tbm_backend_free (bufmgr->backend);
997 bufmgr->backend = NULL;
999 pthread_mutex_destroy (&bufmgr->lock);
1001 TBM_LOG ("[libtbm:%d] "
1002 "tizen bufmgr destroy: bufmgr:%p, ref_cnt:%d\n",
1003 getpid(), bufmgr, bufmgr->ref_count);
1005 dlclose (bufmgr->module_data);
1007 LIST_DEL (&bufmgr->link);
1015 tbm_bo_size (tbm_bo bo)
1017 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1019 tbm_bufmgr bufmgr = bo->bufmgr;
1022 pthread_mutex_lock(&bufmgr->lock);
1023 size = bufmgr->backend->bo_size(bo);
1024 pthread_mutex_unlock(&bufmgr->lock);
1030 tbm_bo_ref (tbm_bo bo)
1032 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), NULL);
1034 tbm_bufmgr bufmgr = bo->bufmgr;
1036 pthread_mutex_lock(&bufmgr->lock);
1040 pthread_mutex_unlock(&bufmgr->lock);
1046 tbm_bo_unref (tbm_bo bo)
1048 TBM_RETURN_IF_FAIL(TBM_BO_IS_VALID(bo));
1050 tbm_bufmgr bufmgr = bo->bufmgr;
1052 pthread_mutex_lock (&bufmgr->lock);
1056 pthread_mutex_unlock(&bufmgr->lock);
1060 tbm_bo_alloc (tbm_bufmgr bufmgr, int size, int flags)
1062 TBM_RETURN_VAL_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
1065 void * bo_priv = NULL;
1067 bo = calloc (1, sizeof(struct _tbm_bo));
1071 bo->bufmgr = bufmgr;
1073 pthread_mutex_lock (&bufmgr->lock);
1075 bo_priv = bufmgr->backend->bo_alloc (bo, size, flags);
1079 pthread_mutex_unlock (&bufmgr->lock);
1085 bo->tgl_key = INITIAL_KEY;
1089 if (!_tbm_bo_init_state (bo, CACHE_OP_CREATE))
1092 pthread_mutex_unlock (&bufmgr->lock);
1096 LIST_INITHEAD (&bo->user_data_list);
1098 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1100 pthread_mutex_unlock(&bufmgr->lock);
1106 tbm_bo_import (tbm_bufmgr bufmgr, unsigned int key)
1108 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1111 void * bo_priv = NULL;
1113 bo = calloc (1, sizeof(struct _tbm_bo));
1117 bo->bufmgr = bufmgr;
1119 pthread_mutex_lock (&bufmgr->lock);
1121 bo_priv = bufmgr->backend->bo_import (bo, key);
1125 pthread_mutex_unlock (&bufmgr->lock);
1130 bo->tgl_key = INITIAL_KEY;
1134 if (!_tbm_bo_init_state (bo, CACHE_OP_IMPORT))
1137 pthread_mutex_unlock (&bufmgr->lock);
1141 LIST_INITHEAD (&bo->user_data_list);
1143 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1145 pthread_mutex_unlock (&bufmgr->lock);
1151 tbm_bo_export (tbm_bo bo)
1153 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1158 bufmgr = bo->bufmgr;
1160 pthread_mutex_lock (&bufmgr->lock);
1161 ret = bufmgr->backend->bo_export (bo);
1162 pthread_mutex_unlock (&bufmgr->lock);
1168 tbm_bo_get_handle (tbm_bo bo, int device)
1170 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), (tbm_bo_handle)0);
1173 tbm_bo_handle bo_handle;
1175 bufmgr = bo->bufmgr;
1177 pthread_mutex_lock (&bufmgr->lock);
1178 bo_handle = bufmgr->backend->bo_get_handle (bo, device);
1179 pthread_mutex_unlock (&bufmgr->lock);
1185 tbm_bo_map (tbm_bo bo, int device, int opt)
1187 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), (tbm_bo_handle)0);
1190 tbm_bo_handle bo_handle;
1192 bufmgr = bo->bufmgr;
1194 pthread_mutex_lock (&bufmgr->lock);
1196 bo_handle = bufmgr->backend->bo_map (bo, device, opt);
1198 _tbm_bo_lock (bo, device, opt);
1200 if (bufmgr->use_map_cache == 1 && bo->map_cnt == 0)
1201 _tbm_bo_set_state (bo, device, opt);
1203 /* increase the map_count */
1206 pthread_mutex_unlock (&bufmgr->lock);
1212 tbm_bo_unmap (tbm_bo bo)
1214 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1219 bufmgr = bo->bufmgr;
1221 pthread_mutex_lock (&bufmgr->lock);
1223 _tbm_bo_unlock (bo);
1225 ret = bufmgr->backend->bo_unmap (bo);
1227 /* decrease the map_count */
1230 if (bo->map_cnt == 0)
1231 _tbm_bo_save_state (bo);
1233 pthread_mutex_unlock (&bufmgr->lock);
1239 tbm_bo_swap (tbm_bo bo1, tbm_bo bo2)
1241 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo1), 0);
1242 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo2), 0);
1245 unsigned int tmp_key;
1247 if (bo1->bufmgr->backend->bo_size (bo1) != bo2->bufmgr->backend->bo_size (bo2))
1250 pthread_mutex_lock (&bo1->bufmgr->lock);
1252 tmp_key = bo1->tgl_key;
1253 bo1->tgl_key = bo2->tgl_key;
1254 bo2->tgl_key = tmp_key;
1257 bo1->priv = bo2->priv;
1260 pthread_mutex_unlock (&bo1->bufmgr->lock);
1266 tbm_bo_locked (tbm_bo bo)
1268 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1272 bufmgr = bo->bufmgr;
1274 if (bufmgr->lock_type == LOCK_TRY_NEVER)
1277 pthread_mutex_lock (&bufmgr->lock);
1279 if (bo->lock_cnt > 0)
1281 pthread_mutex_unlock (&bufmgr->lock);
1285 pthread_mutex_unlock (&bufmgr->lock);
1292 tbm_bo_add_user_data (tbm_bo bo, unsigned long key, tbm_data_free data_free_func)
1294 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1296 tbm_user_data *data;
1298 /* check if the data according to the key exist if so, return false.*/
1299 data = _user_data_lookup (&bo->user_data_list, key);
1302 TBM_LOG ("[libtbm:%d] "
1303 "waring: %s:%d user data already exist. key:%ld\n",
1304 getpid(), __FUNCTION__, __LINE__, key);
1308 data = _user_data_create (key, data_free_func);
1312 LIST_ADD (&data->item_link, &bo->user_data_list);
1318 tbm_bo_set_user_data (tbm_bo bo, unsigned long key, void* data)
1320 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1322 tbm_user_data *old_data;
1324 if (LIST_IS_EMPTY (&bo->user_data_list))
1327 old_data = _user_data_lookup (&bo->user_data_list, key);
1331 if (old_data->data && old_data->free_func)
1332 old_data->free_func(old_data->data);
1334 old_data->data = data;
1340 tbm_bo_get_user_data (tbm_bo bo, unsigned long key, void** data)
1342 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1344 tbm_user_data* old_data;
1346 if (!data || LIST_IS_EMPTY (&bo->user_data_list))
1349 old_data = _user_data_lookup (&bo->user_data_list, key);
1356 *data = old_data->data;
1362 tbm_bo_delete_user_data (tbm_bo bo, unsigned long key)
1364 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1366 tbm_user_data *old_data = (void *)0;
1368 if (LIST_IS_EMPTY (&bo->user_data_list))
1371 old_data = _user_data_lookup (&bo->user_data_list, key);
1375 _user_data_delete (old_data);