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