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