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