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;
102 static __thread tbm_error_e tbm_last_error = TBM_ERROR_NONE;
105 _tbm_set_last_result(tbm_error_e err)
107 tbm_last_error = err;
111 _tgl_init (int fd, unsigned int key)
113 struct tgl_attribute attr;
117 attr.timeout_ms = 1000;
119 err = ioctl (fd, TGL_IOC_INIT_LOCK, &attr);
122 TBM_LOG ( "[libtbm:%d] "
123 "error(%s) %s:%d key:%d\n",
124 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
132 _tgl_destroy (int fd, unsigned int key)
135 err = ioctl (fd, TGL_IOC_DESTROY_LOCK, key);
138 TBM_LOG ( "[libtbm:%d] "
139 "error(%s) %s:%d key:%d\n",
140 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
148 _tgl_lock (int fd, unsigned int key)
151 err = ioctl (fd, TGL_IOC_LOCK_LOCK, key);
154 TBM_LOG ("[libtbm:%d] "
155 "error(%s) %s:%d key:%d\n",
156 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
164 _tgl_unlock (int fd, unsigned int key)
167 err = ioctl (fd, TGL_IOC_UNLOCK_LOCK, key);
170 TBM_LOG ("[libtbm:%d] "
171 "error(%s) %s:%d key:%d\n",
172 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
180 _tgl_set_data (int fd, unsigned int key, unsigned int val)
183 struct tgl_user_data arg;
187 err = ioctl (fd, TGL_IOC_SET_DATA, &arg);
190 TBM_LOG ("[libtbm:%d] "
191 "error(%s) %s:%d key:%d\n",
192 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
199 static inline unsigned int
200 _tgl_get_data (int fd, unsigned int key, unsigned int *locked)
203 struct tgl_user_data arg = {0,};
206 err = ioctl (fd, TGL_IOC_GET_DATA, &arg);
209 TBM_LOG ("[libtbm:%d] "
210 "error(%s) %s:%d key:%d\n",
211 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
216 *locked = arg.locked;
221 static tbm_user_data *
222 _user_data_lookup (struct list_head *user_data_list, unsigned long key)
224 tbm_user_data *user_data = NULL;
225 tbm_user_data *old_data = NULL, *tmp = NULL;
227 if (!LIST_IS_EMPTY (user_data_list))
229 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, user_data_list, item_link)
231 if (old_data->key == key)
233 user_data = old_data;
242 static tbm_user_data *
243 _user_data_create (unsigned long key, tbm_data_free data_free_func)
245 tbm_user_data * user_data = NULL;
247 user_data = calloc (1, sizeof (tbm_user_data));
251 user_data->key = key;
252 user_data->free_func = data_free_func;
253 user_data->data = (void *)0;
259 _user_data_delete (tbm_user_data *user_data)
261 if (user_data->data && user_data->free_func)
262 user_data->free_func(user_data->data);
264 LIST_DEL (&user_data->item_link);
270 _bo_lock (tbm_bo bo, int device, int opt)
272 tbm_bufmgr bufmgr = bo->bufmgr;
275 if (TBM_LOCK_CTRL_BACKEND_VALID(bufmgr->backend->flags))
277 if (bufmgr->backend->bo_lock2)
279 /* use bo_lock2 backend lock */
280 ret = bufmgr->backend->bo_lock2 (bo, device, opt);
282 else if (bufmgr->backend->bo_lock)
284 /* use bo_lock backend lock */
285 ret = bufmgr->backend->bo_lock (bo);
288 TBM_LOG ("[libtbm:%d] "
289 "error %s:%d no backend lock functions\n",
290 getpid(), __FUNCTION__, __LINE__);
294 /* use tizen global lock */
295 ret = _tgl_lock (bufmgr->lock_fd, bo->tgl_key);
302 _bo_unlock (tbm_bo bo)
304 tbm_bufmgr bufmgr = bo->bufmgr;
306 if (TBM_LOCK_CTRL_BACKEND_VALID(bufmgr->backend->flags))
308 if (bufmgr->backend->bo_unlock)
310 /* use backend unlock */
311 bufmgr->backend->bo_unlock (bo);
314 TBM_LOG ("[libtbm:%d] "
315 "error %s:%d no backend unlock functions\n",
316 getpid(), __FUNCTION__, __LINE__);
320 /* use tizen global unlock */
321 _tgl_unlock (bufmgr->lock_fd, bo->tgl_key);
326 _tbm_bo_init_state (tbm_bo bo, int opt)
328 tbm_bufmgr bufmgr = bo->bufmgr;
329 tbm_bo_cache_state cache_state;
331 if (bo->tgl_key == INITIAL_KEY)
332 bo->tgl_key = bufmgr->backend->bo_get_global_key (bo);
334 if (!bo->default_handle.u32)
335 bo->default_handle = bufmgr->backend->bo_get_handle (bo, TBM_DEVICE_DEFAULT);
337 RETURN_VAL_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
342 case CACHE_OP_CREATE: /*Create*/
344 _tgl_init (bufmgr->lock_fd, bo->tgl_key);
346 cache_state.data.isCacheable = BO_IS_CACHEABLE(bo);
347 cache_state.data.isDirtied = DEVICE_NONE;
348 cache_state.data.isCached = 0;
349 cache_state.data.cntFlush = 0;
351 _tgl_set_data (bufmgr->lock_fd, bo->tgl_key, cache_state.val);
353 case CACHE_OP_IMPORT: /*Import*/
355 _tgl_init (bufmgr->lock_fd, bo->tgl_key);
365 _tbm_bo_destroy_state (tbm_bo bo)
367 tbm_bufmgr bufmgr = bo->bufmgr;
369 RETURN_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags));
371 _tgl_destroy (bufmgr->lock_fd, bo->tgl_key);
375 _tbm_bo_set_state (tbm_bo bo, int device, int opt)
377 tbm_bufmgr bufmgr = bo->bufmgr;
379 unsigned short cntFlush = 0;
380 unsigned int is_locked;
382 RETURN_VAL_CHECK_FLAG (TBM_CACHE_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
384 /* get cache state of a bo */
385 bo->cache_state.val = _tgl_get_data (bufmgr->lock_fd, bo->tgl_key, &is_locked);
387 if (!bo->cache_state.data.isCacheable)
390 /* get global cache flush count */
391 cntFlush = (unsigned short)_tgl_get_data (bufmgr->lock_fd, GLOBAL_KEY, NULL);
393 if (DEVICE_IS_CACHE_AWARE (device))
395 if (bo->cache_state.data.isDirtied == DEVICE_CO &&
396 bo->cache_state.data.isCached)
398 need_flush = TBM_CACHE_INV;
401 bo->cache_state.data.isCached = 1;
402 if (opt & TBM_OPTION_WRITE)
403 bo->cache_state.data.isDirtied = DEVICE_CA;
406 if( bo->cache_state.data.isDirtied != DEVICE_CA )
407 bo->cache_state.data.isDirtied = DEVICE_NONE;
412 if (bo->cache_state.data.isDirtied == DEVICE_CA &&
413 bo->cache_state.data.isCached &&
414 bo->cache_state.data.cntFlush == cntFlush)
416 need_flush = TBM_CACHE_CLN | TBM_CACHE_ALL;
419 if (opt & TBM_OPTION_WRITE)
420 bo->cache_state.data.isDirtied = DEVICE_CO;
423 if( bo->cache_state.data.isDirtied != DEVICE_CO )
424 bo->cache_state.data.isDirtied = DEVICE_NONE;
430 /* set global cache flush count */
431 if (need_flush & TBM_CACHE_ALL)
432 _tgl_set_data (bufmgr->lock_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
434 /* call backend cache flush */
435 bufmgr->backend->bo_cache_flush (bo, need_flush);
437 DBG ("[libtbm:%d] \tcache(%d,%d,%d)....flush:0x%x, cntFlush(%d)\n", getpid(),
438 bo->cache_state.data.isCacheable,
439 bo->cache_state.data.isCached,
440 bo->cache_state.data.isDirtied,
441 need_flush, cntFlush);
448 _tbm_bo_save_state (tbm_bo bo)
450 tbm_bufmgr bufmgr = bo->bufmgr;
451 unsigned short cntFlush = 0;
453 RETURN_CHECK_FLAG (TBM_CACHE_CTRL_BACKEND_VALID(bufmgr->backend->flags));
455 /* get global cache flush count */
456 cntFlush = (unsigned short)_tgl_get_data (bufmgr->lock_fd, GLOBAL_KEY, NULL);
458 /* save global cache flush count */
459 bo->cache_state.data.cntFlush = cntFlush;
460 _tgl_set_data(bufmgr->lock_fd, bo->tgl_key, bo->cache_state.val);
465 _tbm_bo_lock (tbm_bo bo, int device, int opt)
467 tbm_bufmgr bufmgr = NULL;
476 /* do not try to lock the bo */
477 if (bufmgr->lock_type == LOCK_TRY_NEVER)
480 if (bo->lock_cnt < 0)
482 TBM_LOG ("[libtbm:%d] "
483 "error %s:%d bo:%p(%d) LOCK_CNT=%d\n",
484 getpid(), __FUNCTION__, __LINE__, bo, bo->tgl_key, bo->lock_cnt);
488 if (bufmgr->lock_type == LOCK_TRY_ONCE)
490 if (bo->lock_cnt == 0)
492 pthread_mutex_unlock (&bufmgr->lock);
493 ret = _bo_lock (bo, device, opt);
494 pthread_mutex_lock (&bufmgr->lock);
501 else if (bufmgr->lock_type == LOCK_TRY_ALWAYS)
503 pthread_mutex_unlock (&bufmgr->lock);
504 ret = _bo_lock (bo, device, opt);
505 pthread_mutex_lock (&bufmgr->lock);
510 TBM_LOG ("[libtbm:%d] "
511 "error %s:%d bo:%p lock_type is wrong.\n",
512 getpid(), __FUNCTION__, __LINE__, bo);
514 DBG_LOCK ("[libtbm:%d] >> LOCK bo:%p(%d, %d->%d)\n", getpid(),
515 bo, bo->tgl_key, old, bo->lock_cnt);
521 _tbm_bo_unlock (tbm_bo bo)
523 tbm_bufmgr bufmgr = NULL;
532 /* do not try to unlock the bo */
533 if (bufmgr->lock_type == LOCK_TRY_NEVER)
537 if (bufmgr->lock_type == LOCK_TRY_ONCE)
539 if (bo->lock_cnt > 0)
542 if (bo->lock_cnt == 0)
546 else if (bufmgr->lock_type == LOCK_TRY_ALWAYS)
548 if (bo->lock_cnt > 0)
555 TBM_LOG ("[libtbm:%d] "
556 "error %s:%d bo:%p lock_type is wrong.\n",
557 getpid(), __FUNCTION__, __LINE__, bo);
559 if (bo->lock_cnt < 0)
562 DBG_LOCK ("[libtbm:%d] << unlock bo:%p(%d, %d->%d)\n", getpid(),
563 bo, bo->tgl_key, old, bo->lock_cnt);
567 _tbm_bo_is_valid(tbm_bo bo)
569 tbm_bo old_data=NULL, tmp = NULL;;
574 if(!LIST_IS_EMPTY (&gBufMgr->bo_list))
576 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, &gBufMgr->bo_list, item_link)
589 _tbm_bo_ref (tbm_bo bo)
595 _tbm_bo_unref (tbm_bo bo)
597 tbm_bufmgr bufmgr = bo->bufmgr;
598 tbm_user_data *old_data = NULL, *tmp = NULL;
600 if (bo->ref_cnt <= 0)
604 if (bo->ref_cnt == 0)
606 /* destory the user_data_list */
607 if (!LIST_IS_EMPTY (&bo->user_data_list))
609 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, &bo->user_data_list, item_link)
611 DBG ("[libtbm:%d] free user_data \n", getpid());
612 _user_data_delete (old_data);
616 if (bo->lock_cnt > 0)
618 TBM_LOG ("[libtbm:%d] "
619 "error %s:%d lock_cnt:%d\n",
620 getpid(), __FUNCTION__, __LINE__, bo->lock_cnt);
624 /* Destroy Global Lock */
625 _tbm_bo_destroy_state (bo);
627 /* call the bo_free */
628 bufmgr->backend->bo_free (bo);
631 LIST_DEL (&bo->item_link);
639 _tbm_bufmgr_init_state (tbm_bufmgr bufmgr)
641 RETURN_VAL_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
643 bufmgr->lock_fd = open (tgl_devfile, O_RDWR);
645 if(bufmgr->lock_fd < 0)
647 bufmgr->lock_fd = open (tgl_devfile1, O_RDWR);
648 if(bufmgr->lock_fd < 0)
651 TBM_LOG ("[libtbm:%d] "
652 "error: Fail to open global_lock:%s\n",
653 getpid(), tgl_devfile);
658 if (!_tgl_init(bufmgr->lock_fd, GLOBAL_KEY))
660 TBM_LOG ("[libtbm:%d] "
661 "error: Fail to initialize the tgl\n",
670 _tbm_bufmgr_destroy_state (tbm_bufmgr bufmgr)
672 RETURN_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags));
674 close (bufmgr->lock_fd);
678 _check_version (TBMModuleVersionInfo *data)
683 abimaj = GET_ABI_MAJOR (data->abiversion);
684 abimin = GET_ABI_MINOR (data->abiversion);
687 "TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
688 getpid(), data->modname ? data->modname : "UNKNOWN!",
689 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
691 vermaj = GET_ABI_MAJOR (TBM_ABI_VERSION);
692 vermin = GET_ABI_MINOR (TBM_ABI_VERSION);
694 DBG ("[libtbm:%d] " "TBM ABI version %d.%d\n", getpid(), vermaj, vermin);
696 if (abimaj != vermaj)
698 TBM_LOG ("[libtbm:%d] "
699 "TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
700 getpid(), abimaj, vermaj);
703 else if (abimin > vermin)
705 TBM_LOG ("[libtbm:%d] "
706 "TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
707 getpid(), abimin, vermin);
714 _tbm_bufmgr_load_module (tbm_bufmgr bufmgr, int fd, const char *file)
716 char path[PATH_MAX] = {0,};
717 TBMModuleData *initdata = NULL;
720 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
722 module_data = dlopen (path, RTLD_LAZY);
725 TBM_LOG ("[libtbm:%d] "
726 "failed to load module: %s(%s)\n",
727 getpid(), dlerror(), file);
731 initdata = dlsym (module_data, "tbmModuleData");
735 TBMModuleVersionInfo *vers;
737 vers = initdata->vers;
738 init = initdata->init;
742 if (!_check_version (vers))
744 dlclose (module_data);
750 TBM_LOG ("[libtbm:%d] "
751 "Error: module does not supply version information.\n",
754 dlclose (module_data);
760 if(!init (bufmgr, fd))
762 TBM_LOG ("[libtbm:%d] "
763 "Fail to init module(%s)\n",
765 dlclose (module_data);
769 if (!bufmgr->backend || !bufmgr->backend->priv)
771 TBM_LOG ("[libtbm:%d] "
772 "Error: module(%s) wrong operation. Check backend or backend's priv.\n",
774 dlclose (module_data);
780 TBM_LOG ("[libtbm:%d] "
781 "Error: module does not supply init symbol.\n", getpid());
782 dlclose (module_data);
788 TBM_LOG ("[libtbm:%d] "
789 "Error: module does not have data object.\n", getpid());
790 dlclose (module_data);
794 bufmgr->module_data = module_data;
797 "Success to load module(%s)\n", getpid(), file);
802 static int _tbm_load_module (tbm_bufmgr bufmgr, int fd)
804 struct dirent **namelist;
805 const char *p = NULL;
809 /* load bufmgr priv from default lib */
810 ret = _tbm_bufmgr_load_module (bufmgr, fd, DEFAULT_LIB);
812 /* load bufmgr priv from configured path */
815 n = scandir (BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
817 TBM_LOG ("[libtbm:%d] "
818 "no files : %s\n", getpid(), BUFMGR_MODULE_DIR);
823 if (!ret && strstr (namelist[n]->d_name, PREFIX_LIB))
825 p = strstr (namelist[n]->d_name, SUFFIX_LIB);
828 if (!strcmp (p, SUFFIX_LIB))
830 ret = _tbm_bufmgr_load_module (bufmgr, fd, namelist[n]->d_name);
844 tbm_bufmgr_init (int fd)
848 int backend_flag = 0;
850 pthread_mutex_lock (&gLock);
853 env = getenv("GEM_DEBUG");
857 TBM_LOG ("GEM_DEBUG=%s\n", env);
863 /* initialize buffer manager */
866 DBG ("[libtbm:%d] use previous gBufMgr\n", getpid());
867 gBufMgr->ref_count++;
871 if (dup2(gBufMgr->fd, fd) < 0) {
872 _tbm_set_last_result (TBM_BO_ERROR_DUP_FD_FAILED);
873 DBG ("[libtbm:%d] Fail to duplicate(dup2) the drm fd\n", getpid());
874 pthread_mutex_unlock (&gLock);
877 DBG ("[libtbm:%d] duplicate the drm_fd(%d), new drm_fd(%d).\n",
878 getpid(), gBufMgr->fd, fd);
881 DBG ("[libtbm:%d] bufmgr ref: fd=%d, ref_count:%d\n",
882 getpid(), gBufMgr->fd, gBufMgr->ref_count);
883 pthread_mutex_unlock (&gLock);
890 fd = tbm_bufmgr_get_drm_fd_x11();
892 fd = tbm_bufmgr_get_drm_fd_wayland();
896 _tbm_set_last_result (TBM_BO_ERROR_GET_FD_FAILED);
897 TBM_LOG ("[libtbm:%d] Fail get drm fd\n", getpid());
898 pthread_mutex_unlock (&gLock);
904 DBG ("[libtbm:%d] bufmgr init: fd=%d\n", getpid(), fd);
906 /* allocate bufmgr */
907 gBufMgr = calloc (1, sizeof(struct _tbm_bufmgr));
910 _tbm_set_last_result (TBM_BO_ERROR_HEAP_ALLOC_FAILED);
914 pthread_mutex_unlock (&gLock);
918 gBufMgr->fd_flag = fd_flag;
926 gBufMgr->fd = dup(fd);
929 _tbm_set_last_result (TBM_BO_ERROR_DUP_FD_FAILED);
930 TBM_LOG ("[libtbm:%d] Fail to duplicate(dup) the drm fd\n", getpid());
933 pthread_mutex_unlock (&gLock);
936 DBG ("[libtbm:%d] duplicate the drm_fd(%d), bufmgr use fd(%d).\n",
937 getpid(), fd, gBufMgr->fd);
940 /* load bufmgr priv from env */
941 if (!_tbm_load_module(gBufMgr, gBufMgr->fd))
943 _tbm_set_last_result (TBM_BO_ERROR_LOAD_MODULE_FAILED);
944 TBM_LOG ("[libtbm:%d] "
945 "error : Fail to load bufmgr backend\n",
950 pthread_mutex_unlock (&gLock);
955 backend_flag = gBufMgr->backend->flags;
956 /* log for tbm backend_flag */
957 DBG ("[libtbm:%d] ", getpid());
959 if (backend_flag&TBM_CACHE_CTRL_BACKEND) {
965 if (backend_flag&TBM_LOCK_CTRL_BACKEND) {
973 gBufMgr->ref_count = 1;
975 DBG ("[libtbm:%d] create tizen bufmgr: ref_count:%d\n", getpid(), gBufMgr->ref_count);
977 if (pthread_mutex_init (&gBufMgr->lock, NULL) != 0)
979 _tbm_set_last_result (TBM_BO_ERROR_THREAD_INIT_FAILED);
980 gBufMgr->backend->bufmgr_deinit (gBufMgr->backend->priv);
981 tbm_backend_free (gBufMgr->backend);
982 dlclose (gBufMgr->module_data);
986 pthread_mutex_unlock (&gLock);
990 /* intialize the tizen global status */
991 if (!_tbm_bufmgr_init_state (gBufMgr))
993 _tbm_set_last_result (TBM_BO_ERROR_INIT_STATE_FAILED);
994 TBM_LOG ("[libtbm:%d] "
995 "error: Fail to init state\n",
997 gBufMgr->backend->bufmgr_deinit (gBufMgr->backend->priv);
998 tbm_backend_free (gBufMgr->backend);
999 pthread_mutex_destroy (&gBufMgr->lock);
1000 dlclose (gBufMgr->module_data);
1001 close (gBufMgr->fd);
1004 pthread_mutex_unlock (&gLock);
1008 /* setup the lock_type */
1009 env = getenv ("BUFMGR_LOCK_TYPE");
1010 if (env && !strcmp (env, "always"))
1011 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
1012 else if(env && !strcmp(env, "none"))
1013 gBufMgr->lock_type = LOCK_TRY_NEVER;
1014 else if(env && !strcmp(env, "once"))
1015 gBufMgr->lock_type = LOCK_TRY_ONCE;
1017 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
1019 DBG ("[libtbm:%d] BUFMGR_LOCK_TYPE=%s\n", getpid(), env?env:"default:once");
1021 /* setup the map_cache */
1022 env = getenv ("BUFMGR_MAP_CACHE");
1023 if (env && !strcmp (env, "false"))
1024 gBufMgr->use_map_cache = 0;
1026 gBufMgr->use_map_cache = 1;
1027 DBG ("[libtbm:%d] BUFMGR_MAP_CACHE=%s\n", getpid(), env?env:"default:true");
1029 /* intialize bo_list */
1030 LIST_INITHEAD (&gBufMgr->bo_list);
1032 /* intialize surf_list */
1033 LIST_INITHEAD (&gBufMgr->surf_list);
1035 pthread_mutex_unlock (&gLock);
1040 tbm_bufmgr_deinit (tbm_bufmgr bufmgr)
1042 TBM_RETURN_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr));
1047 tbm_surface_h surf = NULL;
1048 tbm_surface_h tmp_surf = NULL;
1050 pthread_mutex_lock (&gLock);
1052 bufmgr->ref_count--;
1053 if (bufmgr->ref_count > 0)
1055 TBM_LOG ("[libtbm:%d] "
1056 "tizen bufmgr destroy: bufmgr:%p, ref_count:%d\n",
1057 getpid(), bufmgr, bufmgr->ref_count);
1058 pthread_mutex_unlock (&gLock);
1062 /* destroy bo_list */
1063 if(!LIST_IS_EMPTY (&bufmgr->bo_list))
1065 LIST_FOR_EACH_ENTRY_SAFE (bo, tmp, &bufmgr->bo_list, item_link)
1067 TBM_LOG ("[libtbm:%d] "
1068 "Un-freed bo(%p, ref:%d) \n",
1069 getpid(), bo, bo->ref_cnt);
1075 /* destroy surf_list */
1076 if(!LIST_IS_EMPTY (&bufmgr->surf_list))
1078 LIST_FOR_EACH_ENTRY_SAFE (surf, tmp_surf, &bufmgr->surf_list, item_link)
1080 TBM_LOG ("[libtbm:%d] "
1081 "Destroy surf(%p) \n",
1083 tbm_surface_destroy(surf);
1087 /* destroy the tizen global status */
1088 _tbm_bufmgr_destroy_state (bufmgr);
1090 /* destroy bufmgr priv */
1091 bufmgr->backend->bufmgr_deinit (bufmgr->backend->priv);
1092 bufmgr->backend->priv = NULL;
1093 tbm_backend_free (bufmgr->backend);
1094 bufmgr->backend = NULL;
1096 pthread_mutex_destroy (&bufmgr->lock);
1099 "tizen bufmgr destroy: bufmgr:%p\n",
1102 dlclose (bufmgr->module_data);
1110 pthread_mutex_unlock (&gLock);
1114 tbm_bo_size (tbm_bo bo)
1116 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), 0);
1118 tbm_bufmgr bufmgr = bo->bufmgr;
1121 pthread_mutex_lock(&bufmgr->lock);
1123 size = bufmgr->backend->bo_size(bo);
1125 pthread_mutex_unlock(&bufmgr->lock);
1131 tbm_bo_ref (tbm_bo bo)
1133 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
1135 tbm_bufmgr bufmgr = bo->bufmgr;
1137 pthread_mutex_lock(&bufmgr->lock);
1141 pthread_mutex_unlock(&bufmgr->lock);
1147 tbm_bo_unref (tbm_bo bo)
1149 TBM_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
1151 tbm_bufmgr bufmgr = bo->bufmgr;
1153 pthread_mutex_lock (&bufmgr->lock);
1157 pthread_mutex_unlock(&bufmgr->lock);
1161 tbm_bo_alloc (tbm_bufmgr bufmgr, int size, int flags)
1163 TBM_RETURN_VAL_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
1166 void * bo_priv = NULL;
1168 bo = calloc (1, sizeof(struct _tbm_bo));
1171 _tbm_set_last_result (TBM_BO_ERROR_HEAP_ALLOC_FAILED);
1175 bo->bufmgr = bufmgr;
1177 pthread_mutex_lock (&bufmgr->lock);
1179 bo_priv = bufmgr->backend->bo_alloc (bo, size, flags);
1182 _tbm_set_last_result (TBM_BO_ERROR_BO_ALLOC_FAILED);
1184 pthread_mutex_unlock (&bufmgr->lock);
1190 bo->tgl_key = INITIAL_KEY;
1192 bo->default_handle.u32 = 0;
1195 if (!_tbm_bo_init_state (bo, CACHE_OP_CREATE))
1197 _tbm_set_last_result (TBM_BO_ERROR_INIT_STATE_FAILED);
1199 pthread_mutex_unlock (&bufmgr->lock);
1203 LIST_INITHEAD (&bo->user_data_list);
1205 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1207 pthread_mutex_unlock(&bufmgr->lock);
1213 tbm_bo_import (tbm_bufmgr bufmgr, unsigned int key)
1215 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1220 void * bo_priv = NULL;
1222 pthread_mutex_lock (&bufmgr->lock);
1224 /* find bo in list */
1225 if(!LIST_IS_EMPTY (&bufmgr->bo_list))
1227 LIST_FOR_EACH_ENTRY_SAFE (bo2, tmp, &bufmgr->bo_list, item_link)
1229 if (bo2->tgl_key == key)
1232 "find bo(%p, ref:%d key:%d) in list \n",
1233 getpid(), bo2, bo2->ref_cnt, bo2->tgl_key);
1236 pthread_mutex_unlock (&bufmgr->lock);
1242 bo = calloc (1, sizeof(struct _tbm_bo));
1245 pthread_mutex_unlock (&bufmgr->lock);
1249 bo->bufmgr = bufmgr;
1251 bo_priv = bufmgr->backend->bo_import (bo, key);
1254 _tbm_set_last_result (TBM_BO_ERROR_IMPORT_FAILED);
1256 pthread_mutex_unlock (&bufmgr->lock);
1261 bo->tgl_key = INITIAL_KEY;
1263 bo->default_handle.u32 = 0;
1265 if (bufmgr->backend->bo_get_flags)
1266 bo->flags = bufmgr->backend->bo_get_flags (bo);
1268 bo->flags = TBM_BO_DEFAULT;
1271 if (!_tbm_bo_init_state (bo, CACHE_OP_IMPORT))
1273 _tbm_set_last_result (TBM_BO_ERROR_INIT_STATE_FAILED);
1275 pthread_mutex_unlock (&bufmgr->lock);
1279 LIST_INITHEAD (&bo->user_data_list);
1281 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1283 pthread_mutex_unlock (&bufmgr->lock);
1289 tbm_bo_import_fd (tbm_bufmgr bufmgr, tbm_fd fd)
1291 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1296 void * bo_priv = NULL;
1297 tbm_bo_handle default_handle;
1299 pthread_mutex_lock (&bufmgr->lock);
1301 default_handle = bufmgr->backend->fd_to_handle (bufmgr, fd, TBM_DEVICE_DEFAULT);
1303 /* find bo in list */
1304 if(!LIST_IS_EMPTY (&bufmgr->bo_list))
1306 LIST_FOR_EACH_ENTRY_SAFE (bo2, tmp, &bufmgr->bo_list, item_link)
1308 if (bo2->default_handle.u32 == default_handle.u32)
1311 "find bo(%p, ref:%d handle:%d) in list \n",
1312 getpid(), bo2, bo2->ref_cnt, bo2->default_handle.u32);
1315 pthread_mutex_unlock (&bufmgr->lock);
1321 bo = calloc (1, sizeof(struct _tbm_bo));
1324 pthread_mutex_unlock (&bufmgr->lock);
1328 bo->bufmgr = bufmgr;
1330 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1333 _tbm_set_last_result (TBM_BO_ERROR_IMPORT_FD_FAILED);
1335 pthread_mutex_unlock (&bufmgr->lock);
1340 bo->tgl_key = INITIAL_KEY;
1342 bo->default_handle.u32 = 0;
1344 if (bufmgr->backend->bo_get_flags)
1345 bo->flags = bufmgr->backend->bo_get_flags (bo);
1347 bo->flags = TBM_BO_DEFAULT;
1350 if (!_tbm_bo_init_state (bo, CACHE_OP_IMPORT))
1352 _tbm_set_last_result (TBM_BO_ERROR_INIT_STATE_FAILED);
1354 pthread_mutex_unlock (&bufmgr->lock);
1358 LIST_INITHEAD (&bo->user_data_list);
1360 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1362 pthread_mutex_unlock (&bufmgr->lock);
1368 tbm_bo_export (tbm_bo bo)
1370 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), 0);
1375 bufmgr = bo->bufmgr;
1377 pthread_mutex_lock (&bufmgr->lock);
1378 ret = bufmgr->backend->bo_export (bo);
1381 _tbm_set_last_result (TBM_BO_ERROR_EXPORT_FAILED);
1382 pthread_mutex_unlock (&bufmgr->lock);
1385 pthread_mutex_unlock (&bufmgr->lock);
1391 tbm_bo_export_fd (tbm_bo bo)
1393 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), -1);
1398 bufmgr = bo->bufmgr;
1400 pthread_mutex_lock (&bufmgr->lock);
1401 ret = bufmgr->backend->bo_export_fd (bo);
1404 _tbm_set_last_result (TBM_BO_ERROR_EXPORT_FD_FAILED);
1405 pthread_mutex_unlock (&bufmgr->lock);
1408 pthread_mutex_unlock (&bufmgr->lock);
1415 tbm_bo_get_handle (tbm_bo bo, int device)
1417 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), (tbm_bo_handle)0);
1420 tbm_bo_handle bo_handle;
1422 bufmgr = bo->bufmgr;
1424 pthread_mutex_lock (&bufmgr->lock);
1425 bo_handle = bufmgr->backend->bo_get_handle (bo, device);
1426 if (bo_handle.ptr == NULL)
1428 _tbm_set_last_result (TBM_BO_ERROR_GET_HANDLE_FAILED);
1429 pthread_mutex_unlock (&bufmgr->lock);
1430 return (tbm_bo_handle)NULL;
1432 pthread_mutex_unlock (&bufmgr->lock);
1438 tbm_bo_map (tbm_bo bo, int device, int opt)
1440 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), (tbm_bo_handle)0);
1443 tbm_bo_handle bo_handle;
1445 bufmgr = bo->bufmgr;
1447 pthread_mutex_lock (&bufmgr->lock);
1449 bo_handle = bufmgr->backend->bo_get_handle (bo, device);
1451 if (!_tbm_bo_lock (bo, device, opt))
1453 _tbm_set_last_result (TBM_BO_ERROR_LOCK_FAILED);
1454 TBM_LOG ("[libtbm:%d] "
1455 "error %s:%d fail to lock bo:%p)\n",
1456 getpid(), __FUNCTION__, __LINE__, bo);
1457 pthread_mutex_unlock (&bufmgr->lock);
1458 return (tbm_bo_handle)NULL;
1461 bo_handle = bufmgr->backend->bo_map (bo, device, opt);
1462 if (bo_handle.ptr == NULL)
1464 _tbm_set_last_result (TBM_BO_ERROR_MAP_FAILED);
1465 TBM_LOG ("[libtbm:%d] "
1466 "error %s:%d fail to map bo:%p\n",
1467 getpid(), __FUNCTION__, __LINE__, bo);
1470 pthread_mutex_unlock (&bufmgr->lock);
1471 return (tbm_bo_handle)NULL;
1474 if (bufmgr->use_map_cache == 1 && bo->map_cnt == 0)
1475 _tbm_bo_set_state (bo, device, opt);
1477 /* increase the map_count */
1480 pthread_mutex_unlock (&bufmgr->lock);
1486 tbm_bo_unmap (tbm_bo bo)
1488 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), 0);
1493 bufmgr = bo->bufmgr;
1495 pthread_mutex_lock (&bufmgr->lock);
1497 ret = bufmgr->backend->bo_unmap (bo);
1501 _tbm_set_last_result (TBM_BO_ERROR_UNMAP_FAILED);
1502 pthread_mutex_unlock (&bufmgr->lock);
1506 /* decrease the map_count */
1509 if (bo->map_cnt == 0)
1510 _tbm_bo_save_state (bo);
1512 _tbm_bo_unlock (bo);
1514 pthread_mutex_unlock (&bufmgr->lock);
1520 tbm_bo_swap (tbm_bo bo1, tbm_bo bo2)
1522 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo1), 0);
1523 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo2), 0);
1526 unsigned int tmp_key;
1527 tbm_bo_handle tmp_defualt_handle;
1529 pthread_mutex_lock (&bo1->bufmgr->lock);
1531 if (bo1->bufmgr->backend->bo_size (bo1) != bo2->bufmgr->backend->bo_size (bo2))
1533 _tbm_set_last_result (TBM_BO_ERROR_SWAP_FAILED);
1534 pthread_mutex_unlock (&bo1->bufmgr->lock);
1539 tmp_key = bo1->tgl_key;
1540 bo1->tgl_key = bo2->tgl_key;
1541 bo2->tgl_key = tmp_key;
1543 tmp_defualt_handle = bo1->default_handle;
1544 bo1->default_handle = bo2->default_handle;
1545 bo2->default_handle = tmp_defualt_handle;
1548 bo1->priv = bo2->priv;
1551 pthread_mutex_unlock (&bo1->bufmgr->lock);
1557 tbm_bo_locked (tbm_bo bo)
1559 TBM_RETURN_VAL_IF_FAIL (_tbm_bo_is_valid(bo), 0);
1563 bufmgr = bo->bufmgr;
1565 if (bufmgr->lock_type == LOCK_TRY_NEVER)
1568 pthread_mutex_lock (&bufmgr->lock);
1570 if (bo->lock_cnt > 0)
1572 pthread_mutex_unlock (&bufmgr->lock);
1576 pthread_mutex_unlock (&bufmgr->lock);
1583 tbm_bo_add_user_data (tbm_bo bo, unsigned long key, tbm_data_free data_free_func)
1585 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1587 tbm_user_data *data;
1589 /* check if the data according to the key exist if so, return false.*/
1590 data = _user_data_lookup (&bo->user_data_list, key);
1593 TBM_LOG ("[libtbm:%d] "
1594 "waring: %s:%d user data already exist. key:%ld\n",
1595 getpid(), __FUNCTION__, __LINE__, key);
1599 data = _user_data_create (key, data_free_func);
1603 LIST_ADD (&data->item_link, &bo->user_data_list);
1609 tbm_bo_set_user_data (tbm_bo bo, unsigned long key, void* data)
1611 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1613 tbm_user_data *old_data;
1615 if (LIST_IS_EMPTY (&bo->user_data_list))
1618 old_data = _user_data_lookup (&bo->user_data_list, key);
1622 if (old_data->data && old_data->free_func)
1623 old_data->free_func(old_data->data);
1625 old_data->data = data;
1631 tbm_bo_get_user_data (tbm_bo bo, unsigned long key, void** data)
1633 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1635 tbm_user_data* old_data;
1637 if (!data || LIST_IS_EMPTY (&bo->user_data_list))
1640 old_data = _user_data_lookup (&bo->user_data_list, key);
1647 *data = old_data->data;
1653 tbm_bo_delete_user_data (tbm_bo bo, unsigned long key)
1655 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1657 tbm_user_data *old_data = (void *)0;
1659 if (LIST_IS_EMPTY (&bo->user_data_list))
1662 old_data = _user_data_lookup (&bo->user_data_list, key);
1666 _user_data_delete (old_data);
1672 tbm_get_last_error (void)
1674 return tbm_last_error;
1678 tbm_bufmgr_get_capability (tbm_bufmgr bufmgr)
1680 TBM_RETURN_VAL_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr), 0);
1682 unsigned int capability = TBM_BUFMGR_CAPABILITY_NONE;
1684 if (bufmgr->backend->bo_import && bufmgr->backend->bo_export)
1685 capability |= TBM_BUFMGR_CAPABILITY_SHARE_KEY;
1687 if (bufmgr->backend->bo_import_fd && bufmgr->backend->bo_export_fd)
1688 capability |= TBM_BUFMGR_CAPABILITY_SHARE_FD;
1694 tbm_bo_get_flags (tbm_bo bo)
1696 TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);