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"
46 #define DBG(...) if(bDebug&0x1) TBM_LOG (__VA_ARGS__)
47 #define DBG_LOCK(...) if(bDebug&0x2) TBM_LOG (__VA_ARGS__)
53 #define PREFIX_LIB "libtbm_"
54 #define SUFFIX_LIB ".so"
55 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
57 #define BO_IS_CACHEABLE(bo) ((bo->flags & TBM_BO_NONCACHABLE)?0:1)
58 #define DEVICE_IS_CACHE_AWARE(device) ((device == TBM_DEVICE_CPU)?(1):(0))
61 #define GLOBAL_KEY ((unsigned int)(-1))
62 #define INITIAL_KEY ((unsigned int)(-2))
64 #define CACHE_OP_CREATE (-1)
65 #define CACHE_OP_ATTACH (-2)
66 #define CACHE_OP_IMPORT (-3)
68 /* values to indicate unspecified fields in XF86ModReqInfo. */
69 #define MAJOR_UNSPEC 0xFF
70 #define MINOR_UNSPEC 0xFF
71 #define PATCH_UNSPEC 0xFFFF
72 #define ABI_VERS_UNSPEC 0xFFFFFFFF
74 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
75 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
76 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
77 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
78 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
88 DEVICE_CA, /* cache aware device */
89 DEVICE_CO /* cache oblivious device */
96 tbm_data_free free_func ;
98 /* link of user_data */
99 struct list_head item_link;
102 pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
103 tbm_bufmgr gBufMgr = NULL;
106 _tgl_init (int fd, unsigned int key)
108 struct tgl_attribute attr;
112 attr.timeout_ms = 1000;
114 err = ioctl (fd, TGL_IOC_INIT_LOCK, &attr);
117 TBM_LOG ( "[libtbm:%d] "
118 "error(%s) %s:%d key:%d\n",
119 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
127 _tgl_destroy (int fd, unsigned int key)
130 err = ioctl (fd, TGL_IOC_DESTROY_LOCK, key);
133 TBM_LOG ( "[libtbm:%d] "
134 "error(%s) %s:%d key:%d\n",
135 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
143 _tgl_lock (int fd, unsigned int key)
146 err = ioctl (fd, TGL_IOC_LOCK_LOCK, key);
149 TBM_LOG ("[libtbm:%d] "
150 "error(%s) %s:%d key:%d\n",
151 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
159 _tgl_unlock (int fd, unsigned int key)
162 err = ioctl (fd, TGL_IOC_UNLOCK_LOCK, key);
165 TBM_LOG ("[libtbm:%d] "
166 "error(%s) %s:%d key:%d\n",
167 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
175 _tgl_set_data (int fd, unsigned int key, unsigned int val)
178 struct tgl_user_data arg;
182 err = ioctl (fd, TGL_IOC_SET_DATA, &arg);
185 TBM_LOG ("[libtbm:%d] "
186 "error(%s) %s:%d key:%d\n",
187 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
194 static inline unsigned int
195 _tgl_get_data (int fd, unsigned int key, unsigned int *locked)
198 struct tgl_user_data arg = {0,};
201 err = ioctl (fd, TGL_IOC_GET_DATA, &arg);
204 TBM_LOG ("[libtbm:%d] "
205 "error(%s) %s:%d key:%d\n",
206 getpid(), strerror(errno), __FUNCTION__, __LINE__, key);
211 *locked = arg.locked;
216 static tbm_user_data *
217 _user_data_lookup (struct list_head *user_data_list, unsigned long key)
219 tbm_user_data *user_data = NULL;
220 tbm_user_data *old_data = NULL, *tmp = NULL;
222 if (!LIST_IS_EMPTY (user_data_list))
224 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, user_data_list, item_link)
226 if (old_data->key == key)
228 user_data = old_data;
237 static tbm_user_data *
238 _user_data_create (unsigned long key, tbm_data_free data_free_func)
240 tbm_user_data * user_data = NULL;
242 user_data = calloc (1, sizeof (tbm_user_data));
246 user_data->key = key;
247 user_data->free_func = data_free_func;
248 user_data->data = (void *)0;
254 _user_data_delete (tbm_user_data *user_data)
256 if (user_data->data && user_data->free_func)
257 user_data->free_func(user_data->data);
259 LIST_DEL (&user_data->item_link);
265 _bo_lock (tbm_bo bo, int device, int opt)
267 tbm_bufmgr bufmgr = bo->bufmgr;
270 if (TBM_LOCK_CTRL_BACKEND_VALID(bufmgr->backend->flags))
272 if (bufmgr->backend->bo_lock2)
274 /* use bo_lock2 backend lock */
275 ret = bufmgr->backend->bo_lock2 (bo, device, opt);
277 else if (bufmgr->backend->bo_lock)
279 /* use bo_lock backend lock */
280 ret = bufmgr->backend->bo_lock (bo);
283 TBM_LOG ("[libtbm:%d] "
284 "error %s:%d no backend lock functions\n",
285 getpid(), __FUNCTION__, __LINE__);
289 /* use tizen global lock */
290 ret = _tgl_lock (bufmgr->lock_fd, bo->tgl_key);
297 _bo_unlock (tbm_bo bo)
299 tbm_bufmgr bufmgr = bo->bufmgr;
301 if (TBM_LOCK_CTRL_BACKEND_VALID(bufmgr->backend->flags))
303 if (bufmgr->backend->bo_unlock)
305 /* use backend unlock */
306 bufmgr->backend->bo_unlock (bo);
309 TBM_LOG ("[libtbm:%d] "
310 "error %s:%d no backend unlock functions\n",
311 getpid(), __FUNCTION__, __LINE__);
315 /* use tizen global unlock */
316 _tgl_unlock (bufmgr->lock_fd, bo->tgl_key);
321 _tbm_bo_init_state (tbm_bo bo, int opt)
323 tbm_bufmgr bufmgr = bo->bufmgr;
324 tbm_bo_cache_state cache_state;
326 RETURN_VAL_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
331 case CACHE_OP_CREATE: /*Create*/
332 if (bo->tgl_key == INITIAL_KEY)
333 bo->tgl_key = bufmgr->backend->bo_get_global_key (bo);
335 _tgl_init (bufmgr->lock_fd, bo->tgl_key);
337 cache_state.data.isCacheable = BO_IS_CACHEABLE(bo);
338 cache_state.data.isDirtied = DEVICE_NONE;
339 cache_state.data.isCached = 0;
340 cache_state.data.cntFlush = 0;
342 _tgl_set_data (bufmgr->lock_fd, bo->tgl_key, cache_state.val);
344 case CACHE_OP_IMPORT: /*Import*/
345 if (bo->tgl_key == INITIAL_KEY)
346 bo->tgl_key = bufmgr->backend->bo_get_global_key (bo);
348 _tgl_init (bufmgr->lock_fd, bo->tgl_key);
358 _tbm_bo_destroy_state (tbm_bo bo)
360 tbm_bufmgr bufmgr = bo->bufmgr;
362 RETURN_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags));
364 _tgl_destroy (bufmgr->lock_fd, bo->tgl_key);
368 _tbm_bo_set_state (tbm_bo bo, int device, int opt)
370 tbm_bufmgr bufmgr = bo->bufmgr;
372 unsigned short cntFlush = 0;
373 unsigned int is_locked;
375 RETURN_VAL_CHECK_FLAG (TBM_CACHE_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
377 /* get cache state of a bo */
378 bo->cache_state.val = _tgl_get_data (bufmgr->lock_fd, bo->tgl_key, &is_locked);
380 if (!bo->cache_state.data.isCacheable)
383 /* get global cache flush count */
384 cntFlush = (unsigned short)_tgl_get_data (bufmgr->lock_fd, GLOBAL_KEY, NULL);
386 if (DEVICE_IS_CACHE_AWARE (device))
388 if (bo->cache_state.data.isDirtied == DEVICE_CO &&
389 bo->cache_state.data.isCached)
391 need_flush = TBM_CACHE_INV;
394 bo->cache_state.data.isCached = 1;
395 if (opt & TBM_OPTION_WRITE)
396 bo->cache_state.data.isDirtied = DEVICE_CA;
399 if( bo->cache_state.data.isDirtied != DEVICE_CA )
400 bo->cache_state.data.isDirtied = DEVICE_NONE;
405 if (bo->cache_state.data.isDirtied == DEVICE_CA &&
406 bo->cache_state.data.isCached &&
407 bo->cache_state.data.cntFlush == cntFlush)
409 need_flush = TBM_CACHE_CLN | TBM_CACHE_ALL;
412 if (opt & TBM_OPTION_WRITE)
413 bo->cache_state.data.isDirtied = DEVICE_CO;
416 if( bo->cache_state.data.isDirtied != DEVICE_CO )
417 bo->cache_state.data.isDirtied = DEVICE_NONE;
423 /* set global cache flush count */
424 if (need_flush & TBM_CACHE_ALL)
425 _tgl_set_data (bufmgr->lock_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
427 /* call backend cache flush */
428 bufmgr->backend->bo_cache_flush (bo, need_flush);
430 DBG ("[libtbm:%d] \tcache(%d,%d,%d)....flush:0x%x, cntFlush(%d)\n", getpid(),
431 bo->cache_state.data.isCacheable,
432 bo->cache_state.data.isCached,
433 bo->cache_state.data.isDirtied,
434 need_flush, cntFlush);
441 _tbm_bo_save_state (tbm_bo bo)
443 tbm_bufmgr bufmgr = bo->bufmgr;
444 unsigned short cntFlush = 0;
446 RETURN_CHECK_FLAG (TBM_CACHE_CTRL_BACKEND_VALID(bufmgr->backend->flags));
448 /* get global cache flush count */
449 cntFlush = (unsigned short)_tgl_get_data (bufmgr->lock_fd, GLOBAL_KEY, NULL);
451 /* save global cache flush count */
452 bo->cache_state.data.cntFlush = cntFlush;
453 _tgl_set_data(bufmgr->lock_fd, bo->tgl_key, bo->cache_state.val);
458 _tbm_bo_lock (tbm_bo bo, int device, int opt)
460 tbm_bufmgr bufmgr = NULL;
469 /* do not try to lock the bo */
470 if (bufmgr->lock_type == LOCK_TRY_NEVER)
473 if (bo->lock_cnt < 0)
475 TBM_LOG ("[libtbm:%d] "
476 "error %s:%d bo:%p(%d) LOCK_CNT=%d\n",
477 getpid(), __FUNCTION__, __LINE__, bo, bo->tgl_key, bo->lock_cnt);
481 if (bufmgr->lock_type == LOCK_TRY_ONCE)
483 if (bo->lock_cnt == 0)
485 pthread_mutex_unlock (&bufmgr->lock);
486 ret = _bo_lock (bo, device, opt);
487 pthread_mutex_lock (&bufmgr->lock);
492 else if (bufmgr->lock_type == LOCK_TRY_ALWAYS)
494 pthread_mutex_unlock (&bufmgr->lock);
495 ret = _bo_lock (bo, device, opt);
496 pthread_mutex_lock (&bufmgr->lock);
501 TBM_LOG ("[libtbm:%d] "
502 "error %s:%d bo:%p lock_type is wrong.\n",
503 getpid(), __FUNCTION__, __LINE__, bo);
505 DBG_LOCK ("[libtbm:%d] >> LOCK bo:%p(%d, %d->%d)\n", getpid(),
506 bo, bo->tgl_key, old, bo->lock_cnt);
512 _tbm_bo_unlock (tbm_bo bo)
514 tbm_bufmgr bufmgr = NULL;
523 /* do not try to unlock the bo */
524 if (bufmgr->lock_type == LOCK_TRY_NEVER)
528 if (bufmgr->lock_type == LOCK_TRY_ONCE)
530 if (bo->lock_cnt > 0)
533 if (bo->lock_cnt == 0)
537 else if (bufmgr->lock_type == LOCK_TRY_ALWAYS)
539 if (bo->lock_cnt > 0)
546 TBM_LOG ("[libtbm:%d] "
547 "error %s:%d bo:%p lock_type is wrong.\n",
548 getpid(), __FUNCTION__, __LINE__, bo);
550 if (bo->lock_cnt < 0)
553 DBG_LOCK ("[libtbm:%d] << unlock bo:%p(%d, %d->%d)\n", getpid(),
554 bo, bo->tgl_key, old, bo->lock_cnt);
559 _tbm_bo_ref (tbm_bo bo)
565 _tbm_bo_unref (tbm_bo bo)
567 tbm_bufmgr bufmgr = bo->bufmgr;
568 tbm_user_data *old_data = NULL, *tmp = NULL;
570 if (bo->ref_cnt <= 0)
574 if (bo->ref_cnt == 0)
576 /* destory the user_data_list */
577 if (!LIST_IS_EMPTY (&bo->user_data_list))
579 LIST_FOR_EACH_ENTRY_SAFE (old_data, tmp, &bo->user_data_list, item_link)
581 DBG ("[libtbm:%d] free user_data \n", getpid());
582 _user_data_delete (old_data);
586 if (bo->lock_cnt > 0)
588 TBM_LOG ("[libtbm:%d] "
589 "error %s:%d lock_cnt:%d\n",
590 getpid(), __FUNCTION__, __LINE__, bo->lock_cnt);
594 /* Destroy Global Lock */
595 _tbm_bo_destroy_state (bo);
597 /* call the bo_free */
598 bufmgr->backend->bo_free (bo);
601 LIST_DEL (&bo->item_link);
609 _tbm_bufmgr_init_state (tbm_bufmgr bufmgr)
611 RETURN_VAL_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
613 bufmgr->lock_fd = open (tgl_devfile, O_RDWR);
615 if(bufmgr->lock_fd < 0)
617 bufmgr->lock_fd = open (tgl_devfile1, O_RDWR);
618 if(bufmgr->lock_fd < 0)
621 TBM_LOG ("[libtbm:%d] "
622 "error: Fail to open global_lock:%s\n",
623 getpid(), tgl_devfile);
628 if (!_tgl_init(bufmgr->lock_fd, GLOBAL_KEY))
630 TBM_LOG ("[libtbm:%d] "
631 "error: Fail to initialize the tgl\n",
640 _tbm_bufmgr_destroy_state (tbm_bufmgr bufmgr)
642 RETURN_CHECK_FLAG (TBM_ALL_CTRL_BACKEND_VALID(bufmgr->backend->flags));
644 close (bufmgr->lock_fd);
648 _check_version (TBMModuleVersionInfo *data)
653 abimaj = GET_ABI_MAJOR (data->abiversion);
654 abimin = GET_ABI_MINOR (data->abiversion);
656 TBM_LOG ("[libtbm:%d] "
657 "TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
658 getpid(), data->modname ? data->modname : "UNKNOWN!",
659 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
661 vermaj = GET_ABI_MAJOR (TBM_ABI_VERSION);
662 vermin = GET_ABI_MINOR (TBM_ABI_VERSION);
664 DBG ("[libtbm:%d] " "TBM ABI version %d.%d\n", getpid(), vermaj, vermin);
666 if (abimaj != vermaj)
668 TBM_LOG ("[libtbm:%d] "
669 "TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
670 getpid(), abimaj, vermaj);
673 else if (abimin > vermin)
675 TBM_LOG ("[libtbm:%d] "
676 "TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
677 getpid(), abimin, vermin);
684 _tbm_bufmgr_load_module (tbm_bufmgr bufmgr, int fd, const char *file)
686 char path[PATH_MAX] = {0,};
687 TBMModuleData *initdata = NULL;
690 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
692 module_data = dlopen (path, RTLD_LAZY);
695 TBM_LOG ("[libtbm:%d] "
696 "failed to load module: %s(%s)\n",
697 getpid(), dlerror(), file);
701 initdata = dlsym (module_data, "tbmModuleData");
705 TBMModuleVersionInfo *vers;
707 vers = initdata->vers;
708 init = initdata->init;
712 if (!_check_version (vers))
714 dlclose (module_data);
720 TBM_LOG ("[libtbm:%d] "
721 "Error: module does not supply version information.\n",
724 dlclose (module_data);
730 if(!init (bufmgr, fd))
732 TBM_LOG ("[libtbm:%d] "
733 "Fail to init module(%s)\n",
735 dlclose (module_data);
739 if (!bufmgr->backend || !bufmgr->backend->priv)
741 TBM_LOG ("[libtbm:%d] "
742 "Error: module(%s) wrong operation. Check backend or backend's priv.\n",
744 dlclose (module_data);
750 TBM_LOG ("[libtbm:%d] "
751 "Error: module does not supply init symbol.\n", getpid());
752 dlclose (module_data);
758 TBM_LOG ("[libtbm:%d] "
759 "Error: module does not have data object.\n", getpid());
760 dlclose (module_data);
764 bufmgr->module_data = module_data;
766 TBM_LOG ("[libtbm:%d] "
767 "Success to load module(%s)\n", getpid(), file);
772 static int _tbm_load_module (tbm_bufmgr bufmgr, int fd)
774 struct dirent **namelist;
775 const char *p = NULL;
779 /* load bufmgr priv from default lib */
780 ret = _tbm_bufmgr_load_module (bufmgr, fd, DEFAULT_LIB);
782 /* load bufmgr priv from configured path */
785 n = scandir (BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
787 TBM_LOG ("[libtbm:%d] "
788 "no files : %s\n", getpid(), BUFMGR_MODULE_DIR);
793 if (!ret && strstr (namelist[n]->d_name, PREFIX_LIB))
795 p = strstr (namelist[n]->d_name, SUFFIX_LIB);
796 if (!strcmp (p, SUFFIX_LIB))
798 ret = _tbm_bufmgr_load_module (bufmgr, fd, namelist[n]->d_name);
811 _tbm_bufmgr_get_drm_fd()
815 int dri2Major, dri2Minor;
816 int eventBase, errorBase;
818 char *driver_name, *device_name;
821 display = XOpenDisplay(NULL);
824 TBM_LOG ("[libtbm:%d] Fail XOpenDisplay\n", getpid());
828 screen = DefaultScreen(display);
830 if (!DRI2QueryExtension (display, &eventBase, &errorBase))
832 TBM_LOG ("[libtbm:%d] Fail DRI2QueryExtention\n", getpid());
833 XCloseDisplay(display);
837 if (!DRI2QueryVersion (display, &dri2Major, &dri2Minor))
839 TBM_LOG ("[libtbm:%d] Fail DRI2QueryVersion\n", getpid());
840 XCloseDisplay(display);
844 if (!DRI2Connect (display, RootWindow(display, screen), &driver_name, &device_name))
846 TBM_LOG ("[libtbm:%d] Fail DRI2Connect\n", getpid());
847 XCloseDisplay(display);
851 fd = open (device_name, O_RDWR);
854 TBM_LOG ("[libtbm:%d] cannot open drm device (%s)\n", getpid(), device_name);
857 XCloseDisplay(display);
861 if (drmGetMagic (fd, &magic))
863 TBM_LOG ("[libtbm:%d] Fail drmGetMagic\n", getpid());
867 XCloseDisplay(display);
871 if (!DRI2Authenticate(display, RootWindow(display, screen), magic))
873 TBM_LOG ("[libtbm:%d] Fail DRI2Authenticate\n", getpid());
877 XCloseDisplay(display);
881 if(!drmAuthMagic(fd, magic))
883 TBM_LOG ("[libtbm:%d] Fail drmAuthMagic\n", getpid());
887 XCloseDisplay(display);
893 XCloseDisplay(display);
898 tbm_bufmgr_init (int fd)
903 pthread_mutex_lock (&gLock);
906 env = getenv("GEM_DEBUG");
910 TBM_LOG ("GEM_DEBUG=%s\n", env);
916 /* initialize buffer manager */
919 TBM_LOG ("[libtbm:%d] use previous gBufMgr\n", getpid());
920 gBufMgr->ref_count++;
921 TBM_LOG ("[libtbm:%d] bufmgr ref: fd=%d, ref_count:%d\n",
922 getpid(), gBufMgr->fd, gBufMgr->ref_count);
923 pthread_mutex_unlock (&gLock);
929 fd = _tbm_bufmgr_get_drm_fd();
932 TBM_LOG ("[libtbm:%d] Fail get drm fd\n", getpid());
933 pthread_mutex_unlock (&gLock);
939 TBM_LOG ("[libtbm:%d] bufmgr init: fd=%d\n", getpid(), fd);
941 /* allocate bufmgr */
942 gBufMgr = calloc (1, sizeof(struct _tbm_bufmgr));
945 pthread_mutex_unlock (&gLock);
949 /* load bufmgr priv from env */
950 if (!_tbm_load_module(gBufMgr, fd))
952 TBM_LOG ("[libtbm:%d] "
953 "error : Fail to load bufmgr backend\n",
957 pthread_mutex_unlock (&gLock);
961 gBufMgr->fd_flag = fd_flag;
963 gBufMgr->ref_count = 1;
965 TBM_LOG ("[libtbm:%d] create tizen bufmgr: ref_count:%d\n", getpid(), gBufMgr->ref_count);
967 if (pthread_mutex_init (&gBufMgr->lock, NULL) != 0)
969 gBufMgr->backend->bufmgr_deinit (gBufMgr->backend->priv);
970 tbm_backend_free (gBufMgr->backend);
971 dlclose (gBufMgr->module_data);
974 pthread_mutex_unlock (&gLock);
978 /* intialize the tizen global status */
979 if (!_tbm_bufmgr_init_state (gBufMgr))
981 TBM_LOG ("[libtbm:%d] "
982 "error: Fail to init state\n",
984 gBufMgr->backend->bufmgr_deinit (gBufMgr->backend->priv);
985 tbm_backend_free (gBufMgr->backend);
986 pthread_mutex_destroy (&gBufMgr->lock);
987 dlclose (gBufMgr->module_data);
990 pthread_mutex_unlock (&gLock);
994 /* setup the lock_type */
995 env = getenv ("BUFMGR_LOCK_TYPE");
996 if (env && !strcmp (env, "always"))
997 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
998 else if(env && !strcmp(env, "none"))
999 gBufMgr->lock_type = LOCK_TRY_NEVER;
1000 else if(env && !strcmp(env, "once"))
1001 gBufMgr->lock_type = LOCK_TRY_ONCE;
1003 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
1005 DBG ("[libtbm:%d] BUFMGR_LOCK_TYPE=%s\n", getpid(), env?env:"default:once");
1007 /* setup the map_cache */
1008 env = getenv ("BUFMGR_MAP_CACHE");
1009 if (env && !strcmp (env, "false"))
1010 gBufMgr->use_map_cache = 0;
1012 gBufMgr->use_map_cache = 1;
1013 DBG ("[libtbm:%d] BUFMGR_MAP_CACHE=%s\n", getpid(), env?env:"default:true");
1015 /* intialize bo_list */
1016 LIST_INITHEAD (&gBufMgr->bo_list);
1018 /* intialize surf_list */
1019 LIST_INITHEAD (&gBufMgr->surf_list);
1021 pthread_mutex_unlock (&gLock);
1026 tbm_bufmgr_deinit (tbm_bufmgr bufmgr)
1028 TBM_RETURN_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr));
1033 tbm_surface_h surf = NULL;
1034 tbm_surface_h tmp_surf = NULL;
1036 pthread_mutex_lock (&gLock);
1038 bufmgr->ref_count--;
1039 if (bufmgr->ref_count > 0)
1041 TBM_LOG ("[libtbm:%d] "
1042 "tizen bufmgr destroy: bufmgr:%p, ref_count:%d\n",
1043 getpid(), bufmgr, bufmgr->ref_count);
1044 pthread_mutex_unlock (&gLock);
1048 /* destroy bo_list */
1049 if(!LIST_IS_EMPTY (&bufmgr->bo_list))
1051 LIST_FOR_EACH_ENTRY_SAFE (bo, tmp, &bufmgr->bo_list, item_link)
1053 TBM_LOG ("[libtbm:%d] "
1054 "Un-freed bo(%p, ref:%d) \n",
1055 getpid(), bo, bo->ref_cnt);
1061 /* destroy surf_list */
1062 if(!LIST_IS_EMPTY (&bufmgr->surf_list))
1064 LIST_FOR_EACH_ENTRY_SAFE (surf, tmp_surf, &bufmgr->surf_list, item_link)
1066 TBM_LOG ("[libtbm:%d] "
1067 "Destroy surf(%p) \n",
1069 tbm_surface_destroy(surf);
1073 /* destroy the tizen global status */
1074 _tbm_bufmgr_destroy_state (bufmgr);
1076 /* destroy bufmgr priv */
1077 bufmgr->backend->bufmgr_deinit (bufmgr->backend->priv);
1078 bufmgr->backend->priv = NULL;
1079 tbm_backend_free (bufmgr->backend);
1080 bufmgr->backend = NULL;
1082 pthread_mutex_destroy (&bufmgr->lock);
1084 TBM_LOG ("[libtbm:%d] "
1085 "tizen bufmgr destroy: bufmgr:%p\n",
1088 dlclose (bufmgr->module_data);
1097 pthread_mutex_unlock (&gLock);
1101 tbm_bo_size (tbm_bo bo)
1103 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1105 tbm_bufmgr bufmgr = bo->bufmgr;
1108 pthread_mutex_lock(&bufmgr->lock);
1110 size = bufmgr->backend->bo_size(bo);
1112 pthread_mutex_unlock(&bufmgr->lock);
1118 tbm_bo_ref (tbm_bo bo)
1120 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), NULL);
1122 tbm_bufmgr bufmgr = bo->bufmgr;
1124 pthread_mutex_lock(&bufmgr->lock);
1128 pthread_mutex_unlock(&bufmgr->lock);
1134 tbm_bo_unref (tbm_bo bo)
1136 TBM_RETURN_IF_FAIL(TBM_BO_IS_VALID(bo));
1138 tbm_bufmgr bufmgr = bo->bufmgr;
1140 pthread_mutex_lock (&bufmgr->lock);
1144 pthread_mutex_unlock(&bufmgr->lock);
1148 tbm_bo_alloc (tbm_bufmgr bufmgr, int size, int flags)
1150 TBM_RETURN_VAL_IF_FAIL (TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
1153 void * bo_priv = NULL;
1155 bo = calloc (1, sizeof(struct _tbm_bo));
1159 bo->bufmgr = bufmgr;
1161 pthread_mutex_lock (&bufmgr->lock);
1163 bo_priv = bufmgr->backend->bo_alloc (bo, size, flags);
1167 pthread_mutex_unlock (&bufmgr->lock);
1173 bo->tgl_key = INITIAL_KEY;
1177 if (!_tbm_bo_init_state (bo, CACHE_OP_CREATE))
1180 pthread_mutex_unlock (&bufmgr->lock);
1184 LIST_INITHEAD (&bo->user_data_list);
1186 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1188 pthread_mutex_unlock(&bufmgr->lock);
1194 tbm_bo_import (tbm_bufmgr bufmgr, unsigned int key)
1196 TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1199 void * bo_priv = NULL;
1201 bo = calloc (1, sizeof(struct _tbm_bo));
1205 bo->bufmgr = bufmgr;
1207 pthread_mutex_lock (&bufmgr->lock);
1209 bo_priv = bufmgr->backend->bo_import (bo, key);
1213 pthread_mutex_unlock (&bufmgr->lock);
1218 bo->tgl_key = INITIAL_KEY;
1222 if (!_tbm_bo_init_state (bo, CACHE_OP_IMPORT))
1225 pthread_mutex_unlock (&bufmgr->lock);
1229 LIST_INITHEAD (&bo->user_data_list);
1231 LIST_ADD (&bo->item_link, &bufmgr->bo_list);
1233 pthread_mutex_unlock (&bufmgr->lock);
1239 tbm_bo_import_fd (tbm_bufmgr bufmgr, tbm_fd fd)
1247 tbm_bo_export (tbm_bo bo)
1249 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1254 bufmgr = bo->bufmgr;
1256 pthread_mutex_lock (&bufmgr->lock);
1257 ret = bufmgr->backend->bo_export (bo);
1258 pthread_mutex_unlock (&bufmgr->lock);
1264 tbm_bo_export_fd (tbm_bo bo)
1273 tbm_bo_get_handle (tbm_bo bo, int device)
1275 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), (tbm_bo_handle)0);
1278 tbm_bo_handle bo_handle;
1280 bufmgr = bo->bufmgr;
1282 pthread_mutex_lock (&bufmgr->lock);
1283 bo_handle = bufmgr->backend->bo_get_handle (bo, device);
1284 pthread_mutex_unlock (&bufmgr->lock);
1290 tbm_bo_map (tbm_bo bo, int device, int opt)
1292 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), (tbm_bo_handle)0);
1295 tbm_bo_handle bo_handle;
1297 bufmgr = bo->bufmgr;
1299 pthread_mutex_lock (&bufmgr->lock);
1301 bo_handle = bufmgr->backend->bo_get_handle (bo, device);
1303 _tbm_bo_lock (bo, device, opt);
1305 bo_handle = bufmgr->backend->bo_map (bo, device, opt);
1307 if (bufmgr->use_map_cache == 1 && bo->map_cnt == 0)
1308 _tbm_bo_set_state (bo, device, opt);
1310 /* increase the map_count */
1313 pthread_mutex_unlock (&bufmgr->lock);
1319 tbm_bo_unmap (tbm_bo bo)
1321 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1326 bufmgr = bo->bufmgr;
1328 pthread_mutex_lock (&bufmgr->lock);
1331 ret = bufmgr->backend->bo_unmap (bo);
1333 /* decrease the map_count */
1336 if (bo->map_cnt == 0)
1337 _tbm_bo_save_state (bo);
1339 _tbm_bo_unlock (bo);
1341 pthread_mutex_unlock (&bufmgr->lock);
1347 tbm_bo_swap (tbm_bo bo1, tbm_bo bo2)
1349 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo1), 0);
1350 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo2), 0);
1353 unsigned int tmp_key;
1355 if (bo1->bufmgr->backend->bo_size (bo1) != bo2->bufmgr->backend->bo_size (bo2))
1358 pthread_mutex_lock (&bo1->bufmgr->lock);
1360 tmp_key = bo1->tgl_key;
1361 bo1->tgl_key = bo2->tgl_key;
1362 bo2->tgl_key = tmp_key;
1365 bo1->priv = bo2->priv;
1368 pthread_mutex_unlock (&bo1->bufmgr->lock);
1374 tbm_bo_locked (tbm_bo bo)
1376 TBM_RETURN_VAL_IF_FAIL (TBM_BO_IS_VALID(bo), 0);
1380 bufmgr = bo->bufmgr;
1382 if (bufmgr->lock_type == LOCK_TRY_NEVER)
1385 pthread_mutex_lock (&bufmgr->lock);
1387 if (bo->lock_cnt > 0)
1389 pthread_mutex_unlock (&bufmgr->lock);
1393 pthread_mutex_unlock (&bufmgr->lock);
1400 tbm_bo_add_user_data (tbm_bo bo, unsigned long key, tbm_data_free data_free_func)
1402 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1404 tbm_user_data *data;
1406 /* check if the data according to the key exist if so, return false.*/
1407 data = _user_data_lookup (&bo->user_data_list, key);
1410 TBM_LOG ("[libtbm:%d] "
1411 "waring: %s:%d user data already exist. key:%ld\n",
1412 getpid(), __FUNCTION__, __LINE__, key);
1416 data = _user_data_create (key, data_free_func);
1420 LIST_ADD (&data->item_link, &bo->user_data_list);
1426 tbm_bo_set_user_data (tbm_bo bo, unsigned long key, void* data)
1428 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1430 tbm_user_data *old_data;
1432 if (LIST_IS_EMPTY (&bo->user_data_list))
1435 old_data = _user_data_lookup (&bo->user_data_list, key);
1439 if (old_data->data && old_data->free_func)
1440 old_data->free_func(old_data->data);
1442 old_data->data = data;
1448 tbm_bo_get_user_data (tbm_bo bo, unsigned long key, void** data)
1450 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1452 tbm_user_data* old_data;
1454 if (!data || LIST_IS_EMPTY (&bo->user_data_list))
1457 old_data = _user_data_lookup (&bo->user_data_list, key);
1464 *data = old_data->data;
1470 tbm_bo_delete_user_data (tbm_bo bo, unsigned long key)
1472 TBM_RETURN_VAL_IF_FAIL(TBM_BO_IS_VALID(bo), 0);
1474 tbm_user_data *old_data = (void *)0;
1476 if (LIST_IS_EMPTY (&bo->user_data_list))
1479 old_data = _user_data_lookup (&bo->user_data_list, key);
1483 _user_data_delete (old_data);
1489 tbm_bo_cache_flush(tbm_bo bo, int flags)
1491 tbm_bufmgr bufmgr = bo->bufmgr;
1493 bufmgr->backend->bo_cache_flush (bo, flags);
1495 RETURN_VAL_CHECK_FLAG (TBM_CACHE_CTRL_BACKEND_VALID(bufmgr->backend->flags), 1);
1497 unsigned short cntFlush = 0;
1498 unsigned int is_locked;
1500 /* get cache state of a bo */
1501 bo->cache_state.val = _tgl_get_data (bufmgr->lock_fd, bo->tgl_key, &is_locked);
1503 if (!bo->cache_state.data.isCacheable)
1506 /* get global cache flush count */
1507 cntFlush = (unsigned short)_tgl_get_data (bufmgr->lock_fd, GLOBAL_KEY, NULL);
1509 bo->cache_state.data.isDirtied = DEVICE_NONE;
1510 bo->cache_state.data.isCached = 0;
1512 /* set global cache flush count */
1513 _tgl_set_data (bufmgr->lock_fd, GLOBAL_KEY, (unsigned int)(++cntFlush));
1515 DBG ("[libtbm:%d] \tcache(%d,%d,%d).... cntFlush(%d)\n", getpid(),
1516 bo->cache_state.data.isCacheable,
1517 bo->cache_state.data.isCached,
1518 bo->cache_state.data.isDirtied,