add _tbm_bufmgr_get_bufmgr as internal function
[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         pthread_mutex_unlock(&gLock);
638         return gBufMgr;
639 }
640
641 void
642 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
643 {
644         TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
645
646         tbm_bo bo = NULL;
647         tbm_bo tmp = NULL;
648
649         tbm_surface_h surf = NULL;
650         tbm_surface_h tmp_surf = NULL;
651
652         pthread_mutex_lock(&gLock);
653
654         if (!gBufMgr) {
655                 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
656                 pthread_mutex_unlock(&gLock);
657                 return;
658         }
659
660         bufmgr->ref_count--;
661         if (bufmgr->ref_count > 0) {
662                 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
663                 pthread_mutex_unlock(&gLock);
664                 return;
665         }
666
667         /* destroy bo_list */
668         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
669                 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
670                         TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
671                                 bo, bo->ref_cnt);
672                         bo->ref_cnt = 1;
673                         tbm_bo_unref(bo);
674                 }
675         }
676
677         /* destroy surf_list */
678         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
679                 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
680                         TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
681                                 surf, surf->refcnt);
682                         tbm_surface_destroy(surf);
683                 }
684         }
685
686         /* destroy bufmgr priv */
687         bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
688         bufmgr->backend->priv = NULL;
689         tbm_backend_free(bufmgr->backend);
690         bufmgr->backend = NULL;
691
692         pthread_mutex_destroy(&bufmgr->lock);
693
694         TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
695
696         dlclose(bufmgr->module_data);
697
698         if (bufmgr->fd > 0)
699                 close(bufmgr->fd);
700
701         free(bufmgr);
702         bufmgr = NULL;
703         gBufMgr = NULL;
704
705         pthread_mutex_unlock(&gLock);
706 }
707
708 int
709 tbm_bo_size(tbm_bo bo)
710 {
711         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
712
713         tbm_bufmgr bufmgr = bo->bufmgr;
714         int size;
715
716         pthread_mutex_lock(&bufmgr->lock);
717
718         size = bufmgr->backend->bo_size(bo);
719
720         TBM_TRACE("bo(%p) size(%d)\n", bo, size);
721
722         pthread_mutex_unlock(&bufmgr->lock);
723
724         return size;
725 }
726
727 tbm_bo
728 tbm_bo_ref(tbm_bo bo)
729 {
730         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
731
732         tbm_bufmgr bufmgr = bo->bufmgr;
733
734         pthread_mutex_lock(&bufmgr->lock);
735
736         _tbm_bo_ref(bo);
737
738         TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
739
740         pthread_mutex_unlock(&bufmgr->lock);
741
742         return bo;
743 }
744
745 void
746 tbm_bo_unref(tbm_bo bo)
747 {
748         TBM_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
749
750         tbm_bufmgr bufmgr = bo->bufmgr;
751
752         pthread_mutex_lock(&bufmgr->lock);
753
754         TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
755
756         _tbm_bo_unref(bo);
757
758         pthread_mutex_unlock(&bufmgr->lock);
759 }
760
761 tbm_bo
762 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
763 {
764         TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr) && (size > 0), NULL);
765
766         tbm_bo bo = NULL;
767         void *bo_priv = NULL;
768
769         bo = calloc(1, sizeof(struct _tbm_bo));
770         if (!bo) {
771                 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
772                 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
773                 return NULL;
774         }
775
776         _tbm_util_check_bo_cnt(bufmgr);
777         bufmgr->bo_cnt++;
778
779         bo->bufmgr = bufmgr;
780
781         pthread_mutex_lock(&bufmgr->lock);
782
783         bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
784         if (!bo_priv) {
785                 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
786                 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
787                 free(bo);
788                 pthread_mutex_unlock(&bufmgr->lock);
789                 return NULL;
790         }
791
792         bo->ref_cnt = 1;
793         bo->flags = flags;
794         bo->priv = bo_priv;
795
796         TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
797
798         LIST_INITHEAD(&bo->user_data_list);
799
800         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
801
802         pthread_mutex_unlock(&bufmgr->lock);
803
804         return bo;
805 }
806
807 tbm_bo
808 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
809 {
810         TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
811
812         tbm_bo bo = NULL;
813         tbm_bo bo2 = NULL;
814         tbm_bo tmp = NULL;
815         void *bo_priv = NULL;
816
817         _tbm_util_check_bo_cnt(bufmgr);
818
819         pthread_mutex_lock(&bufmgr->lock);
820
821         bo = calloc(1, sizeof(struct _tbm_bo));
822         if (!bo) {
823                 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
824                 pthread_mutex_unlock(&bufmgr->lock);
825                 return NULL;
826         }
827
828         bufmgr->bo_cnt++;
829
830         bo->bufmgr = bufmgr;
831
832         bo_priv = bufmgr->backend->bo_import(bo, key);
833         if (!bo_priv) {
834                 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
835                 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
836                 free(bo);
837                 pthread_mutex_unlock(&bufmgr->lock);
838                 return NULL;
839         }
840
841         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
842                 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
843                         if (bo2->priv == bo_priv) {
844                                 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
845                                                         bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
846                                 bo2->ref_cnt++;
847                                 free(bo);
848                                 pthread_mutex_unlock(&bufmgr->lock);
849                                 return bo2;
850                         }
851                 }
852         }
853
854         bo->ref_cnt = 1;
855         bo->priv = bo_priv;
856
857         if (bufmgr->backend->bo_get_flags)
858                 bo->flags = bufmgr->backend->bo_get_flags(bo);
859         else
860                 bo->flags = TBM_BO_DEFAULT;
861
862         TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
863                           bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
864
865         LIST_INITHEAD(&bo->user_data_list);
866
867         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
868
869         pthread_mutex_unlock(&bufmgr->lock);
870
871         return bo;
872 }
873
874 tbm_bo
875 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
876 {
877         TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
878
879         tbm_bo bo = NULL;
880         tbm_bo bo2 = NULL;
881         tbm_bo tmp = NULL;
882         void *bo_priv = NULL;
883
884         _tbm_util_check_bo_cnt(bufmgr);
885
886         pthread_mutex_lock(&bufmgr->lock);
887
888         bo = calloc(1, sizeof(struct _tbm_bo));
889         if (!bo) {
890                 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
891                 pthread_mutex_unlock(&bufmgr->lock);
892                 return NULL;
893         }
894
895         bufmgr->bo_cnt++;
896
897         bo->bufmgr = bufmgr;
898
899         bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
900         if (!bo_priv) {
901                 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
902                 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
903                 free(bo);
904                 pthread_mutex_unlock(&bufmgr->lock);
905                 return NULL;
906         }
907
908         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
909                 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
910                         if (bo2->priv == bo_priv) {
911                                 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
912                                                         bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
913                                 bo2->ref_cnt++;
914                                 free(bo);
915                                 pthread_mutex_unlock(&bufmgr->lock);
916                                 return bo2;
917                         }
918                 }
919         }
920
921         bo->ref_cnt = 1;
922         bo->priv = bo_priv;
923
924         if (bufmgr->backend->bo_get_flags)
925                 bo->flags = bufmgr->backend->bo_get_flags(bo);
926         else
927                 bo->flags = TBM_BO_DEFAULT;
928
929         TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
930                                 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
931
932         LIST_INITHEAD(&bo->user_data_list);
933
934         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
935
936         pthread_mutex_unlock(&bufmgr->lock);
937
938         return bo;
939 }
940
941 tbm_key
942 tbm_bo_export(tbm_bo bo)
943 {
944         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
945
946         tbm_bufmgr bufmgr;
947         tbm_key ret;
948
949         bufmgr = bo->bufmgr;
950
951         pthread_mutex_lock(&bufmgr->lock);
952
953         ret = bufmgr->backend->bo_export(bo);
954         if (!ret) {
955                 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
956                 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
957                 pthread_mutex_unlock(&bufmgr->lock);
958                 return ret;
959         }
960
961         TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
962
963         pthread_mutex_unlock(&bufmgr->lock);
964
965         return ret;
966 }
967
968 tbm_fd
969 tbm_bo_export_fd(tbm_bo bo)
970 {
971         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
972
973         tbm_bufmgr bufmgr;
974         int ret;
975
976         bufmgr = bo->bufmgr;
977
978         pthread_mutex_lock(&bufmgr->lock);
979
980         ret = bufmgr->backend->bo_export_fd(bo);
981         if (ret < 0) {
982                 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
983                 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
984                 pthread_mutex_unlock(&bufmgr->lock);
985                 return ret;
986         }
987
988         TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
989
990         pthread_mutex_unlock(&bufmgr->lock);
991
992         return ret;
993 }
994
995 tbm_bo_handle
996 tbm_bo_get_handle(tbm_bo bo, int device)
997 {
998         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
999
1000         tbm_bufmgr bufmgr;
1001         tbm_bo_handle bo_handle;
1002
1003         bufmgr = bo->bufmgr;
1004
1005         pthread_mutex_lock(&bufmgr->lock);
1006
1007         bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1008         if (bo_handle.ptr == NULL) {
1009                 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1010                 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1011                 pthread_mutex_unlock(&bufmgr->lock);
1012                 return (tbm_bo_handle) NULL;
1013         }
1014
1015         TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1016
1017         pthread_mutex_unlock(&bufmgr->lock);
1018
1019         return bo_handle;
1020 }
1021
1022 tbm_bo_handle
1023 tbm_bo_map(tbm_bo bo, int device, int opt)
1024 {
1025         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) 0);
1026
1027         tbm_bufmgr bufmgr;
1028         tbm_bo_handle bo_handle;
1029
1030         bufmgr = bo->bufmgr;
1031
1032         pthread_mutex_lock(&bufmgr->lock);
1033
1034         if (!_tbm_bo_lock(bo, device, opt)) {
1035                 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1036                 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1037                 pthread_mutex_unlock(&bufmgr->lock);
1038                 return (tbm_bo_handle) NULL;
1039         }
1040
1041         bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1042         if (bo_handle.ptr == NULL) {
1043                 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1044                 TBM_TRACE("error: fail to map bo:%p\n", bo);
1045                 _tbm_bo_unlock(bo);
1046                 pthread_mutex_unlock(&bufmgr->lock);
1047                 return (tbm_bo_handle) NULL;
1048         }
1049
1050         /* increase the map_count */
1051         bo->map_cnt++;
1052
1053         TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1054
1055         pthread_mutex_unlock(&bufmgr->lock);
1056
1057         return bo_handle;
1058 }
1059
1060 int
1061 tbm_bo_unmap(tbm_bo bo)
1062 {
1063         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1064
1065         tbm_bufmgr bufmgr;
1066         int ret;
1067
1068         bufmgr = bo->bufmgr;
1069
1070         pthread_mutex_lock(&bufmgr->lock);
1071
1072         ret = bufmgr->backend->bo_unmap(bo);
1073         if (!ret) {
1074                 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1075                 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1076                 pthread_mutex_unlock(&bufmgr->lock);
1077                 return ret;
1078         }
1079
1080         /* decrease the map_count */
1081         bo->map_cnt--;
1082
1083         TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1084
1085         _tbm_bo_unlock(bo);
1086
1087         pthread_mutex_unlock(&bufmgr->lock);
1088
1089         return ret;
1090 }
1091
1092 int
1093 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1094 {
1095         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1096         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1097
1098         void *temp;
1099
1100         pthread_mutex_lock(&bo1->bufmgr->lock);
1101
1102         TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1103
1104         if (bo1->bufmgr->backend->bo_size(bo1) != bo2->bufmgr->backend->bo_size(bo2)) {
1105                 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1106                 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1107         pthread_mutex_unlock(&bo1->bufmgr->lock);
1108                 return 0;
1109         }
1110
1111         TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1112
1113         temp = bo1->priv;
1114         bo1->priv = bo2->priv;
1115         bo2->priv = temp;
1116
1117         pthread_mutex_unlock(&bo1->bufmgr->lock);
1118
1119         return 1;
1120 }
1121
1122 int
1123 tbm_bo_locked(tbm_bo bo)
1124 {
1125         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1126
1127         tbm_bufmgr bufmgr;
1128
1129         bufmgr = bo->bufmgr;
1130
1131         if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1132                 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1133                 return 0;
1134         }
1135
1136         pthread_mutex_lock(&bufmgr->lock);
1137
1138
1139         if (bo->lock_cnt > 0) {
1140                 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1141                 pthread_mutex_unlock(&bufmgr->lock);
1142                 return 1;
1143         }
1144
1145         TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1146         pthread_mutex_unlock(&bufmgr->lock);
1147
1148         return 0;
1149 }
1150
1151 int
1152 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1153                      tbm_data_free data_free_func)
1154 {
1155         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1156
1157         tbm_user_data *data;
1158
1159         /* check if the data according to the key exist if so, return false. */
1160         data = user_data_lookup(&bo->user_data_list, key);
1161         if (data) {
1162                 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1163                 return 0;
1164         }
1165
1166         data = user_data_create(key, data_free_func);
1167         if (!data) {
1168                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1169                 return 0;
1170         }
1171
1172         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1173
1174         LIST_ADD(&data->item_link, &bo->user_data_list);
1175
1176         return 1;
1177 }
1178
1179 int
1180 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1181 {
1182         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1183
1184         tbm_user_data *old_data;
1185
1186         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1187                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1188                 return 0;
1189         }
1190
1191         old_data = user_data_lookup(&bo->user_data_list, key);
1192         if (!old_data) {
1193                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1194                 return 0;
1195         }
1196
1197         if (old_data->data && old_data->free_func)
1198                 old_data->free_func(old_data->data);
1199
1200         old_data->data = data;
1201
1202         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1203
1204         return 1;
1205 }
1206
1207 int
1208 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1209 {
1210         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1211
1212         tbm_user_data *old_data;
1213
1214         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1215                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1216                 return 0;
1217         }
1218
1219         old_data = user_data_lookup(&bo->user_data_list, key);
1220         if (!old_data) {
1221                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1222                 *data = NULL;
1223                 return 0;
1224         }
1225
1226         *data = old_data->data;
1227
1228         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1229
1230         return 1;
1231 }
1232
1233 int
1234 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1235 {
1236         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1237
1238         tbm_user_data *old_data = (void *)0;
1239
1240         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1241                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1242                 return 0;
1243         }
1244
1245         old_data = user_data_lookup(&bo->user_data_list, key);
1246         if (!old_data) {
1247                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1248                 return 0;
1249         }
1250
1251         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1252
1253         user_data_delete(old_data);
1254
1255         return 1;
1256 }
1257
1258 unsigned int
1259 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1260 {
1261         TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1262
1263         TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1264
1265         return bufmgr->capabilities;
1266 }
1267
1268 int
1269 tbm_bo_get_flags(tbm_bo bo)
1270 {
1271         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1272
1273         TBM_TRACE("bo(%p)\n", bo);
1274
1275         return bo->flags;
1276 }
1277
1278 /* LCOV_EXCL_START */
1279 tbm_error_e
1280 tbm_get_last_error(void)
1281 {
1282         return tbm_last_error;
1283 }
1284
1285 void
1286 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1287 {
1288         TBM_RETURN_IF_FAIL(bufmgr != NULL);
1289         tbm_bo bo = NULL, tmp_bo = NULL;
1290         int bo_cnt = 0;
1291
1292         tbm_surface_h surf = NULL, tmp_surf = NULL;
1293         int surf_cnt = 0;
1294         int i;
1295         char app_name[255] = {0,};
1296         unsigned int pid = 0;
1297
1298         pthread_mutex_lock(&gLock);
1299
1300         TBM_DEBUG("\n");
1301         _tbm_util_get_appname_from_pid(getpid(), app_name);
1302         _tbm_util_get_appname_brief(app_name);
1303         TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1304                   app_name, getpid());
1305         memset(app_name, 0x0, 255 * sizeof(char));
1306
1307         TBM_DEBUG("[tbm_surface information]\n");
1308         TBM_DEBUG("no  surface              refcnt  width  height  bpp  size      num_bos num_planes flags format              app_name\n");
1309         /* show the tbm_surface information in surf_list */
1310         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1311                 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1312                         pid = _tbm_surface_internal_get_debug_pid(surf);
1313                         if (!pid) {
1314                                 /* if pid is null, set the self_pid */
1315                                 pid = getpid();
1316                         }
1317
1318                         _tbm_util_get_appname_from_pid(pid, app_name);
1319                         _tbm_util_get_appname_brief(app_name);
1320
1321                         TBM_DEBUG("%-4d%-23p%-6d%-7d%-8d%-5d%-12d%-10d%-9d%-4d%-20s%s\n",
1322                                   ++surf_cnt,
1323                                   surf,
1324                                   surf->refcnt,
1325                                   surf->info.width,
1326                                   surf->info.height,
1327                                   surf->info.bpp,
1328                                   surf->info.size / 1024,
1329                                   surf->num_bos,
1330                                   surf->num_planes,
1331                                   surf->flags,
1332                                   _tbm_surface_internal_format_to_str(surf->info.format),
1333                                   app_name);
1334
1335                         for (i = 0; i < surf->num_bos; i++) {
1336                                 TBM_DEBUG(" bo:%-12p  %-26d%-10d\n",
1337                                           surf->bos[i],
1338                                           surf->bos[i]->ref_cnt,
1339                                           tbm_bo_size(surf->bos[i]) / 1024);
1340                         }
1341
1342                         memset(app_name, 0x0, 255 * sizeof(char));
1343                 }
1344         } else {
1345                 TBM_DEBUG("no tbm_surfaces.\n");
1346         }
1347         TBM_DEBUG("\n");
1348
1349         TBM_DEBUG("[tbm_bo information]\n");
1350         TBM_DEBUG("no  bo                   refcnt  size     lock_cnt map_cnt flags surface\n");
1351
1352         /* show the tbm_bo information in bo_list */
1353         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1354                 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1355                         TBM_DEBUG("%-4d%-11p   %-6d%-12d%-9d%-9d%-4d%-11p\n",
1356                                   ++bo_cnt,
1357                                   bo,
1358                                   bo->ref_cnt,
1359                                   tbm_bo_size(bo) / 1024,
1360                                   bo->lock_cnt,
1361                                   bo->map_cnt,
1362                                   bo->flags,
1363                                   bo->surface);
1364                 }
1365         } else {
1366                 TBM_DEBUG("no tbm_bos.\n");
1367         }
1368         TBM_DEBUG("\n");
1369
1370         TBM_DEBUG("===============================================================\n");
1371
1372         pthread_mutex_unlock(&gLock);
1373
1374 }
1375
1376 void
1377 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1378 {
1379 #ifdef TRACE
1380         TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1381         bTrace = onoff;
1382 #endif
1383 }
1384
1385 /* internal function */
1386 tbm_bufmgr
1387 _tbm_bufmgr_get_bufmgr(void)
1388 {
1389         return gBufMgr;
1390 }
1391
1392 int
1393 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1394 {
1395         TBM_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1396
1397         bo->surface = surface;
1398
1399         return 1;
1400 }
1401
1402 int
1403 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1404 {
1405         TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
1406
1407         int ret;
1408
1409         pthread_mutex_lock(&bufmgr->lock);
1410
1411         if (!bufmgr->backend->bufmgr_bind_native_display) {
1412                 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1413                 pthread_mutex_unlock(&bufmgr->lock);
1414                 return 1;
1415         }
1416
1417         ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1418         if (!ret) {
1419                 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1420                 pthread_mutex_unlock(&bufmgr->lock);
1421                 return 0;
1422         }
1423
1424         TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1425
1426         pthread_mutex_unlock(&bufmgr->lock);
1427
1428         return 1;
1429 }
1430 /* LCOV_EXCL_STOP */