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);
556 _tbm_bo_ref (tbm_bo bo)
562 _tbm_bo_unref (tbm_bo bo)
564 tbm_bufmgr bufmgr = bo->bufmgr;
565 tbm_user_data *old_data = NULL, *tmp = NULL;
567 if (bo->ref_cnt <= 0)
571 if (bo->ref_cnt == 0)
573 /* destory the user_data_list */
574 if (!LIST_IS_EMPTY (&bo->user_data_list))
576 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, &bo->user_data_list, item_link)
578 DBG ("[libtbm:%d] free user_data \n", getpid());
579 _user_data_delete (old_data);
583 if (bo->lock_cnt > 0)
585 TBM_LOG ("[libtbm:%d] "
586 "error %s:%d lock_cnt:%d\n",
587 getpid(), __FUNCTION__, __LINE__, bo->lock_cnt);
591 /* Destroy Global Lock */
592 _tbm_bo_destroy_state (bo);
594 /* call the bo_free */
595 bufmgr->backend->bo_free (bo);
598 LIST_DEL (&bo->item_link);
606 _tbm_bufmgr_init_state (tbm_bufmgr bufmgr)
608 RETURN_VAL_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
610 bufmgr->lock_fd = open (tgl_devfile, O_RDWR);
612 if(bufmgr->lock_fd < 0)
614 bufmgr->lock_fd = open (tgl_devfile1, O_RDWR);
615 if(bufmgr->lock_fd < 0)
618 TBM_LOG ("[libtbm:%d] "
619 "error: Fail to open global_lock:%s\n",
620 getpid(), tgl_devfile);
625 if (!_tgl_init(bufmgr->lock_fd, GLOBAL_KEY))
627 TBM_LOG ("[libtbm:%d] "
628 "error: Fail to initialize the tgl\n",
637 _tbm_bufmgr_destroy_state (tbm_bufmgr bufmgr)
639 RETURN_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags));
641 close (bufmgr->lock_fd);
645 _check_version (TBMModuleVersionInfo *data)
650 abimaj = GET_ABI_MAJOR (data->abiversion);
651 abimin = GET_ABI_MINOR (data->abiversion);
653 TBM_LOG ("[libtbm:%d] "
654 "TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
655 getpid(), data->modname ? data->modname : "UNKNOWN!",
656 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
658 vermaj = GET_ABI_MAJOR (TBM_ABI_VERSION);
659 vermin = GET_ABI_MINOR (TBM_ABI_VERSION);
661 DBG ("[libtbm:%d] " "TBM ABI version %d.%d\n", getpid(), vermaj, vermin);
663 if (abimaj != vermaj)
665 TBM_LOG ("[libtbm:%d] "
666 "TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
667 getpid(), abimaj, vermaj);
670 else if (abimin > vermin)
672 TBM_LOG ("[libtbm:%d] "
673 "TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
674 getpid(), abimin, vermin);
681 _tbm_bufmgr_load_module (tbm_bufmgr bufmgr, int fd, const char *file)
683 char path[PATH_MAX] = {0,};
684 TBMModuleData *initdata = NULL;
687 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
689 module_data = dlopen (path, RTLD_LAZY);
692 TBM_LOG ("[libtbm:%d] "
693 "failed to load module: %s(%s)\n",
694 getpid(), dlerror(), file);
698 initdata = dlsym (module_data, "tbmModuleData");
702 TBMModuleVersionInfo *vers;
704 vers = initdata->vers;
705 init = initdata->init;
709 if (!_check_version (vers))
711 dlclose (module_data);
717 TBM_LOG ("[libtbm:%d] "
718 "Error: module does not supply version information.\n",
721 dlclose (module_data);
727 if(!init (bufmgr, fd))
729 TBM_LOG ("[libtbm:%d] "
730 "Fail to init module(%s)\n",
732 dlclose (module_data);
736 if (!bufmgr->backend || !bufmgr->backend->priv)
738 TBM_LOG ("[libtbm:%d] "
739 "Error: module(%s) wrong operation. Check backend or backend's priv.\n",
741 dlclose (module_data);
747 TBM_LOG ("[libtbm:%d] "
748 "Error: module does not supply init symbol.\n", getpid());
749 dlclose (module_data);
755 TBM_LOG ("[libtbm:%d] "
756 "Error: module does not have data object.\n", getpid());
757 dlclose (module_data);
761 bufmgr->module_data = module_data;
763 TBM_LOG ("[libtbm:%d] "
764 "Success to load module(%s)\n", getpid(), file);
769 static int _tbm_load_module (tbm_bufmgr bufmgr, int fd)
771 struct dirent **namelist;
772 const char *p = NULL;
776 /* load bufmgr priv from default lib */
777 ret = _tbm_bufmgr_load_module (bufmgr, fd, DEFAULT_LIB);
779 /* load bufmgr priv from configured path */
782 n = scandir (BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
784 TBM_LOG ("[libtbm:%d] "
785 "no files : %s\n", getpid(), BUFMGR_MODULE_DIR);
790 if (!ret && strstr (namelist[n]->d_name, PREFIX_LIB))
792 p = strstr (namelist[n]->d_name, SUFFIX_LIB);
795 if (!strcmp (p, SUFFIX_LIB))
797 ret = _tbm_bufmgr_load_module (bufmgr, fd, namelist[n]->d_name);
811 tbm_bufmgr_init (int fd)
816 pthread_mutex_lock (&gLock);
819 env = getenv("GEM_DEBUG");
823 TBM_LOG ("GEM_DEBUG=%s\n", env);
829 /* initialize buffer manager */
832 TBM_LOG ("[libtbm:%d] use previous gBufMgr\n", getpid());
833 gBufMgr->ref_count++;
834 TBM_LOG ("[libtbm:%d] bufmgr ref: fd=%d, ref_count:%d\n",
835 getpid(), gBufMgr->fd, gBufMgr->ref_count);
836 pthread_mutex_unlock (&gLock);
843 fd = tbm_bufmgr_get_drm_fd_x11();
845 fd = tbm_bufmgr_get_drm_fd_wayland();
849 TBM_LOG ("[libtbm:%d] Fail get drm fd\n", getpid());
850 pthread_mutex_unlock (&gLock);
856 TBM_LOG ("[libtbm:%d] bufmgr init: fd=%d\n", getpid(), fd);
858 /* allocate bufmgr */
859 gBufMgr = calloc (1, sizeof(struct _tbm_bufmgr));
862 pthread_mutex_unlock (&gLock);
866 /* load bufmgr priv from env */
867 if (!_tbm_load_module(gBufMgr, fd))
869 TBM_LOG ("[libtbm:%d] "
870 "error : Fail to load bufmgr backend\n",
874 pthread_mutex_unlock (&gLock);
878 gBufMgr->fd_flag = fd_flag;
880 gBufMgr->ref_count = 1;
882 TBM_LOG ("[libtbm:%d] create tizen bufmgr: ref_count:%d\n", getpid(), gBufMgr->ref_count);
884 if (pthread_mutex_init (&gBufMgr->lock, NULL) != 0)
886 gBufMgr->backend->bufmgr_deinit (gBufMgr->backend->priv);
887 tbm_backend_free (gBufMgr->backend);
888 dlclose (gBufMgr->module_data);
891 pthread_mutex_unlock (&gLock);
895 /* intialize the tizen global status */
896 if (!_tbm_bufmgr_init_state (gBufMgr))
898 TBM_LOG ("[libtbm:%d] "
899 "error: Fail to init state\n",
901 gBufMgr->backend->bufmgr_deinit (gBufMgr->backend->priv);
902 tbm_backend_free (gBufMgr->backend);
903 pthread_mutex_destroy (&gBufMgr->lock);
904 dlclose (gBufMgr->module_data);
907 pthread_mutex_unlock (&gLock);
911 /* setup the lock_type */
912 env = getenv ("BUFMGR_LOCK_TYPE");
913 if (env && !strcmp (env, "always"))
914 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
915 else if(env && !strcmp(env, "none"))
916 gBufMgr->lock_type = LOCK_TRY_NEVER;
917 else if(env && !strcmp(env, "once"))
918 gBufMgr->lock_type = LOCK_TRY_ONCE;
920 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
922 DBG ("[libtbm:%d] BUFMGR_LOCK_TYPE=%s\n", getpid(), env?env:"default:once");
924 /* setup the map_cache */
925 env = getenv ("BUFMGR_MAP_CACHE");
926 if (env && !strcmp (env, "false"))
927 gBufMgr->use_map_cache = 0;
929 gBufMgr->use_map_cache = 1;
930 DBG ("[libtbm:%d] BUFMGR_MAP_CACHE=%s\n", getpid(), env?env:"default:true");
932 /* intialize bo_list */
933 LIST_INITHEAD (&gBufMgr->bo_list);
935 /* intialize surf_list */
936 LIST_INITHEAD (&gBufMgr->surf_list);
938 pthread_mutex_unlock (&gLock);
943 tbm_bufmgr_deinit (tbm_bufmgr bufmgr)
945 TBM_RETURN_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr));
950 tbm_surface_h surf = NULL;
951 tbm_surface_h tmp_surf = NULL;
953 pthread_mutex_lock (&gLock);
956 if (bufmgr->ref_count > 0)
958 TBM_LOG ("[libtbm:%d] "
959 "tizen bufmgr destroy: bufmgr:%p, ref_count:%d\n",
960 getpid(), bufmgr, bufmgr->ref_count);
961 pthread_mutex_unlock (&gLock);
965 /* destroy bo_list */
966 if(!LIST_IS_EMPTY (&bufmgr->bo_list))
968 LIST_FOR_EACH_ENTRY_SAFE (bo, tmp, &bufmgr->bo_list, item_link)
970 TBM_LOG ("[libtbm:%d] "
971 "Un-freed bo(%p, ref:%d) \n",
972 getpid(), bo, bo->ref_cnt);
978 /* destroy surf_list */
979 if(!LIST_IS_EMPTY (&bufmgr->surf_list))
981 LIST_FOR_EACH_ENTRY_SAFE (surf, tmp_surf, &bufmgr->surf_list, item_link)
983 TBM_LOG ("[libtbm:%d] "
984 "Destroy surf(%p) \n",
986 tbm_surface_destroy(surf);
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\n",
1005 dlclose (bufmgr->module_data);
1014 pthread_mutex_unlock (&gLock);
1018 tbm_bo_size (tbm_bo bo)
1020 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1022 tbm_bufmgr bufmgr = bo->bufmgr;
1025 pthread_mutex_lock(&bufmgr->lock);
1027 size = bufmgr->backend->bo_size(bo);
1029 pthread_mutex_unlock(&bufmgr->lock);
1035 tbm_bo_ref (tbm_bo bo)
1037 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), NULL);
1039 tbm_bufmgr bufmgr = bo->bufmgr;
1041 pthread_mutex_lock(&bufmgr->lock);
1045 pthread_mutex_unlock(&bufmgr->lock);
1051 tbm_bo_unref (tbm_bo bo)
1053 TBM_RETURN_IF_FAIL(TBM_BO_IS_VALID(bo));
1055 tbm_bufmgr bufmgr = bo->bufmgr;
1057 pthread_mutex_lock (&bufmgr->lock);
1061 pthread_mutex_unlock(&bufmgr->lock);
1065 tbm_bo_alloc (tbm_bufmgr bufmgr, int size, int flags)
1067 TBM_RETURN_VAL_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
1070 void * bo_priv = NULL;
1072 bo = calloc (1, sizeof(struct _tbm_bo));
1076 bo->bufmgr = bufmgr;
1078 pthread_mutex_lock (&bufmgr->lock);
1080 bo_priv = bufmgr->backend->bo_alloc (bo, size, flags);
1084 pthread_mutex_unlock (&bufmgr->lock);
1090 bo->tgl_key = INITIAL_KEY;
1094 if (!_tbm_bo_init_state (bo, CACHE_OP_CREATE))
1097 pthread_mutex_unlock (&bufmgr->lock);
1101 LIST_INITHEAD (&bo->user_data_list);
1103 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1105 pthread_mutex_unlock(&bufmgr->lock);
1111 tbm_bo_import (tbm_bufmgr bufmgr, unsigned int key)
1113 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1116 void * bo_priv = NULL;
1118 bo = calloc (1, sizeof(struct _tbm_bo));
1122 bo->bufmgr = bufmgr;
1124 pthread_mutex_lock (&bufmgr->lock);
1126 bo_priv = bufmgr->backend->bo_import (bo, key);
1130 pthread_mutex_unlock (&bufmgr->lock);
1135 bo->tgl_key = INITIAL_KEY;
1139 if (!_tbm_bo_init_state (bo, CACHE_OP_IMPORT))
1142 pthread_mutex_unlock (&bufmgr->lock);
1146 LIST_INITHEAD (&bo->user_data_list);
1148 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1150 pthread_mutex_unlock (&bufmgr->lock);
1156 tbm_bo_import_fd (tbm_bufmgr bufmgr, tbm_fd fd)
1164 tbm_bo_export (tbm_bo bo)
1166 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1171 bufmgr = bo->bufmgr;
1173 pthread_mutex_lock (&bufmgr->lock);
1174 ret = bufmgr->backend->bo_export (bo);
1175 pthread_mutex_unlock (&bufmgr->lock);
1181 tbm_bo_export_fd (tbm_bo bo)
1190 tbm_bo_get_handle (tbm_bo bo, int device)
1192 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), (tbm_bo_handle)0);
1195 tbm_bo_handle bo_handle;
1197 bufmgr = bo->bufmgr;
1199 pthread_mutex_lock (&bufmgr->lock);
1200 bo_handle = bufmgr->backend->bo_get_handle (bo, device);
1201 pthread_mutex_unlock (&bufmgr->lock);
1207 tbm_bo_map (tbm_bo bo, int device, int opt)
1209 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), (tbm_bo_handle)0);
1212 tbm_bo_handle bo_handle;
1214 bufmgr = bo->bufmgr;
1216 pthread_mutex_lock (&bufmgr->lock);
1218 bo_handle = bufmgr->backend->bo_get_handle (bo, device);
1220 _tbm_bo_lock (bo, device, opt);
1222 bo_handle = bufmgr->backend->bo_map (bo, device, opt);
1224 if (bufmgr->use_map_cache == 1 && bo->map_cnt == 0)
1225 _tbm_bo_set_state (bo, device, opt);
1227 /* increase the map_count */
1230 pthread_mutex_unlock (&bufmgr->lock);
1236 tbm_bo_unmap (tbm_bo bo)
1238 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1243 bufmgr = bo->bufmgr;
1245 pthread_mutex_lock (&bufmgr->lock);
1248 ret = bufmgr->backend->bo_unmap (bo);
1250 /* decrease the map_count */
1253 if (bo->map_cnt == 0)
1254 _tbm_bo_save_state (bo);
1256 _tbm_bo_unlock (bo);
1258 pthread_mutex_unlock (&bufmgr->lock);
1264 tbm_bo_swap (tbm_bo bo1, tbm_bo bo2)
1266 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo1), 0);
1267 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo2), 0);
1270 unsigned int tmp_key;
1272 if (bo1->bufmgr->backend->bo_size (bo1) != bo2->bufmgr->backend->bo_size (bo2))
1275 pthread_mutex_lock (&bo1->bufmgr->lock);
1277 tmp_key = bo1->tgl_key;
1278 bo1->tgl_key = bo2->tgl_key;
1279 bo2->tgl_key = tmp_key;
1282 bo1->priv = bo2->priv;
1285 pthread_mutex_unlock (&bo1->bufmgr->lock);
1291 tbm_bo_locked (tbm_bo bo)
1293 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1297 bufmgr = bo->bufmgr;
1299 if (bufmgr->lock_type == LOCK_TRY_NEVER)
1302 pthread_mutex_lock (&bufmgr->lock);
1304 if (bo->lock_cnt > 0)
1306 pthread_mutex_unlock (&bufmgr->lock);
1310 pthread_mutex_unlock (&bufmgr->lock);
1317 tbm_bo_add_user_data (tbm_bo bo, unsigned long key, tbm_data_free data_free_func)
1319 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1321 tbm_user_data *data;
1323 /* check if the data according to the key exist if so, return false.*/
1324 data = _user_data_lookup (&bo->user_data_list, key);
1327 TBM_LOG ("[libtbm:%d] "
1328 "waring: %s:%d user data already exist. key:%ld\n",
1329 getpid(), __FUNCTION__, __LINE__, key);
1333 data = _user_data_create (key, data_free_func);
1337 LIST_ADD (&data->item_link, &bo->user_data_list);
1343 tbm_bo_set_user_data (tbm_bo bo, unsigned long key, void* data)
1345 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1347 tbm_user_data *old_data;
1349 if (LIST_IS_EMPTY (&bo->user_data_list))
1352 old_data = _user_data_lookup (&bo->user_data_list, key);
1356 if (old_data->data && old_data->free_func)
1357 old_data->free_func(old_data->data);
1359 old_data->data = data;
1365 tbm_bo_get_user_data (tbm_bo bo, unsigned long key, void** data)
1367 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1369 tbm_user_data* old_data;
1371 if (!data || LIST_IS_EMPTY (&bo->user_data_list))
1374 old_data = _user_data_lookup (&bo->user_data_list, key);
1381 *data = old_data->data;
1387 tbm_bo_delete_user_data (tbm_bo bo, unsigned long key)
1389 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1391 tbm_user_data *old_data = (void *)0;
1393 if (LIST_IS_EMPTY (&bo->user_data_list))
1396 old_data = _user_data_lookup (&bo->user_data_list, key);
1400 _user_data_delete (old_data);