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