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