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"
37 #include "tbm_bufmgr_tgl.h"
43 #define DBG(...) if(bDebug&0x1) TBM_LOG (__VA_ARGS__)
44 #define DBG_LOCK(...) if(bDebug&0x2) TBM_LOG (__VA_ARGS__)
50 #define PREFIX_LIB "libtbm_"
51 #define SUFFIX_LIB ".so"
52 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
54 #define BO_IS_CACHEABLE(bo) ((bo->flags & TBM_BO_NONCACHABLE)?0:1)
55 #define DEVICE_IS_CACHE_AWARE(device) ((device == TBM_DEVICE_CPU)?(1):(0))
58 #define GLOBAL_KEY ((unsigned int)(-1))
59 #define INITIAL_KEY ((unsigned int)(-2))
61 #define CACHE_OP_CREATE (-1)
62 #define CACHE_OP_ATTACH (-2)
63 #define CACHE_OP_IMPORT (-3)
65 /* values to indicate unspecified fields in XF86ModReqInfo. */
66 #define MAJOR_UNSPEC 0xFF
67 #define MINOR_UNSPEC 0xFF
68 #define PATCH_UNSPEC 0xFFFF
69 #define ABI_VERS_UNSPEC 0xFFFFFFFF
71 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
72 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
73 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
74 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
75 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
85 DEVICE_CA, /* cache aware device */
86 DEVICE_CO /* cache oblivious device */
93 tbm_data_free free_func ;
95 /* link of user_data */
96 struct list_head item_link;
99 pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
100 tbm_bufmgr gBufMgr = NULL;
103 _tgl_init (int fd, unsigned int key)
105 struct tgl_attribute attr;
109 attr.timeout_ms = 1000;
111 err = ioctl (fd, TGL_IOC_INIT_LOCK, &attr);
114 TBM_LOG ( "[libtbm:%d] "
115 "error(%s) %s:%d key:%d\n",
116 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
124 _tgl_destroy (int fd, unsigned int key)
127 err = ioctl (fd, TGL_IOC_DESTROY_LOCK, key);
130 TBM_LOG ( "[libtbm:%d] "
131 "error(%s) %s:%d key:%d\n",
132 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
140 _tgl_lock (int fd, unsigned int key)
143 err = ioctl (fd, TGL_IOC_LOCK_LOCK, key);
146 TBM_LOG ("[libtbm:%d] "
147 "error(%s) %s:%d key:%d\n",
148 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
156 _tgl_unlock (int fd, unsigned int key)
159 err = ioctl (fd, TGL_IOC_UNLOCK_LOCK, key);
162 TBM_LOG ("[libtbm:%d] "
163 "error(%s) %s:%d key:%d\n",
164 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
172 _tgl_set_data (int fd, unsigned int key, unsigned int val)
175 struct tgl_user_data arg;
179 err = ioctl (fd, TGL_IOC_SET_DATA, &arg);
182 TBM_LOG ("[libtbm:%d] "
183 "error(%s) %s:%d key:%d\n",
184 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
191 static inline unsigned int
192 _tgl_get_data (int fd, unsigned int key, unsigned int *locked)
195 struct tgl_user_data arg = {0,};
198 err = ioctl (fd, TGL_IOC_GET_DATA, &arg);
201 TBM_LOG ("[libtbm:%d] "
202 "error(%s) %s:%d key:%d\n",
203 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
208 *locked = arg.locked;
213 static tbm_user_data *
214 _user_data_lookup (struct list_head *user_data_list, unsigned long key)
216 tbm_user_data *user_data = NULL;
217 tbm_user_data *old_data = NULL, *tmp = NULL;
219 if (!LIST_IS_EMPTY (user_data_list))
221 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, user_data_list, item_link)
223 if (old_data->key == key)
225 user_data = old_data;
234 static tbm_user_data *
235 _user_data_create (unsigned long key, tbm_data_free data_free_func)
237 tbm_user_data * user_data = NULL;
239 user_data = calloc (1, sizeof (tbm_user_data));
243 user_data->key = key;
244 user_data->free_func = data_free_func;
245 user_data->data = (void *)0;
251 _user_data_delete (tbm_user_data *user_data)
253 if (user_data->data && user_data->free_func)
254 user_data->free_func(user_data->data);
256 LIST_DEL (&user_data->item_link);
262 _bo_lock (tbm_bo bo, int device, int opt)
264 tbm_bufmgr bufmgr = bo->bufmgr;
267 if (TBM_LOCK_CTRL_BACKEND_VALID(bufmgr->backend->flags))
269 if (bufmgr->backend->bo_lock2)
271 /* use bo_lock2 backend lock */
272 ret = bufmgr->backend->bo_lock2 (bo, device, opt);
274 else if (bufmgr->backend->bo_lock)
276 /* use bo_lock backend lock */
277 ret = bufmgr->backend->bo_lock (bo);
280 TBM_LOG ("[libtbm:%d] "
281 "error %s:%d no backend lock functions\n",
282 getpid(), __FUNCTION__, __LINE__);
286 /* use tizen global lock */
287 ret = _tgl_lock (bufmgr->lock_fd, bo->tgl_key);
294 _bo_unlock (tbm_bo bo)
296 tbm_bufmgr bufmgr = bo->bufmgr;
298 if (TBM_LOCK_CTRL_BACKEND_VALID(bufmgr->backend->flags))
300 if (bufmgr->backend->bo_unlock)
302 /* use backend unlock */
303 bufmgr->backend->bo_unlock (bo);
306 TBM_LOG ("[libtbm:%d] "
307 "error %s:%d no backend unlock functions\n",
308 getpid(), __FUNCTION__, __LINE__);
312 /* use tizen global unlock */
313 _tgl_unlock (bufmgr->lock_fd, bo->tgl_key);
318 _tbm_bo_init_state (tbm_bo bo, int opt)
320 tbm_bufmgr bufmgr = bo->bufmgr;
321 tbm_bo_cache_state cache_state;
323 RETURN_VAL_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
328 case CACHE_OP_CREATE: /*Create*/
329 if (bo->tgl_key == INITIAL_KEY)
330 bo->tgl_key = bufmgr->backend->bo_get_global_key (bo);
332 _tgl_init (bufmgr->lock_fd, bo->tgl_key);
334 cache_state.data.isCacheable = BO_IS_CACHEABLE(bo);
335 cache_state.data.isDirtied = DEVICE_NONE;
336 cache_state.data.isCached = 0;
337 cache_state.data.cntFlush = 0;
339 _tgl_set_data (bufmgr->lock_fd, bo->tgl_key, cache_state.val);
341 case CACHE_OP_IMPORT: /*Import*/
342 if (bo->tgl_key == INITIAL_KEY)
343 bo->tgl_key = bufmgr->backend->bo_get_global_key (bo);
345 _tgl_init (bufmgr->lock_fd, bo->tgl_key);
355 _tbm_bo_destroy_state (tbm_bo bo)
357 tbm_bufmgr bufmgr = bo->bufmgr;
359 RETURN_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags));
361 _tgl_destroy (bufmgr->lock_fd, bo->tgl_key);
365 _tbm_bo_set_state (tbm_bo bo, int device, int opt)
367 tbm_bufmgr bufmgr = bo->bufmgr;
369 unsigned short cntFlush = 0;
370 unsigned int is_locked;
372 RETURN_VAL_CHECK_FLAG (TBM_CACHE_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
374 /* get cache state of a bo */
375 bo->cache_state.val = _tgl_get_data (bufmgr->lock_fd, bo->tgl_key, &is_locked);
377 if (!bo->cache_state.data.isCacheable)
380 /* get global cache flush count */
381 cntFlush = (unsigned short)_tgl_get_data (bufmgr->lock_fd, GLOBAL_KEY, NULL);
383 if (DEVICE_IS_CACHE_AWARE (device))
385 if (bo->cache_state.data.isDirtied == DEVICE_CO &&
386 bo->cache_state.data.isCached)
388 need_flush = TBM_CACHE_INV;
391 bo->cache_state.data.isCached = 1;
392 if (opt & TBM_OPTION_WRITE)
393 bo->cache_state.data.isDirtied = DEVICE_CA;
396 if( bo->cache_state.data.isDirtied != DEVICE_CA )
397 bo->cache_state.data.isDirtied = DEVICE_NONE;
402 if (bo->cache_state.data.isDirtied == DEVICE_CA &&
403 bo->cache_state.data.isCached &&
404 bo->cache_state.data.cntFlush == cntFlush)
406 need_flush = TBM_CACHE_CLN | TBM_CACHE_ALL;
409 if (opt & TBM_OPTION_WRITE)
410 bo->cache_state.data.isDirtied = DEVICE_CO;
413 if( bo->cache_state.data.isDirtied != DEVICE_CO )
414 bo->cache_state.data.isDirtied = DEVICE_NONE;
420 /* set global cache flush count */
421 if (need_flush & TBM_CACHE_ALL)
422 _tgl_set_data (bufmgr->lock_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
424 /* call backend cache flush */
425 bufmgr->backend->bo_cache_flush (bo, need_flush);
427 DBG ("[libtbm:%d] \tcache(%d,%d,%d)....flush:0x%x, cntFlush(%d)\n", getpid(),
428 bo->cache_state.data.isCacheable,
429 bo->cache_state.data.isCached,
430 bo->cache_state.data.isDirtied,
431 need_flush, cntFlush);
438 _tbm_bo_save_state (tbm_bo bo)
440 tbm_bufmgr bufmgr = bo->bufmgr;
441 unsigned short cntFlush = 0;
443 RETURN_CHECK_FLAG (TBM_CACHE_CTRL_BACKEND_VALID(bufmgr->backend->flags));
445 /* get global cache flush count */
446 cntFlush = (unsigned short)_tgl_get_data (bufmgr->lock_fd, GLOBAL_KEY, NULL);
448 /* save global cache flush count */
449 bo->cache_state.data.cntFlush = cntFlush;
450 _tgl_set_data(bufmgr->lock_fd, bo->tgl_key, bo->cache_state.val);
455 _tbm_bo_lock (tbm_bo bo, int device, int opt)
457 tbm_bufmgr bufmgr = NULL;
466 /* do not try to lock the bo */
467 if (bufmgr->lock_type == LOCK_TRY_NEVER)
470 if (bo->lock_cnt < 0)
472 TBM_LOG ("[libtbm:%d] "
473 "error %s:%d bo:%p(%d) LOCK_CNT=%d\n",
474 getpid(), __FUNCTION__, __LINE__, bo, bo->tgl_key, bo->lock_cnt);
478 if (bufmgr->lock_type == LOCK_TRY_ONCE)
480 if (bo->lock_cnt == 0)
482 pthread_mutex_unlock (&bufmgr->lock);
483 ret = _bo_lock (bo, device, opt);
484 pthread_mutex_lock (&bufmgr->lock);
489 else if (bufmgr->lock_type == LOCK_TRY_ALWAYS)
491 pthread_mutex_unlock (&bufmgr->lock);
492 ret = _bo_lock (bo, device, opt);
493 pthread_mutex_lock (&bufmgr->lock);
498 TBM_LOG ("[libtbm:%d] "
499 "error %s:%d bo:%p lock_type is wrong.\n",
500 getpid(), __FUNCTION__, __LINE__, bo);
502 DBG_LOCK ("[libtbm:%d] >> LOCK bo:%p(%d, %d->%d)\n", getpid(),
503 bo, bo->tgl_key, old, bo->lock_cnt);
509 _tbm_bo_unlock (tbm_bo bo)
511 tbm_bufmgr bufmgr = NULL;
520 /* do not try to unlock the bo */
521 if (bufmgr->lock_type == LOCK_TRY_NEVER)
525 if (bufmgr->lock_type == LOCK_TRY_ONCE)
527 if (bo->lock_cnt > 0)
530 if (bo->lock_cnt == 0)
534 else if (bufmgr->lock_type == LOCK_TRY_ALWAYS)
536 if (bo->lock_cnt > 0)
543 TBM_LOG ("[libtbm:%d] "
544 "error %s:%d bo:%p lock_type is wrong.\n",
545 getpid(), __FUNCTION__, __LINE__, bo);
547 if (bo->lock_cnt < 0)
550 DBG_LOCK ("[libtbm:%d] << unlock bo:%p(%d, %d->%d)\n", getpid(),
551 bo, bo->tgl_key, old, bo->lock_cnt);
555 _tbm_bo_is_valid(tbm_bo bo)
557 tbm_bo old_data=NULL, tmp = NULL;;
562 if(!LIST_IS_EMPTY (&gBufMgr->bo_list))
564 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, &gBufMgr->bo_list, item_link)
577 _tbm_bo_ref (tbm_bo bo)
583 _tbm_bo_unref (tbm_bo bo)
585 tbm_bufmgr bufmgr = bo->bufmgr;
586 tbm_user_data *old_data = NULL, *tmp = NULL;
588 if (bo->ref_cnt <= 0)
592 if (bo->ref_cnt == 0)
594 /* destory the user_data_list */
595 if (!LIST_IS_EMPTY (&bo->user_data_list))
597 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, &bo->user_data_list, item_link)
599 DBG ("[libtbm:%d] free user_data \n", getpid());
600 _user_data_delete (old_data);
604 if (bo->lock_cnt > 0)
606 TBM_LOG ("[libtbm:%d] "
607 "error %s:%d lock_cnt:%d\n",
608 getpid(), __FUNCTION__, __LINE__, bo->lock_cnt);
612 /* Destroy Global Lock */
613 _tbm_bo_destroy_state (bo);
615 /* call the bo_free */
616 bufmgr->backend->bo_free (bo);
619 LIST_DEL (&bo->item_link);
627 _tbm_bufmgr_init_state (tbm_bufmgr bufmgr)
629 RETURN_VAL_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
631 bufmgr->lock_fd = open (tgl_devfile, O_RDWR);
633 if(bufmgr->lock_fd < 0)
635 bufmgr->lock_fd = open (tgl_devfile1, O_RDWR);
636 if(bufmgr->lock_fd < 0)
639 TBM_LOG ("[libtbm:%d] "
640 "error: Fail to open global_lock:%s\n",
641 getpid(), tgl_devfile);
646 if (!_tgl_init(bufmgr->lock_fd, GLOBAL_KEY))
648 TBM_LOG ("[libtbm:%d] "
649 "error: Fail to initialize the tgl\n",
658 _tbm_bufmgr_destroy_state (tbm_bufmgr bufmgr)
660 RETURN_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags));
662 close (bufmgr->lock_fd);
666 _check_version (TBMModuleVersionInfo *data)
671 abimaj = GET_ABI_MAJOR (data->abiversion);
672 abimin = GET_ABI_MINOR (data->abiversion);
674 TBM_LOG ("[libtbm:%d] "
675 "TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
676 getpid(), data->modname ? data->modname : "UNKNOWN!",
677 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
679 vermaj = GET_ABI_MAJOR (TBM_ABI_VERSION);
680 vermin = GET_ABI_MINOR (TBM_ABI_VERSION);
682 DBG ("[libtbm:%d] " "TBM ABI version %d.%d\n", getpid(), vermaj, vermin);
684 if (abimaj != vermaj)
686 TBM_LOG ("[libtbm:%d] "
687 "TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
688 getpid(), abimaj, vermaj);
691 else if (abimin > vermin)
693 TBM_LOG ("[libtbm:%d] "
694 "TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
695 getpid(), abimin, vermin);
702 _tbm_bufmgr_load_module (tbm_bufmgr bufmgr, int fd, const char *file)
704 char path[PATH_MAX] = {0,};
705 TBMModuleData *initdata = NULL;
708 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
710 module_data = dlopen (path, RTLD_LAZY);
713 TBM_LOG ("[libtbm:%d] "
714 "failed to load module: %s(%s)\n",
715 getpid(), dlerror(), file);
719 initdata = dlsym (module_data, "tbmModuleData");
723 TBMModuleVersionInfo *vers;
725 vers = initdata->vers;
726 init = initdata->init;
730 if (!_check_version (vers))
732 dlclose (module_data);
738 TBM_LOG ("[libtbm:%d] "
739 "Error: module does not supply version information.\n",
742 dlclose (module_data);
748 if(!init (bufmgr, fd))
750 TBM_LOG ("[libtbm:%d] "
751 "Fail to init module(%s)\n",
753 dlclose (module_data);
757 if (!bufmgr->backend || !bufmgr->backend->priv)
759 TBM_LOG ("[libtbm:%d] "
760 "Error: module(%s) wrong operation. Check backend or backend's priv.\n",
762 dlclose (module_data);
768 TBM_LOG ("[libtbm:%d] "
769 "Error: module does not supply init symbol.\n", getpid());
770 dlclose (module_data);
776 TBM_LOG ("[libtbm:%d] "
777 "Error: module does not have data object.\n", getpid());
778 dlclose (module_data);
782 bufmgr->module_data = module_data;
784 TBM_LOG ("[libtbm:%d] "
785 "Success to load module(%s)\n", getpid(), file);
790 static int _tbm_load_module (tbm_bufmgr bufmgr, int fd)
792 struct dirent **namelist;
793 const char *p = NULL;
797 /* load bufmgr priv from default lib */
798 ret = _tbm_bufmgr_load_module (bufmgr, fd, DEFAULT_LIB);
800 /* load bufmgr priv from configured path */
803 n = scandir (BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
805 TBM_LOG ("[libtbm:%d] "
806 "no files : %s\n", getpid(), BUFMGR_MODULE_DIR);
811 if (!ret && strstr (namelist[n]->d_name, PREFIX_LIB))
813 p = strstr (namelist[n]->d_name, SUFFIX_LIB);
816 if (!strcmp (p, SUFFIX_LIB))
818 ret = _tbm_bufmgr_load_module (bufmgr, fd, namelist[n]->d_name);
832 tbm_bufmgr_init (int fd)
837 pthread_mutex_lock (&gLock);
840 env = getenv("GEM_DEBUG");
844 TBM_LOG ("GEM_DEBUG=%s\n", env);
850 /* initialize buffer manager */
853 TBM_LOG ("[libtbm:%d] use previous gBufMgr\n", getpid());
854 gBufMgr->ref_count++;
855 TBM_LOG ("[libtbm:%d] bufmgr ref: fd=%d, ref_count:%d\n",
856 getpid(), gBufMgr->fd, gBufMgr->ref_count);
857 pthread_mutex_unlock (&gLock);
864 fd = tbm_bufmgr_get_drm_fd_x11();
866 fd = tbm_bufmgr_get_drm_fd_wayland();
870 TBM_LOG ("[libtbm:%d] Fail get drm fd\n", getpid());
871 pthread_mutex_unlock (&gLock);
877 TBM_LOG ("[libtbm:%d] bufmgr init: fd=%d\n", getpid(), fd);
879 /* allocate bufmgr */
880 gBufMgr = calloc (1, sizeof(struct _tbm_bufmgr));
883 pthread_mutex_unlock (&gLock);
887 /* load bufmgr priv from env */
888 if (!_tbm_load_module(gBufMgr, fd))
890 TBM_LOG ("[libtbm:%d] "
891 "error : Fail to load bufmgr backend\n",
895 pthread_mutex_unlock (&gLock);
899 gBufMgr->fd_flag = fd_flag;
901 gBufMgr->ref_count = 1;
903 TBM_LOG ("[libtbm:%d] create tizen bufmgr: ref_count:%d\n", getpid(), gBufMgr->ref_count);
905 if (pthread_mutex_init (&gBufMgr->lock, NULL) != 0)
907 gBufMgr->backend->bufmgr_deinit (gBufMgr->backend->priv);
908 tbm_backend_free (gBufMgr->backend);
909 dlclose (gBufMgr->module_data);
912 pthread_mutex_unlock (&gLock);
916 /* intialize the tizen global status */
917 if (!_tbm_bufmgr_init_state (gBufMgr))
919 TBM_LOG ("[libtbm:%d] "
920 "error: Fail to init state\n",
922 gBufMgr->backend->bufmgr_deinit (gBufMgr->backend->priv);
923 tbm_backend_free (gBufMgr->backend);
924 pthread_mutex_destroy (&gBufMgr->lock);
925 dlclose (gBufMgr->module_data);
928 pthread_mutex_unlock (&gLock);
932 /* setup the lock_type */
933 env = getenv ("BUFMGR_LOCK_TYPE");
934 if (env && !strcmp (env, "always"))
935 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
936 else if(env && !strcmp(env, "none"))
937 gBufMgr->lock_type = LOCK_TRY_NEVER;
938 else if(env && !strcmp(env, "once"))
939 gBufMgr->lock_type = LOCK_TRY_ONCE;
941 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
943 DBG ("[libtbm:%d] BUFMGR_LOCK_TYPE=%s\n", getpid(), env?env:"default:once");
945 /* setup the map_cache */
946 env = getenv ("BUFMGR_MAP_CACHE");
947 if (env && !strcmp (env, "false"))
948 gBufMgr->use_map_cache = 0;
950 gBufMgr->use_map_cache = 1;
951 DBG ("[libtbm:%d] BUFMGR_MAP_CACHE=%s\n", getpid(), env?env:"default:true");
953 /* intialize bo_list */
954 LIST_INITHEAD (&gBufMgr->bo_list);
956 /* intialize surf_list */
957 LIST_INITHEAD (&gBufMgr->surf_list);
959 pthread_mutex_unlock (&gLock);
964 tbm_bufmgr_deinit (tbm_bufmgr bufmgr)
966 TBM_RETURN_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr));
971 tbm_surface_h surf = NULL;
972 tbm_surface_h tmp_surf = NULL;
974 pthread_mutex_lock (&gLock);
977 if (bufmgr->ref_count > 0)
979 TBM_LOG ("[libtbm:%d] "
980 "tizen bufmgr destroy: bufmgr:%p, ref_count:%d\n",
981 getpid(), bufmgr, bufmgr->ref_count);
982 pthread_mutex_unlock (&gLock);
986 /* destroy bo_list */
987 if(!LIST_IS_EMPTY (&bufmgr->bo_list))
989 LIST_FOR_EACH_ENTRY_SAFE (bo, tmp, &bufmgr->bo_list, item_link)
991 TBM_LOG ("[libtbm:%d] "
992 "Un-freed bo(%p, ref:%d) \n",
993 getpid(), bo, bo->ref_cnt);
999 /* destroy surf_list */
1000 if(!LIST_IS_EMPTY (&bufmgr->surf_list))
1002 LIST_FOR_EACH_ENTRY_SAFE (surf, tmp_surf, &bufmgr->surf_list, item_link)
1004 TBM_LOG ("[libtbm:%d] "
1005 "Destroy surf(%p) \n",
1007 tbm_surface_destroy(surf);
1011 /* destroy the tizen global status */
1012 _tbm_bufmgr_destroy_state (bufmgr);
1014 /* destroy bufmgr priv */
1015 bufmgr->backend->bufmgr_deinit (bufmgr->backend->priv);
1016 bufmgr->backend->priv = NULL;
1017 tbm_backend_free (bufmgr->backend);
1018 bufmgr->backend = NULL;
1020 pthread_mutex_destroy (&bufmgr->lock);
1022 TBM_LOG ("[libtbm:%d] "
1023 "tizen bufmgr destroy: bufmgr:%p\n",
1026 dlclose (bufmgr->module_data);
1035 pthread_mutex_unlock (&gLock);
1039 tbm_bo_size (tbm_bo bo)
1041 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), 0);
1043 tbm_bufmgr bufmgr = bo->bufmgr;
1046 pthread_mutex_lock(&bufmgr->lock);
1048 size = bufmgr->backend->bo_size(bo);
1050 pthread_mutex_unlock(&bufmgr->lock);
1056 tbm_bo_ref (tbm_bo bo)
1058 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
1060 tbm_bufmgr bufmgr = bo->bufmgr;
1062 pthread_mutex_lock(&bufmgr->lock);
1066 pthread_mutex_unlock(&bufmgr->lock);
1072 tbm_bo_unref (tbm_bo bo)
1074 TBM_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
1076 tbm_bufmgr bufmgr = bo->bufmgr;
1078 pthread_mutex_lock (&bufmgr->lock);
1082 pthread_mutex_unlock(&bufmgr->lock);
1086 tbm_bo_alloc (tbm_bufmgr bufmgr, int size, int flags)
1088 TBM_RETURN_VAL_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
1091 void * bo_priv = NULL;
1093 bo = calloc (1, sizeof(struct _tbm_bo));
1097 bo->bufmgr = bufmgr;
1099 pthread_mutex_lock (&bufmgr->lock);
1101 bo_priv = bufmgr->backend->bo_alloc (bo, size, flags);
1105 pthread_mutex_unlock (&bufmgr->lock);
1111 bo->tgl_key = INITIAL_KEY;
1115 if (!_tbm_bo_init_state (bo, CACHE_OP_CREATE))
1118 pthread_mutex_unlock (&bufmgr->lock);
1122 LIST_INITHEAD (&bo->user_data_list);
1124 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1126 pthread_mutex_unlock(&bufmgr->lock);
1132 tbm_bo_import (tbm_bufmgr bufmgr, unsigned int key)
1134 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1137 void * bo_priv = NULL;
1139 bo = calloc (1, sizeof(struct _tbm_bo));
1143 bo->bufmgr = bufmgr;
1145 pthread_mutex_lock (&bufmgr->lock);
1147 bo_priv = bufmgr->backend->bo_import (bo, key);
1151 pthread_mutex_unlock (&bufmgr->lock);
1156 bo->tgl_key = INITIAL_KEY;
1160 if (!_tbm_bo_init_state (bo, CACHE_OP_IMPORT))
1163 pthread_mutex_unlock (&bufmgr->lock);
1167 LIST_INITHEAD (&bo->user_data_list);
1169 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1171 pthread_mutex_unlock (&bufmgr->lock);
1177 tbm_bo_import_fd (tbm_bufmgr bufmgr, tbm_fd fd)
1185 tbm_bo_export (tbm_bo bo)
1187 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), 0);
1192 bufmgr = bo->bufmgr;
1194 pthread_mutex_lock (&bufmgr->lock);
1195 ret = bufmgr->backend->bo_export (bo);
1196 pthread_mutex_unlock (&bufmgr->lock);
1202 tbm_bo_export_fd (tbm_bo bo)
1211 tbm_bo_get_handle (tbm_bo bo, int device)
1213 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), (tbm_bo_handle)0);
1216 tbm_bo_handle bo_handle;
1218 bufmgr = bo->bufmgr;
1220 pthread_mutex_lock (&bufmgr->lock);
1221 bo_handle = bufmgr->backend->bo_get_handle (bo, device);
1222 pthread_mutex_unlock (&bufmgr->lock);
1228 tbm_bo_map (tbm_bo bo, int device, int opt)
1230 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), (tbm_bo_handle)0);
1233 tbm_bo_handle bo_handle;
1235 bufmgr = bo->bufmgr;
1237 pthread_mutex_lock (&bufmgr->lock);
1239 bo_handle = bufmgr->backend->bo_get_handle (bo, device);
1241 if (!_tbm_bo_lock (bo, device, opt))
1243 TBM_LOG ("[libtbm:%d] "
1244 "error %s:%d fail to lock bo:%p)\n",
1245 getpid(), __FUNCTION__, __LINE__, bo);
1247 pthread_mutex_unlock (&bufmgr->lock);
1248 return (tbm_bo_handle)NULL;
1251 bo_handle = bufmgr->backend->bo_map (bo, device, opt);
1252 if (bo_handle.ptr == NULL)
1254 TBM_LOG ("[libtbm:%d] "
1255 "error %s:%d fail to map bo:%p\n",
1256 getpid(), __FUNCTION__, __LINE__, bo);
1259 pthread_mutex_unlock (&bufmgr->lock);
1260 return (tbm_bo_handle)NULL;
1263 if (bufmgr->use_map_cache == 1 && bo->map_cnt == 0)
1264 _tbm_bo_set_state (bo, device, opt);
1266 /* increase the map_count */
1269 pthread_mutex_unlock (&bufmgr->lock);
1275 tbm_bo_unmap (tbm_bo bo)
1277 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), 0);
1282 bufmgr = bo->bufmgr;
1284 pthread_mutex_lock (&bufmgr->lock);
1286 ret = bufmgr->backend->bo_unmap (bo);
1289 pthread_mutex_unlock (&bufmgr->lock);
1293 /* decrease the map_count */
1296 if (bo->map_cnt == 0)
1297 _tbm_bo_save_state (bo);
1299 _tbm_bo_unlock (bo);
1301 pthread_mutex_unlock (&bufmgr->lock);
1307 tbm_bo_swap (tbm_bo bo1, tbm_bo bo2)
1309 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo1), 0);
1310 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo2), 0);
1313 unsigned int tmp_key;
1315 if (bo1->bufmgr->backend->bo_size (bo1) != bo2->bufmgr->backend->bo_size (bo2))
1318 pthread_mutex_lock (&bo1->bufmgr->lock);
1320 tmp_key = bo1->tgl_key;
1321 bo1->tgl_key = bo2->tgl_key;
1322 bo2->tgl_key = tmp_key;
1325 bo1->priv = bo2->priv;
1328 pthread_mutex_unlock (&bo1->bufmgr->lock);
1334 tbm_bo_locked (tbm_bo bo)
1336 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), 0);
1340 bufmgr = bo->bufmgr;
1342 if (bufmgr->lock_type == LOCK_TRY_NEVER)
1345 pthread_mutex_lock (&bufmgr->lock);
1347 if (bo->lock_cnt > 0)
1349 pthread_mutex_unlock (&bufmgr->lock);
1353 pthread_mutex_unlock (&bufmgr->lock);
1360 tbm_bo_add_user_data (tbm_bo bo, unsigned long key, tbm_data_free data_free_func)
1362 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1364 tbm_user_data *data;
1366 /* check if the data according to the key exist if so, return false.*/
1367 data = _user_data_lookup (&bo->user_data_list, key);
1370 TBM_LOG ("[libtbm:%d] "
1371 "waring: %s:%d user data already exist. key:%ld\n",
1372 getpid(), __FUNCTION__, __LINE__, key);
1376 data = _user_data_create (key, data_free_func);
1380 LIST_ADD (&data->item_link, &bo->user_data_list);
1386 tbm_bo_set_user_data (tbm_bo bo, unsigned long key, void* data)
1388 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1390 tbm_user_data *old_data;
1392 if (LIST_IS_EMPTY (&bo->user_data_list))
1395 old_data = _user_data_lookup (&bo->user_data_list, key);
1399 if (old_data->data && old_data->free_func)
1400 old_data->free_func(old_data->data);
1402 old_data->data = data;
1408 tbm_bo_get_user_data (tbm_bo bo, unsigned long key, void** data)
1410 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1412 tbm_user_data* old_data;
1414 if (!data || LIST_IS_EMPTY (&bo->user_data_list))
1417 old_data = _user_data_lookup (&bo->user_data_list, key);
1424 *data = old_data->data;
1430 tbm_bo_delete_user_data (tbm_bo bo, unsigned long key)
1432 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1434 tbm_user_data *old_data = (void *)0;
1436 if (LIST_IS_EMPTY (&bo->user_data_list))
1439 old_data = _user_data_lookup (&bo->user_data_list, key);
1443 _user_data_delete (old_data);