enforce the thread safety of the tbm_bufmgr
[platform/core/uifw/libtbm.git] / src / tbm_bufmgr.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
6
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>
9
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:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
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.
29
30 **************************************************************************/
31
32 #include "config.h"
33
34 #include "tbm_bufmgr.h"
35 #include "tbm_bufmgr_int.h"
36 #include "tbm_bufmgr_backend.h"
37 #include "list.h"
38
39 #ifdef DEBUG
40 int bDebug;
41 #endif
42
43 #ifdef TRACE
44 int bTrace;
45 #endif
46
47 #ifdef HAVE_DLOG
48 int bDlog;
49 #endif
50
51 tbm_bufmgr gBufMgr;
52 int b_dump_queue;
53
54 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
55 static pthread_mutex_t tbm_bufmgr_lock = PTHREAD_MUTEX_INITIALIZER;
56 static __thread tbm_error_e tbm_last_error = TBM_ERROR_NONE;
57
58 static void _tbm_bufmgr_mutex_unlock(void);
59
60 #define PREFIX_LIB    "libtbm_"
61 #define SUFFIX_LIB    ".so"
62 #define DEFAULT_LIB   PREFIX_LIB"default"SUFFIX_LIB
63
64 /* values to indicate unspecified fields in XF86ModReqInfo. */
65 #define MAJOR_UNSPEC        0xFF
66 #define MINOR_UNSPEC        0xFF
67 #define PATCH_UNSPEC        0xFFFF
68 #define ABI_VERS_UNSPEC   0xFFFFFFFF
69
70 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
71                         ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
72 #define GET_MODULE_MAJOR_VERSION(vers)    (((vers) >> 24) & 0xFF)
73 #define GET_MODULE_MINOR_VERSION(vers)    (((vers) >> 16) & 0xFF)
74 #define GET_MODULE_PATCHLEVEL(vers)    ((vers) & 0xFFFF)
75
76 /* check condition */
77 #define TBM_BUFMGR_RETURN_IF_FAIL(cond) {\
78         if (!(cond)) {\
79                 TBM_LOG_E("'%s' failed.\n", #cond);\
80                 _tbm_bufmgr_mutex_unlock();\
81                 return;\
82         } \
83 }
84
85 #define TBM_BUFMGR_RETURN_VAL_IF_FAIL(cond, val) {\
86         if (!(cond)) {\
87                 TBM_LOG_E("'%s' failed.\n", #cond);\
88                 _tbm_bufmgr_mutex_unlock();\
89                 return val;\
90         } \
91 }
92
93 enum {
94         LOCK_TRY_ONCE,
95         LOCK_TRY_ALWAYS,
96         LOCK_TRY_NEVER
97 };
98
99 static void
100 _tbm_set_last_result(tbm_error_e err)
101 {
102         tbm_last_error = err;
103 }
104
105 static bool
106 _tbm_bufmgr_mutex_init(void)
107 {
108         static bool tbm_bufmgr_mutex_init = false;
109
110         if (tbm_bufmgr_mutex_init)
111                 return true;
112
113         if (pthread_mutex_init(&tbm_bufmgr_lock, NULL)) {
114                 TBM_LOG_E("fail: tbm_bufmgr mutex init\n");
115                 return false;
116         }
117
118         tbm_bufmgr_mutex_init = true;
119
120         return true;
121 }
122
123 static void
124 _tbm_bufmgr_mutex_lock(void)
125 {
126         if (!_tbm_bufmgr_mutex_init())
127                 return;
128
129         pthread_mutex_lock(&tbm_bufmgr_lock);
130 }
131
132 static void
133 _tbm_bufmgr_mutex_unlock(void)
134 {
135         pthread_mutex_unlock(&tbm_bufmgr_lock);
136 }
137
138 char * tbm_flag_to_str(int f)
139 {
140         static char str[255];
141         int c = 0;
142         if (f == TBM_BO_DEFAULT)
143                  snprintf(str, 255, "DEFAULT\n");
144         else {
145                 if (f & TBM_BO_SCANOUT)
146                         c = snprintf(&str[c], 255, "SCANOUT,");
147                 if (f & TBM_BO_NONCACHABLE)
148                         c = snprintf(&str[c], 255, "NONCACHABLE,");
149                 if (f & TBM_BO_WC)
150                         c = snprintf(&str[c], 255, "WC");
151         }
152         return str;
153 }
154
155 /* LCOV_EXCL_START */
156 static int last_chk_bo_cnt = 0;
157 static void
158 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
159 {
160         if (bufmgr->bo_cnt >= 500 && ((bufmgr->bo_cnt % 20) == 0)) {
161                 if (bufmgr->bo_cnt > last_chk_bo_cnt) {
162                         TBM_DEBUG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
163                         tbm_bufmgr_debug_show(bufmgr);
164                         last_chk_bo_cnt = bufmgr->bo_cnt;
165                 }
166         }
167 }
168
169 static int
170 _tbm_util_get_max_surface_size(int * w, int * h)
171 {
172         int count = 0;
173         tbm_surface_h surface = NULL, tmp = NULL;
174         tbm_surface_info_s info;
175
176         *w = 0;
177         *h = 0;
178
179         if (gBufMgr == NULL)
180                 return count;
181
182         if (!LIST_IS_EMPTY(&gBufMgr->surf_list)) {
183                 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
184                         if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
185                                 count++;
186                                 if (*w < info.width) *w = info.width;
187                                 if (*h < info.height) *h = info.height;
188                         }
189                 }
190         }
191
192         return count;
193 }
194
195 static void
196 _tbm_util_get_appname_brief(char *brief)
197 {
198         char delim[] = "/";
199         char *token = NULL;
200         char temp[255] = {0,};
201         char *saveptr = NULL;
202
203         token = strtok_r(brief, delim, &saveptr);
204
205         while (token != NULL) {
206                 memset(temp, 0x00, 255 * sizeof(char));
207                 strncpy(temp, token, 254 * sizeof(char));
208                 token = strtok_r(NULL, delim, &saveptr);
209         }
210
211         snprintf(brief, sizeof(temp), "%s", temp);
212 }
213
214 static void
215 _tbm_util_get_appname_from_pid(long pid, char *str)
216 {
217         FILE *fp;
218         int len;
219         long app_pid = pid;
220         char fn_cmdline[255] = {0,};
221         char cmdline[255] = {0,};
222
223         snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", app_pid);
224
225         fp = fopen(fn_cmdline, "r");
226         if (fp == 0) {
227                 fprintf(stderr, "cannot file open /proc/%ld/cmdline", app_pid);
228                 return;
229         }
230
231         if (!fgets(cmdline, 255, fp)) {
232                 fprintf(stderr, "fail to get appname for pid(%ld)\n", app_pid);
233                 fclose(fp);
234                 return;
235         }
236         fclose(fp);
237
238         len = strlen(cmdline);
239         if (len < 1)
240                 memset(cmdline, 0x00, 255);
241         else
242                 cmdline[len] = 0;
243
244         snprintf(str, sizeof(cmdline), "%s", cmdline);
245 }
246 /* LCOV_EXCL_STOP */
247
248 tbm_user_data
249 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
250 {
251         tbm_user_data *user_data = NULL;
252         tbm_user_data *old_data = NULL, *tmp = NULL;
253
254         if (!LIST_IS_EMPTY(user_data_list)) {
255                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, user_data_list, item_link) {
256                         if (old_data->key == key) {
257                                 user_data = old_data;
258                                 return user_data;
259                         }
260                 }
261         }
262
263         return user_data;
264 }
265
266 tbm_user_data
267 *user_data_create(unsigned long key, tbm_data_free data_free_func)
268 {
269         tbm_user_data *user_data = NULL;
270
271         user_data = calloc(1, sizeof(tbm_user_data));
272         if (!user_data)
273                 return NULL;
274
275         user_data->key = key;
276         user_data->free_func = data_free_func;
277         user_data->data = (void *)0;
278
279         return user_data;
280 }
281
282 void
283 user_data_delete(tbm_user_data *user_data)
284 {
285         if (user_data->data && user_data->free_func)
286                 user_data->free_func(user_data->data);
287
288         LIST_DEL(&user_data->item_link);
289
290         free(user_data);
291 }
292
293 static int
294 _bo_lock(tbm_bo bo, int device, int opt)
295 {
296         tbm_bufmgr bufmgr = bo->bufmgr;
297         int ret = 0;
298
299         if (bufmgr->backend->bo_lock)
300                 ret = bufmgr->backend->bo_lock(bo, device, opt);
301         else
302                 ret = 1;
303
304         return ret;
305 }
306
307 static void
308 _bo_unlock(tbm_bo bo)
309 {
310         tbm_bufmgr bufmgr = bo->bufmgr;
311
312         if (bufmgr->backend->bo_unlock)
313                 bufmgr->backend->bo_unlock(bo);
314 }
315
316 static int
317 _tbm_bo_lock(tbm_bo bo, int device, int opt)
318 {
319         tbm_bufmgr bufmgr = NULL;
320         int old;
321         int ret = 0;
322
323         if (!bo)
324                 return 0;
325
326         bufmgr = bo->bufmgr;
327
328         /* do not try to lock the bo */
329         if (bufmgr->lock_type == LOCK_TRY_NEVER)
330                 return 1;
331
332         if (bo->lock_cnt < 0) {
333                 TBM_LOG_E("error bo:%p LOCK_CNT=%d\n",
334                         bo, bo->lock_cnt);
335         }
336
337         old = bo->lock_cnt;
338         if (bufmgr->lock_type == LOCK_TRY_ONCE) {
339                 if (bo->lock_cnt == 0) {
340                         _tbm_bufmgr_mutex_unlock();
341                         ret = _bo_lock(bo, device, opt);
342                         _tbm_bufmgr_mutex_lock();
343                         if (ret)
344                                 bo->lock_cnt++;
345                 } else
346                         ret = 1;
347         } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
348                 _tbm_bufmgr_mutex_unlock();
349                 ret = _bo_lock(bo, device, opt);
350                 _tbm_bufmgr_mutex_lock();
351                 if (ret)
352                         bo->lock_cnt++;
353         } else {
354                 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
355                         bo);
356         }
357
358         DBG_LOCK(">> LOCK bo:%p(%d->%d)\n",
359                  bo, old, bo->lock_cnt);
360
361         return ret;
362 }
363
364 static void
365 _tbm_bo_unlock(tbm_bo bo)
366 {
367         tbm_bufmgr bufmgr = NULL;
368
369         int old;
370
371         if (!bo)
372                 return;
373
374         bufmgr = bo->bufmgr;
375
376         /* do not try to unlock the bo */
377         if (bufmgr->lock_type == LOCK_TRY_NEVER)
378                 return;
379
380         old = bo->lock_cnt;
381         if (bufmgr->lock_type == LOCK_TRY_ONCE) {
382                 if (bo->lock_cnt > 0) {
383                         bo->lock_cnt--;
384                         if (bo->lock_cnt == 0)
385                                 _bo_unlock(bo);
386                 }
387         } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
388                 if (bo->lock_cnt > 0) {
389                         bo->lock_cnt--;
390                         _bo_unlock(bo);
391                 }
392         } else {
393                 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
394                         bo);
395         }
396
397         if (bo->lock_cnt < 0)
398                 bo->lock_cnt = 0;
399
400         DBG_LOCK(">> UNLOCK bo:%p(%d->%d)\n",
401                  bo, old, bo->lock_cnt);
402 }
403
404 static int
405 _tbm_bo_is_valid(tbm_bo bo)
406 {
407         tbm_bo old_data = NULL, tmp = NULL;
408
409         if (bo == NULL)
410                 return 0;
411
412         if (gBufMgr == NULL) {
413                 TBM_LOG_E("error tbm_bufmgr was deinited\n");
414                 return 0;
415         }
416
417         if (!LIST_IS_EMPTY(&gBufMgr->bo_list)) {
418                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &gBufMgr->bo_list, item_link) {
419                         if (old_data == bo)
420                                 return 1;
421                 }
422
423         }
424         return 0;
425 }
426
427 /* LCOV_EXCL_START */
428 static int
429 _check_version(TBMModuleVersionInfo *data)
430 {
431         int abimaj, abimin;
432         int vermaj, vermin;
433
434         abimaj = GET_ABI_MAJOR(data->abiversion);
435         abimin = GET_ABI_MINOR(data->abiversion);
436
437         DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
438             data->modname ? data->modname : "UNKNOWN!",
439             data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
440
441         vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
442         vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
443
444         DBG("TBM ABI version %d.%d\n",
445             vermaj, vermin);
446
447         if (abimaj != vermaj) {
448                 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
449                         abimaj, vermaj);
450                 return 0;
451         } else if (abimin > vermin) {
452                 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
453                         abimin, vermin);
454                 return 0;
455         }
456         return 1;
457 }
458
459 static int
460 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
461 {
462         char path[PATH_MAX] = { 0, };
463         TBMModuleData *initdata = NULL;
464         void *module_data;
465
466         snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
467
468         module_data = dlopen(path, RTLD_LAZY);
469         if (!module_data) {
470                 TBM_LOG_E("failed to load module: %s(%s)\n",
471                         dlerror(), file);
472                 return 0;
473         }
474
475         initdata = dlsym(module_data, "tbmModuleData");
476         if (initdata) {
477                 ModuleInitProc init;
478                 TBMModuleVersionInfo *vers;
479
480                 vers = initdata->vers;
481                 init = initdata->init;
482
483                 if (vers) {
484                         if (!_check_version(vers)) {
485                                 dlclose(module_data);
486                                 return 0;
487                         }
488                 } else {
489                         TBM_LOG_E("Error: module does not supply version information.\n");
490
491                         dlclose(module_data);
492                         return 0;
493                 }
494
495                 if (init) {
496                         if (!init(bufmgr, fd)) {
497                                 TBM_LOG_E("Fail to init module(%s)\n",
498                                         file);
499                                 dlclose(module_data);
500                                 return 0;
501                         }
502
503                         if (!bufmgr->backend || !bufmgr->backend->priv) {
504                                 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n",
505                                         file);
506                                 dlclose(module_data);
507                                 return 0;
508                         }
509                 } else {
510                         TBM_LOG_E("Error: module does not supply init symbol.\n");
511                         dlclose(module_data);
512                         return 0;
513                 }
514         } else {
515                 TBM_LOG_E("Error: module does not have data object.\n");
516                 dlclose(module_data);
517                 return 0;
518         }
519
520         bufmgr->module_data = module_data;
521
522         DBG("Success to load module(%s)\n",
523             file);
524
525         return 1;
526 }
527
528 static int
529 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
530 {
531         struct dirent **namelist;
532         const char *p = NULL;
533         int n;
534         int ret = 0;
535
536         /* load bufmgr priv from default lib */
537         ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
538
539         /* load bufmgr priv from configured path */
540         if (!ret) {
541                 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
542                 if (n < 0) {
543                         TBM_LOG_E("no files : %s\n",
544                                 BUFMGR_MODULE_DIR);
545                 } else {
546                         while (n--) {
547                                 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
548                                         p = strstr(namelist[n]->d_name, SUFFIX_LIB);
549                                         if (p && !strcmp(p, SUFFIX_LIB))
550                                                 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
551                                 }
552                                 free(namelist[n]);
553                         }
554                         free(namelist);
555                 }
556         }
557
558         return ret;
559 }
560 /* LCOV_EXCL_STOP */
561
562 tbm_bufmgr
563 tbm_bufmgr_init(int fd)
564 {
565         char *env;
566
567         pthread_mutex_lock(&gLock);
568
569         /* LCOV_EXCL_START */
570 #ifdef HAVE_DLOG
571         env = getenv("TBM_DLOG");
572         if (env) {
573                 bDlog = atoi(env);
574                 TBM_LOG_D("TBM_DLOG=%s\n", env);
575         } else {
576                 bDlog = 1;
577         }
578 #endif
579
580 #ifdef DEBUG
581         env = getenv("TBM_DEBUG");
582         if (env) {
583                 bDebug = atoi(env);
584                 TBM_LOG_D("TBM_DEBUG=%s\n", env);
585         } else {
586                 bDebug = 0;
587         }
588 #endif
589
590 #ifdef TRACE
591         env = getenv("TBM_TRACE");
592         if (env) {
593                 bTrace = atoi(env);
594                 TBM_LOG_D("TBM_TRACE=%s\n", env);
595         } else {
596                 bTrace = 0;
597         }
598 #endif
599         /* LCOV_EXCL_STOP */
600
601         /* initialize buffer manager */
602         if (gBufMgr) {
603                 gBufMgr->ref_count++;
604                 TBM_TRACE("reuse  tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
605                 pthread_mutex_unlock(&gLock);
606                 return gBufMgr;
607         }
608
609         DBG("bufmgr init\n");
610
611         /* allocate bufmgr */
612         gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
613         if (!gBufMgr) {
614                 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
615                 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
616                 pthread_mutex_unlock(&gLock);
617                 return NULL;
618         }
619
620         gBufMgr->fd = fd;
621
622         /* load bufmgr priv from env */
623         if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
624                 /* LCOV_EXCL_START */
625                 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
626                 TBM_LOG_E("error : Fail to load bufmgr backend\n");
627                 free(gBufMgr);
628                 gBufMgr = NULL;
629                 pthread_mutex_unlock(&gLock);
630                 return NULL;
631                 /* LCOV_EXCL_STOP */
632         }
633
634         /* log for tbm backend_flag */
635         DBG("backend flag:%x:", gBufMgr->backend->flags);
636         DBG("\n");
637
638         gBufMgr->ref_count = 1;
639
640         DBG("create tizen bufmgr:%p ref_count:%d\n",
641             gBufMgr, gBufMgr->ref_count);
642
643         /* setup the lock_type */
644         env = getenv("BUFMGR_LOCK_TYPE");
645         if (env && !strcmp(env, "always"))
646                 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
647         else if (env && !strcmp(env, "none"))
648                 gBufMgr->lock_type = LOCK_TRY_NEVER;
649         else if (env && !strcmp(env, "once"))
650                 gBufMgr->lock_type = LOCK_TRY_ONCE;
651         else
652                 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
653
654         DBG("BUFMGR_LOCK_TYPE=%s\n",
655             env ? env : "default:once");
656
657         TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
658
659         /* intialize bo_list */
660         LIST_INITHEAD(&gBufMgr->bo_list);
661
662         /* intialize surf_list */
663         LIST_INITHEAD(&gBufMgr->surf_list);
664
665         /* intialize debug_key_list */
666         LIST_INITHEAD(&gBufMgr->debug_key_list);
667
668         pthread_mutex_unlock(&gLock);
669
670         return gBufMgr;
671 }
672
673 void
674 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
675 {
676         TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
677
678         tbm_bo bo = NULL;
679         tbm_bo tmp = NULL;
680
681         tbm_surface_h surf = NULL;
682         tbm_surface_h tmp_surf = NULL;
683
684         pthread_mutex_lock(&gLock);
685
686         if (!gBufMgr) {
687                 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
688                 pthread_mutex_unlock(&gLock);
689                 return;
690         }
691
692         bufmgr->ref_count--;
693         if (bufmgr->ref_count > 0) {
694                 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
695                 pthread_mutex_unlock(&gLock);
696                 return;
697         }
698
699         /* destroy bo_list */
700         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
701                 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
702                         TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
703                                 bo, bo->ref_cnt);
704                         bo->ref_cnt = 1;
705                         tbm_bo_unref(bo);
706                 }
707         }
708
709         /* destroy surf_list */
710         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
711                 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
712                         TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
713                                 surf, surf->refcnt);
714                         tbm_surface_destroy(surf);
715                 }
716         }
717
718         /* destroy bufmgr priv */
719         bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
720         bufmgr->backend->priv = NULL;
721         tbm_backend_free(bufmgr->backend);
722         bufmgr->backend = NULL;
723
724         TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
725
726         dlclose(bufmgr->module_data);
727
728         if (bufmgr->fd > 0)
729                 close(bufmgr->fd);
730
731         free(bufmgr);
732         bufmgr = NULL;
733         gBufMgr = NULL;
734
735         pthread_mutex_unlock(&gLock);
736 }
737
738 int
739 tbm_bo_size(tbm_bo bo)
740 {
741         tbm_bufmgr bufmgr = NULL;
742         int size;
743
744         _tbm_bufmgr_mutex_lock();
745
746         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
747         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
748
749         bufmgr = gBufMgr;
750
751         size = bufmgr->backend->bo_size(bo);
752
753         TBM_TRACE("bo(%p) size(%d)\n", bo, size);
754
755         _tbm_bufmgr_mutex_unlock();
756
757         return size;
758 }
759
760 tbm_bo
761 tbm_bo_ref(tbm_bo bo)
762 {
763         _tbm_bufmgr_mutex_lock();
764
765         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
766         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
767
768         bo->ref_cnt++;
769
770         TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
771
772         _tbm_bufmgr_mutex_unlock();
773
774         return bo;
775 }
776
777 void
778 tbm_bo_unref(tbm_bo bo)
779 {
780         tbm_bufmgr bufmgr = NULL;
781         tbm_user_data *old_data = NULL, *tmp = NULL;
782
783         _tbm_bufmgr_mutex_lock();
784
785         TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
786         TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
787
788         bufmgr = gBufMgr;
789
790         TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
791
792         if (bo->ref_cnt <= 0) {
793                 _tbm_bufmgr_mutex_unlock();
794                 return;
795         }
796
797         bo->ref_cnt--;
798         if (bo->ref_cnt == 0) {
799                 /* destory the user_data_list */
800                 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
801                         LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
802                                 DBG("free user_data\n");
803                                 user_data_delete(old_data);
804                         }
805                 }
806
807                 if (bo->lock_cnt > 0) {
808                         TBM_LOG_E("error lock_cnt:%d\n",
809                                 bo->lock_cnt);
810                         _bo_unlock(bo);
811                 }
812
813                 /* call the bo_free */
814                 bufmgr->backend->bo_free(bo);
815                 bo->priv = NULL;
816
817                 LIST_DEL(&bo->item_link);
818                 free(bo);
819
820                 bufmgr->bo_cnt--;
821         }
822
823         _tbm_bufmgr_mutex_unlock();
824 }
825
826 tbm_bo
827 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
828 {
829         tbm_bo bo = NULL;
830         void *bo_priv = NULL;
831
832         _tbm_bufmgr_mutex_lock();
833
834         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
835         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
836         TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
837
838         bo = calloc(1, sizeof(struct _tbm_bo));
839         if (!bo) {
840                 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
841                 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
842                 _tbm_bufmgr_mutex_unlock();
843                 return NULL;
844         }
845
846         _tbm_util_check_bo_cnt(bufmgr);
847         bufmgr->bo_cnt++;
848
849         bo->bufmgr = bufmgr;
850
851         bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
852         if (!bo_priv) {
853                 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
854                 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
855                 free(bo);
856                 _tbm_bufmgr_mutex_unlock();
857                 return NULL;
858         }
859
860         bo->ref_cnt = 1;
861         bo->flags = flags;
862         bo->priv = bo_priv;
863
864         TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
865
866         LIST_INITHEAD(&bo->user_data_list);
867
868         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
869
870         _tbm_bufmgr_mutex_unlock();
871
872         return bo;
873 }
874
875 tbm_bo
876 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
877 {
878         tbm_bo bo = NULL;
879         tbm_bo bo2 = NULL;
880         tbm_bo tmp = NULL;
881         void *bo_priv = NULL;
882
883         _tbm_bufmgr_mutex_lock();
884
885         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
886         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
887
888         if (!bufmgr->backend->bo_import) {
889                 _tbm_bufmgr_mutex_unlock();
890                 return NULL;
891         }
892
893         _tbm_util_check_bo_cnt(bufmgr);
894
895         bo = calloc(1, sizeof(struct _tbm_bo));
896         if (!bo) {
897                 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
898                 _tbm_bufmgr_mutex_unlock();
899                 return NULL;
900         }
901
902         bufmgr->bo_cnt++;
903
904         bo->bufmgr = bufmgr;
905
906         bo_priv = bufmgr->backend->bo_import(bo, key);
907         if (!bo_priv) {
908                 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
909                 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
910                 free(bo);
911                 _tbm_bufmgr_mutex_unlock();
912                 return NULL;
913         }
914
915         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
916                 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
917                         if (bo2->priv == bo_priv) {
918                                 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
919                                                         bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
920                                 bo2->ref_cnt++;
921                                 free(bo);
922                                 _tbm_bufmgr_mutex_unlock();
923                                 return bo2;
924                         }
925                 }
926         }
927
928         bo->ref_cnt = 1;
929         bo->priv = bo_priv;
930
931         if (bufmgr->backend->bo_get_flags)
932                 bo->flags = bufmgr->backend->bo_get_flags(bo);
933         else
934                 bo->flags = TBM_BO_DEFAULT;
935
936         TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
937                           bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
938
939         LIST_INITHEAD(&bo->user_data_list);
940
941         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
942
943         _tbm_bufmgr_mutex_unlock();
944
945         return bo;
946 }
947
948 tbm_bo
949 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
950 {
951         tbm_bo bo = NULL;
952         tbm_bo bo2 = NULL;
953         tbm_bo tmp = NULL;
954         void *bo_priv = NULL;
955
956         _tbm_bufmgr_mutex_lock();
957
958         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
959         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
960
961         if (!bufmgr->backend->bo_import_fd) {
962                 _tbm_bufmgr_mutex_unlock();
963                 return NULL;
964         }
965
966         _tbm_util_check_bo_cnt(bufmgr);
967
968         bo = calloc(1, sizeof(struct _tbm_bo));
969         if (!bo) {
970                 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
971                 _tbm_bufmgr_mutex_unlock();
972                 return NULL;
973         }
974
975         bufmgr->bo_cnt++;
976
977         bo->bufmgr = bufmgr;
978
979         bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
980         if (!bo_priv) {
981                 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
982                 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
983                 free(bo);
984                 _tbm_bufmgr_mutex_unlock();
985                 return NULL;
986         }
987
988         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
989                 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
990                         if (bo2->priv == bo_priv) {
991                                 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
992                                                         bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
993                                 bo2->ref_cnt++;
994                                 free(bo);
995                                 _tbm_bufmgr_mutex_unlock();
996                                 return bo2;
997                         }
998                 }
999         }
1000
1001         bo->ref_cnt = 1;
1002         bo->priv = bo_priv;
1003
1004         if (bufmgr->backend->bo_get_flags)
1005                 bo->flags = bufmgr->backend->bo_get_flags(bo);
1006         else
1007                 bo->flags = TBM_BO_DEFAULT;
1008
1009         TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1010                                 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
1011
1012         LIST_INITHEAD(&bo->user_data_list);
1013
1014         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1015
1016         _tbm_bufmgr_mutex_unlock();
1017
1018         return bo;
1019 }
1020
1021 tbm_key
1022 tbm_bo_export(tbm_bo bo)
1023 {
1024         tbm_bufmgr bufmgr = NULL;
1025         tbm_key ret;
1026
1027         _tbm_bufmgr_mutex_lock();
1028
1029         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1030         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1031
1032         bufmgr = gBufMgr;
1033
1034         if (!bufmgr->backend->bo_export) {
1035                 _tbm_bufmgr_mutex_unlock();
1036                 return 0;
1037         }
1038
1039         ret = bufmgr->backend->bo_export(bo);
1040         if (!ret) {
1041                 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1042                 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1043                 _tbm_bufmgr_mutex_unlock();
1044                 return ret;
1045         }
1046
1047         TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
1048
1049         _tbm_bufmgr_mutex_unlock();
1050
1051         return ret;
1052 }
1053
1054 tbm_fd
1055 tbm_bo_export_fd(tbm_bo bo)
1056 {
1057         tbm_bufmgr bufmgr = NULL;
1058         int ret;
1059
1060         _tbm_bufmgr_mutex_lock();
1061
1062         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1063         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1064
1065         bufmgr = gBufMgr;
1066
1067         if (!bufmgr->backend->bo_export_fd) {
1068                 _tbm_bufmgr_mutex_unlock();
1069                 return 0;
1070         }
1071
1072         ret = bufmgr->backend->bo_export_fd(bo);
1073         if (ret < 0) {
1074                 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1075                 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1076                 _tbm_bufmgr_mutex_unlock();
1077                 return ret;
1078         }
1079
1080         TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1081
1082         _tbm_bufmgr_mutex_unlock();
1083
1084         return ret;
1085 }
1086
1087 tbm_bo_handle
1088 tbm_bo_get_handle(tbm_bo bo, int device)
1089 {
1090         tbm_bufmgr bufmgr = NULL;
1091         tbm_bo_handle bo_handle;
1092
1093         _tbm_bufmgr_mutex_lock();
1094
1095         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1096         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1097
1098         bufmgr = gBufMgr;
1099
1100         bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1101         if (bo_handle.ptr == NULL) {
1102                 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1103                 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1104                 _tbm_bufmgr_mutex_unlock();
1105                 return (tbm_bo_handle) NULL;
1106         }
1107
1108         TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1109
1110         _tbm_bufmgr_mutex_unlock();
1111
1112         return bo_handle;
1113 }
1114
1115 tbm_bo_handle
1116 tbm_bo_map(tbm_bo bo, int device, int opt)
1117 {
1118         tbm_bufmgr bufmgr = NULL;
1119         tbm_bo_handle bo_handle;
1120
1121         _tbm_bufmgr_mutex_lock();
1122
1123         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1124         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1125
1126         bufmgr = gBufMgr;
1127
1128         if (!_tbm_bo_lock(bo, device, opt)) {
1129                 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1130                 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1131                 _tbm_bufmgr_mutex_unlock();
1132                 return (tbm_bo_handle) NULL;
1133         }
1134
1135         bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1136         if (bo_handle.ptr == NULL) {
1137                 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1138                 TBM_TRACE("error: fail to map bo:%p\n", bo);
1139                 _tbm_bo_unlock(bo);
1140                 _tbm_bufmgr_mutex_unlock();
1141                 return (tbm_bo_handle) NULL;
1142         }
1143
1144         /* increase the map_count */
1145         bo->map_cnt++;
1146
1147         TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1148
1149         _tbm_bufmgr_mutex_unlock();
1150
1151         return bo_handle;
1152 }
1153
1154 int
1155 tbm_bo_unmap(tbm_bo bo)
1156 {
1157         tbm_bufmgr bufmgr = NULL;
1158         int ret;
1159
1160         _tbm_bufmgr_mutex_lock();
1161
1162         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1163         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1164
1165         bufmgr = gBufMgr;
1166
1167         ret = bufmgr->backend->bo_unmap(bo);
1168         if (!ret) {
1169                 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1170                 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1171                 _tbm_bufmgr_mutex_unlock();
1172                 return ret;
1173         }
1174
1175         /* decrease the map_count */
1176         bo->map_cnt--;
1177
1178         TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1179
1180         _tbm_bo_unlock(bo);
1181
1182         _tbm_bufmgr_mutex_unlock();
1183
1184         return ret;
1185 }
1186
1187 int
1188 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1189 {
1190         tbm_bufmgr bufmgr = NULL;
1191         void *temp;
1192
1193         _tbm_bufmgr_mutex_lock();
1194
1195         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1196         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1197         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1198
1199         bufmgr = gBufMgr;
1200
1201         TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1202
1203         if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1204                 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1205                 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1206                 _tbm_bufmgr_mutex_unlock();
1207                 return 0;
1208         }
1209
1210         TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1211
1212         temp = bo1->priv;
1213         bo1->priv = bo2->priv;
1214         bo2->priv = temp;
1215
1216         _tbm_bufmgr_mutex_unlock();
1217
1218         return 1;
1219 }
1220
1221 int
1222 tbm_bo_locked(tbm_bo bo)
1223 {
1224         tbm_bufmgr bufmgr = NULL;
1225
1226         _tbm_bufmgr_mutex_lock();
1227
1228         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1229         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1230
1231         bufmgr = gBufMgr;
1232
1233         if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1234                 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1235                 _tbm_bufmgr_mutex_unlock();
1236                 return 0;
1237         }
1238
1239         if (bo->lock_cnt > 0) {
1240                 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1241                 _tbm_bufmgr_mutex_unlock();
1242                 return 1;
1243         }
1244
1245         TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1246         _tbm_bufmgr_mutex_unlock();
1247
1248         return 0;
1249 }
1250
1251 int
1252 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1253                      tbm_data_free data_free_func)
1254 {
1255         tbm_user_data *data;
1256
1257         _tbm_bufmgr_mutex_lock();
1258
1259         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1260         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1261
1262         /* check if the data according to the key exist if so, return false. */
1263         data = user_data_lookup(&bo->user_data_list, key);
1264         if (data) {
1265                 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1266                 _tbm_bufmgr_mutex_unlock();
1267                 return 0;
1268         }
1269
1270         data = user_data_create(key, data_free_func);
1271         if (!data) {
1272                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1273                 _tbm_bufmgr_mutex_unlock();
1274                 return 0;
1275         }
1276
1277         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1278
1279         LIST_ADD(&data->item_link, &bo->user_data_list);
1280
1281         _tbm_bufmgr_mutex_unlock();
1282
1283         return 1;
1284 }
1285
1286 int
1287 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1288 {
1289         tbm_user_data *old_data;
1290
1291         _tbm_bufmgr_mutex_lock();
1292
1293         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1294         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1295
1296         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1297                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1298                 _tbm_bufmgr_mutex_unlock();
1299                 return 0;
1300         }
1301
1302         old_data = user_data_lookup(&bo->user_data_list, key);
1303         if (!old_data) {
1304                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1305                 _tbm_bufmgr_mutex_unlock();
1306                 return 0;
1307         }
1308
1309         if (old_data->data && old_data->free_func)
1310                 old_data->free_func(old_data->data);
1311
1312         old_data->data = data;
1313
1314         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1315
1316         _tbm_bufmgr_mutex_unlock();
1317
1318         return 1;
1319 }
1320
1321 int
1322 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1323 {
1324         tbm_user_data *old_data;
1325
1326         _tbm_bufmgr_mutex_lock();
1327
1328         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1329         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1330
1331         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1332                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1333                 _tbm_bufmgr_mutex_unlock();
1334                 return 0;
1335         }
1336
1337         old_data = user_data_lookup(&bo->user_data_list, key);
1338         if (!old_data) {
1339                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1340                 *data = NULL;
1341                 _tbm_bufmgr_mutex_unlock();
1342                 return 0;
1343         }
1344
1345         *data = old_data->data;
1346
1347         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1348
1349         _tbm_bufmgr_mutex_unlock();
1350
1351         return 1;
1352 }
1353
1354 int
1355 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1356 {
1357         tbm_user_data *old_data = (void *)0;
1358
1359         _tbm_bufmgr_mutex_lock();
1360
1361         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1362         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1363
1364         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1365                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1366                 _tbm_bufmgr_mutex_unlock();
1367                 return 0;
1368         }
1369
1370         old_data = user_data_lookup(&bo->user_data_list, key);
1371         if (!old_data) {
1372                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1373                 _tbm_bufmgr_mutex_unlock();
1374                 return 0;
1375         }
1376
1377         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1378
1379         user_data_delete(old_data);
1380
1381         _tbm_bufmgr_mutex_unlock();
1382
1383         return 1;
1384 }
1385
1386 unsigned int
1387 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1388 {
1389         int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1390
1391         _tbm_bufmgr_mutex_lock();
1392
1393         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1394         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1395
1396         TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1397
1398         capabilities = bufmgr->capabilities;
1399
1400         _tbm_bufmgr_mutex_unlock();
1401
1402         return capabilities;
1403 }
1404
1405 int
1406 tbm_bo_get_flags(tbm_bo bo)
1407 {
1408         int flags;
1409
1410         _tbm_bufmgr_mutex_lock();
1411
1412         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1413         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1414
1415         flags = bo->flags;
1416
1417         TBM_TRACE("bo(%p)\n", bo);
1418
1419         _tbm_bufmgr_mutex_unlock();
1420
1421         return flags;
1422 }
1423
1424 /* LCOV_EXCL_START */
1425 tbm_error_e
1426 tbm_get_last_error(void)
1427 {
1428         return tbm_last_error;
1429 }
1430
1431 void
1432 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1433 {
1434         tbm_bo bo = NULL, tmp_bo = NULL;
1435         int bo_cnt = 0;
1436         tbm_surface_h surf = NULL, tmp_surf = NULL;
1437         int surf_cnt = 0;
1438         int i;
1439         char app_name[255] = {0,};
1440         unsigned int pid = 0;
1441         char title[255] = {0,};
1442         char data[255] = {0,};
1443         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1444
1445         _tbm_bufmgr_mutex_lock();
1446
1447         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1448         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1449
1450         TBM_DEBUG("\n");
1451         _tbm_util_get_appname_from_pid(getpid(), app_name);
1452         _tbm_util_get_appname_brief(app_name);
1453         TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1454                   app_name, getpid());
1455         memset(app_name, 0x0, 255 * sizeof(char));
1456         snprintf(title, 255, "%s", "no  surface     refcnt  width  height  bpp  size    n_b  n_p  flags  format    app_name       ");
1457         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1458                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1459                         strncat(title, "  ", 2);
1460                         strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1461                 }
1462         }
1463
1464         TBM_DEBUG("[tbm_surface information]\n");
1465         TBM_DEBUG("%s\n", title);
1466         /* show the tbm_surface information in surf_list */
1467         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1468                 char *value = NULL;
1469
1470                 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1471                         pid = _tbm_surface_internal_get_debug_pid(surf);
1472                         if (!pid) {
1473                                 /* if pid is null, set the self_pid */
1474                                 pid = getpid();
1475                         }
1476
1477                         _tbm_util_get_appname_from_pid(pid, app_name);
1478                         _tbm_util_get_appname_brief(app_name);
1479
1480                         snprintf(data, 255, "%-2d  %-9p    %-4d  %-5d  %-6d  %-3d  %-6d   %-2d   %-2d    %-3d  %-8s  %-15s",
1481                                   ++surf_cnt,
1482                                   surf,
1483                                   surf->refcnt,
1484                                   surf->info.width,
1485                                   surf->info.height,
1486                                   surf->info.bpp,
1487                                   surf->info.size / 1024,
1488                                   surf->num_bos,
1489                                   surf->num_planes,
1490                                   surf->flags,
1491                                   _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1492                                   app_name);
1493
1494                         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1495                                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1496                                         strncat(data, "  ", 2);
1497
1498                                         value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1499                                         if (value)
1500                                                 strncat(data, value, strlen(value) + 1);
1501                                         else
1502                                                 strncat(data, "none", strlen("none") + 1);
1503                                 }
1504                         }
1505                         TBM_DEBUG("%s\n", data);
1506
1507                         for (i = 0; i < surf->num_bos; i++) {
1508                                 TBM_DEBUG(" bo:%-12p  %-26d%-10d\n",
1509                                           surf->bos[i],
1510                                           surf->bos[i]->ref_cnt,
1511                                           tbm_bo_size(surf->bos[i]) / 1024);
1512                         }
1513
1514                         memset(app_name, 0x0, 255 * sizeof(char));
1515                 }
1516         } else {
1517                 TBM_DEBUG("no tbm_surfaces.\n");
1518         }
1519         TBM_DEBUG("\n");
1520
1521         TBM_DEBUG("[tbm_bo information]\n");
1522         TBM_DEBUG("no  bo          refcnt  size    lock_cnt  map_cnt  flags  surface\n");
1523
1524         /* show the tbm_bo information in bo_list */
1525         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1526                 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1527                         TBM_DEBUG("%-4d%-11p   %-4d  %-6d     %-5d     %-4d    %-3d  %-11p\n",
1528                                   ++bo_cnt,
1529                                   bo,
1530                                   bo->ref_cnt,
1531                                   tbm_bo_size(bo) / 1024,
1532                                   bo->lock_cnt,
1533                                   bo->map_cnt,
1534                                   bo->flags,
1535                                   bo->surface);
1536                 }
1537         } else {
1538                 TBM_DEBUG("no tbm_bos.\n");
1539         }
1540         TBM_DEBUG("\n");
1541
1542         TBM_DEBUG("===============================================================\n");
1543
1544         _tbm_bufmgr_mutex_unlock();
1545 }
1546
1547 void
1548 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1549 {
1550         _tbm_bufmgr_mutex_lock();
1551
1552         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1553         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1554
1555 #ifdef TRACE
1556         TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1557         bTrace = onoff;
1558 #endif
1559
1560         _tbm_bufmgr_mutex_unlock();
1561 }
1562
1563 int
1564 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1565 {
1566         int w = 0, h = 0;
1567
1568         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1569         TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1570
1571         pthread_mutex_lock(&gLock);
1572
1573         if (onoff == 1) {
1574                 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1575                         TBM_LOG_I("No tbm_surface.\n");
1576                         pthread_mutex_unlock(&gLock);
1577                         return 0;
1578                 }
1579
1580                 tbm_surface_internal_dump_start(path, w, h, count);
1581                 b_dump_queue = 1;
1582         } else if (onoff == 0) {
1583                 tbm_surface_internal_dump_end();
1584                 b_dump_queue = 0;
1585         } else {
1586                 pthread_mutex_unlock(&gLock);
1587                 return 0;
1588         }
1589
1590         pthread_mutex_unlock(&gLock);
1591         return 1;
1592 }
1593
1594 int
1595 tbm_bufmgr_debug_dump_all(char *path)
1596 {
1597         int w = 0, h = 0, count = 0;
1598         tbm_surface_h surface = NULL, tmp = NULL;
1599
1600         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1601         TBM_LOG_D("path=%s\n", path);
1602
1603         pthread_mutex_lock(&gLock);
1604
1605         count = _tbm_util_get_max_surface_size(&w, &h);
1606         if (count == 0) {
1607                 TBM_LOG_I("No tbm_surface.\n");
1608                 pthread_mutex_unlock(&gLock);
1609                 return 1;
1610         }
1611
1612         tbm_surface_internal_dump_start(path, w, h, count);
1613
1614         LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1615                 tbm_surface_internal_dump_buffer(surface, "dump_all");
1616         }
1617
1618         tbm_surface_internal_dump_end();
1619
1620         pthread_mutex_unlock(&gLock);
1621
1622         return 1;
1623 }
1624
1625 /* internal function */
1626 tbm_bufmgr
1627 _tbm_bufmgr_get_bufmgr(void)
1628 {
1629         return gBufMgr;
1630 }
1631
1632 int
1633 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1634 {
1635         _tbm_bufmgr_mutex_lock();
1636
1637         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1638         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1639
1640         bo->surface = surface;
1641
1642         _tbm_bufmgr_mutex_unlock();
1643
1644         return 1;
1645 }
1646
1647 int
1648 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1649 {
1650         int ret;
1651
1652         _tbm_bufmgr_mutex_lock();
1653
1654         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1655
1656         if (!bufmgr->backend->bufmgr_bind_native_display) {
1657                 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1658                 _tbm_bufmgr_mutex_unlock();
1659                 return 1;
1660         }
1661
1662         ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1663         if (!ret) {
1664                 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1665                 _tbm_bufmgr_mutex_unlock();
1666                 return 0;
1667         }
1668
1669         TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1670
1671         _tbm_bufmgr_mutex_unlock();
1672
1673         return 1;
1674 }
1675 /* LCOV_EXCL_STOP */