bufmgr: add tbm_bufmgr_get()
[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 #include <sys/resource.h>
40
41 #ifdef DEBUG
42 int bDebug;
43 #endif
44
45 #ifdef TRACE
46 int bTrace;
47 #endif
48
49 #ifdef HAVE_DLOG
50 int bDlog;
51 #endif
52
53 tbm_bufmgr gBufMgr;
54 int b_dump_queue;
55
56 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
57 static pthread_mutex_t tbm_bufmgr_lock = PTHREAD_MUTEX_INITIALIZER;
58 static double scale_factor = 0;
59 static void _tbm_bufmgr_mutex_unlock(void);
60
61 //#define TBM_BUFMGR_INIT_TIME
62
63 #define PREFIX_LIB    "libtbm_"
64 #define SUFFIX_LIB    ".so"
65 #define DEFAULT_LIB   PREFIX_LIB"default"SUFFIX_LIB
66
67 /* values to indicate unspecified fields in XF86ModReqInfo. */
68 #define MAJOR_UNSPEC      0xFF
69 #define MINOR_UNSPEC      0xFF
70 #define PATCH_UNSPEC      0xFFFF
71 #define ABI_VERS_UNSPEC   0xFFFFFFFF
72
73 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
74                         ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
75 #define GET_MODULE_MAJOR_VERSION(vers)    (((vers) >> 24) & 0xFF)
76 #define GET_MODULE_MINOR_VERSION(vers)    (((vers) >> 16) & 0xFF)
77 #define GET_MODULE_PATCHLEVEL(vers)    ((vers) & 0xFFFF)
78
79 #define MAX_SIZE_N(dest)        (sizeof(dest) - strlen(dest) - 1)
80
81 /* check condition */
82 #define TBM_BUFMGR_RETURN_IF_FAIL(cond) {\
83         if (!(cond)) {\
84                 TBM_LOG_E("'%s' failed.\n", #cond);\
85                 _tbm_bufmgr_mutex_unlock();\
86                 return;\
87         } \
88 }
89
90 #define TBM_BUFMGR_RETURN_VAL_IF_FAIL(cond, val) {\
91         if (!(cond)) {\
92                 TBM_LOG_E("'%s' failed.\n", #cond);\
93                 _tbm_bufmgr_mutex_unlock();\
94                 return val;\
95         } \
96 }
97
98 /* LCOV_EXCL_START */
99 static bool
100 _tbm_bufmgr_mutex_init(void)
101 {
102         static bool tbm_bufmgr_mutex_init = false;
103
104         if (tbm_bufmgr_mutex_init)
105                 return true;
106
107         if (pthread_mutex_init(&tbm_bufmgr_lock, NULL)) {
108                 TBM_LOG_E("fail: Cannot pthread_mutex_init for tbm_bufmgr_lock.\n");
109                 return false;
110         }
111
112         tbm_bufmgr_mutex_init = true;
113
114         return true;
115 }
116
117 static void
118 _tbm_bufmgr_mutex_lock(void)
119 {
120         if (!_tbm_bufmgr_mutex_init()) {
121                 TBM_LOG_E("fail: _tbm_bufmgr_mutex_init()\n");
122                 return;
123         }
124
125         pthread_mutex_lock(&tbm_bufmgr_lock);
126 }
127
128 static void
129 _tbm_bufmgr_mutex_unlock(void)
130 {
131         pthread_mutex_unlock(&tbm_bufmgr_lock);
132 }
133
134 static int
135 _tbm_util_get_max_surface_size(int *w, int *h)
136 {
137         tbm_surface_info_s info;
138         tbm_surface_h surface = NULL;
139         int count = 0;
140
141         *w = 0;
142         *h = 0;
143
144         if (gBufMgr == NULL || LIST_IS_EMPTY(&gBufMgr->surf_list))
145                 return count;
146
147         LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link) {
148                 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
149                         count++;
150                         if (*w < info.width)
151                                 *w = info.width;
152                         if (*h < info.height)
153                                 *h = info.height;
154                 }
155         }
156
157         return count;
158 }
159
160 static void
161 _tbm_util_get_appname_brief(char *brief)
162 {
163         char delim[] = "/";
164         char *token = NULL;
165         char temp[255] = {0,};
166         char *saveptr = NULL;
167
168         token = strtok_r(brief, delim, &saveptr);
169
170         while (token != NULL) {
171                 memset(temp, 0x00, 255 * sizeof(char));
172                 strncpy(temp, token, 254 * sizeof(char));
173                 token = strtok_r(NULL, delim, &saveptr);
174         }
175
176         snprintf(brief, sizeof(temp), "%s", temp);
177 }
178
179 static void
180 _tbm_util_get_appname_from_pid(long pid, char *str)
181 {
182         char fn_cmdline[255] = {0, }, cmdline[255];
183         FILE *fp;
184         int len;
185
186         snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", pid);
187
188         fp = fopen(fn_cmdline, "r");
189         if (fp == 0) {
190                 TBM_LOG_E("cannot file open %s\n", fn_cmdline);
191                 return;
192         }
193
194         if (!fgets(cmdline, 255, fp)) {
195                 TBM_LOG_E("fail to get appname for pid(%ld)\n", pid);
196                 fclose(fp);
197                 return;
198         }
199
200         fclose(fp);
201
202         len = strlen(cmdline);
203         if (len < 1)
204                 memset(cmdline, 0x00, 255);
205         else
206                 cmdline[len] = 0;
207
208         snprintf(str, sizeof(cmdline), "%s", cmdline);
209 }
210
211 static int
212 _check_version(TBMModuleVersionInfo *data)
213 {
214         int abimaj, abimin;
215         int vermaj, vermin;
216
217         abimaj = GET_ABI_MAJOR(data->abiversion);
218         abimin = GET_ABI_MINOR(data->abiversion);
219
220         TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
221             data->modname ? data->modname : "UNKNOWN!",
222             data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
223
224         vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
225         vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
226
227         TBM_DBG("TBM ABI version %d.%d\n",
228             vermaj, vermin);
229
230         if (abimaj != vermaj) {
231                 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
232                         abimaj, vermaj);
233                 return 0;
234         } else if (abimin > vermin) {
235                 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
236                         abimin, vermin);
237                 return 0;
238         }
239
240         return 1;
241 }
242
243 static int
244 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
245 {
246         char path[PATH_MAX] = {0, };
247         TBMModuleVersionInfo *vers;
248         TBMModuleData *initdata;
249         ModuleInitProc init;
250         void *module_data;
251
252         snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
253
254         module_data = dlopen(path, RTLD_LAZY);
255         if (!module_data) {
256                 TBM_LOG_E("failed to load module: %s(%s)\n", dlerror(), file);
257                 return 0;
258         }
259
260         initdata = dlsym(module_data, "tbmModuleData");
261         if (!initdata) {
262                 TBM_LOG_E("Error: module does not have data object.\n");
263                 goto err;
264         }
265
266         vers = initdata->vers;
267         if (!vers) {
268                 TBM_LOG_E("Error: module does not supply version information.\n");
269                 goto err;
270         }
271
272         init = initdata->init;
273         if (!init) {
274                 TBM_LOG_E("Error: module does not supply init symbol.\n");
275                 goto err;
276         }
277
278         if (!_check_version(vers)) {
279                 TBM_LOG_E("Fail to check version.\n");
280                 goto err;
281         }
282
283         if (!init(bufmgr, fd)) {
284                 TBM_LOG_E("Fail to init module(%s)\n", file);
285                 goto err;
286         }
287
288         if (!bufmgr->backend || !bufmgr->backend->priv) {
289                 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n", file);
290                 goto err;
291         }
292
293         bufmgr->module_data = module_data;
294
295         TBM_DBG("Success to load module(%s)\n", file);
296
297         return 1;
298
299 err:
300         dlclose(module_data);
301         return 0;
302 }
303
304 static int
305 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
306 {
307         struct dirent **namelist;
308         int ret = 0, n;
309
310         /* load bufmgr priv from default lib */
311         if (_tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB))
312                 return 1;
313
314         /* load bufmgr priv from configured path */
315         n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
316         if (n < 0) {
317                 TBM_LOG_E("no files : %s\n", BUFMGR_MODULE_DIR);
318                 return 0;
319         }
320
321         while (n--) {
322                 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
323                         const char *p = strstr(namelist[n]->d_name, SUFFIX_LIB);
324
325                         if (p && !strcmp(p, SUFFIX_LIB))
326                                 ret = _tbm_bufmgr_load_module(bufmgr, fd,
327                                                         namelist[n]->d_name);
328                 }
329
330                 free(namelist[n]);
331         }
332
333         free(namelist);
334
335         return ret;
336 }
337 /* LCOV_EXCL_STOP */
338
339 static tbm_bufmgr
340 _tbm_bufmgr_init(int fd, int server)
341 {
342 #ifdef TBM_BUFMGR_INIT_TIME
343         struct timeval start_tv, end_tv;
344 #endif
345         char *env;
346
347 #ifdef TBM_BUFMGR_INIT_TIME
348         /* get the start tv */
349         gettimeofday(&start_tv, NULL);
350 #endif
351
352         /* LCOV_EXCL_START */
353 #ifdef HAVE_DLOG
354         env = getenv("TBM_DLOG");
355         if (env) {
356                 bDlog = atoi(env);
357                 TBM_LOG_D("TBM_DLOG=%s\n", env);
358         } else
359                 bDlog = 1;
360 #endif
361
362 #ifdef DEBUG
363         env = getenv("TBM_DEBUG");
364         if (env) {
365                 bDebug = atoi(env);
366                 TBM_LOG_D("TBM_DEBUG=%s\n", env);
367         } else
368                 bDebug = 0;
369 #endif
370
371 #ifdef TRACE
372         env = getenv("TBM_TRACE");
373         if (env) {
374                 bTrace = atoi(env);
375                 TBM_LOG_D("TBM_TRACE=%s\n", env);
376         } else
377                 bTrace = 0;
378 #endif
379
380         pthread_mutex_lock(&gLock);
381
382         if (fd >= 0) {
383                 TBM_LOG_W("!!!!!WARNING:: The tbm_bufmgr_init DOSE NOT use argument fd ANYMORE.\n");
384                 TBM_LOG_W("!!!!!WARNING:: IT WILL BE CHANGED like tbm_bufmgr_init(int fd) --> tbm_bufmgr_init(void).\n");
385         }
386
387
388         /* initialize buffer manager */
389         if (gBufMgr) {
390                 gBufMgr->ref_count++;
391                 TBM_TRACE("reuse  tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
392                 pthread_mutex_unlock(&gLock);
393                 return gBufMgr;
394         }
395
396         TBM_DBG("bufmgr init\n");
397
398         /* allocate bufmgr */
399         gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
400         if (!gBufMgr) {
401                 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
402                 pthread_mutex_unlock(&gLock);
403                 return NULL;
404         }
405
406         gBufMgr->fd = fd;
407
408         /* set the display_server flag before loading the backend module */
409         if (server) {
410                 TBM_LOG_I("The tbm_bufmgr(%p) is used by display server. Need to bind the native_display.\n", gBufMgr);
411                 gBufMgr->display_server = 1;
412         }
413
414         /* load bufmgr priv from env */
415         if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
416                 TBM_LOG_E("error : Fail to load bufmgr backend\n");
417                 free(gBufMgr);
418                 gBufMgr = NULL;
419                 pthread_mutex_unlock(&gLock);
420                 return NULL;
421
422         }
423         /* LCOV_EXCL_STOP */
424
425         /* log for tbm backend_flag */
426         TBM_DBG("backend flag:%x:", gBufMgr->backend->flags);
427         TBM_DBG("\n");
428
429         gBufMgr->ref_count = 1;
430
431         TBM_DBG("create tizen bufmgr:%p ref_count:%d\n",
432             gBufMgr, gBufMgr->ref_count);
433
434         /* setup the bo_lock_type */
435         env = getenv("BUFMGR_LOCK_TYPE");
436         if (env && !strcmp(env, "always"))
437                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS;
438         else if (env && !strcmp(env, "none"))
439                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_NEVER;
440         else if (env && !strcmp(env, "once"))
441                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ONCE;
442         else
443                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS;
444
445         TBM_DBG("BUFMGR_LOCK_TYPE=%s\n", env ? env : "default:once");
446
447         TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
448
449         /* intialize bo_list */
450         LIST_INITHEAD(&gBufMgr->bo_list);
451
452         /* intialize surf_list */
453         LIST_INITHEAD(&gBufMgr->surf_list);
454
455         /* intialize surf_queue_list */
456         LIST_INITHEAD(&gBufMgr->surf_queue_list);
457
458         /* intialize debug_key_list */
459         LIST_INITHEAD(&gBufMgr->debug_key_list);
460
461 #ifdef TBM_BUFMGR_INIT_TIME
462         /* get the end tv */
463         gettimeofday(&end_tv, NULL);
464         TBM_LOG_I("tbm_bufmgr_init time: %ld ms", ((end_tv.tv_sec * 1000 + end_tv.tv_usec / 1000) - (start_tv.tv_sec * 1000 + start_tv.tv_usec / 1000)));
465 #endif
466
467         pthread_mutex_unlock(&gLock);
468
469         return gBufMgr;
470 }
471
472 tbm_bufmgr
473 tbm_bufmgr_init(int fd)
474 {
475         tbm_bufmgr bufmgr;
476
477         bufmgr = _tbm_bufmgr_init(fd, 0);
478
479         return bufmgr;
480 }
481
482 void
483 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
484 {
485         TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
486
487         _tbm_bufmgr_mutex_lock();
488         pthread_mutex_lock(&gLock);
489
490         if (!gBufMgr) {
491                 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
492                 pthread_mutex_unlock(&gLock);
493                 _tbm_bufmgr_mutex_unlock();
494                 return;
495         }
496
497         bufmgr->ref_count--;
498         if (bufmgr->ref_count > 0) {
499                 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
500                 pthread_mutex_unlock(&gLock);
501                 _tbm_bufmgr_mutex_unlock();
502                 return;
503         }
504
505         /* destroy bo_list */
506         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
507                 tbm_bo bo = NULL, tmp;
508
509                 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
510                         TBM_LOG_E("Un-freed bo(%p, ref:%d)\n", bo, bo->ref_cnt);
511                         _tbm_bo_free(bo);
512                 }
513                 LIST_DELINIT(&bufmgr->bo_list);
514         }
515
516         /* destroy surf_list */
517         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
518                 tbm_surface_h surf = NULL, tmp;
519
520                 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &bufmgr->surf_list, item_link) {
521                         TBM_LOG_E("Un-freed surf(%p, ref:%d)\n", surf, surf->refcnt);
522                         tbm_surface_destroy(surf);
523                 }
524                 LIST_DELINIT(&bufmgr->surf_list);
525         }
526
527         /* destroy bufmgr priv */
528         bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
529         bufmgr->backend->priv = NULL;
530         tbm_backend_free(bufmgr->backend);
531         bufmgr->backend = NULL;
532
533         TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
534
535         dlclose(bufmgr->module_data);
536
537         if (bufmgr->fd > 0)
538                 close(bufmgr->fd);
539
540         free(bufmgr);
541         gBufMgr = NULL;
542
543         pthread_mutex_unlock(&gLock);
544         _tbm_bufmgr_mutex_unlock();
545 }
546
547 unsigned int
548 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
549 {
550         unsigned int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
551
552         _tbm_bufmgr_mutex_lock();
553
554         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
555         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
556
557         TBM_TRACE("tbm_bufmgr(%p) capability(%u)\n", bufmgr, bufmgr->capabilities);
558
559         capabilities = bufmgr->capabilities;
560
561         _tbm_bufmgr_mutex_unlock();
562
563         return capabilities;
564 }
565
566 /* LCOV_EXCL_START */
567 char *
568 tbm_bufmgr_debug_tbm_info_get(tbm_bufmgr bufmgr)
569 {
570         char app_name[255] = {0,}, title[512] = {0,};
571         tbm_surface_debug_data *debug_old_data = NULL;
572         char *str;
573         int len = 1024*4;
574         int c = 0;
575
576         pthread_mutex_lock(&gLock);
577
578         if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
579                 TBM_LOG_E("invalid bufmgr\n");
580                 pthread_mutex_unlock(&gLock);
581                 return NULL;
582         }
583
584         str = malloc(len);
585         if (!str) {
586                 TBM_LOG_E("Fail to allocate the string.\n");
587                 pthread_mutex_unlock(&gLock);
588                 return NULL;
589         }
590
591         TBM_SNRPRINTF(str, len, c, "\n");
592         _tbm_util_get_appname_from_pid(getpid(), app_name);
593         _tbm_util_get_appname_brief(app_name);
594         TBM_SNRPRINTF(str, len, c, "============TBM DEBUG: %s(%d)===========================\n",
595                   app_name, getpid());
596
597         snprintf(title, 255, "%s", "no  surface     refcnt  width  height  bpp  size    n_b  n_p  flags  format    app_name       ");
598
599         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
600                 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
601                         strncat(title, "  ", MAX_SIZE_N(title));
602                         strncat(title, debug_old_data->key, MAX_SIZE_N(title));
603                 }
604         }
605
606         TBM_SNRPRINTF(str, len, c, "[tbm_surface information]\n");
607         TBM_SNRPRINTF(str, len, c, "%s\n", title);
608
609         /* show the tbm_surface information in surf_list */
610         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
611                 tbm_surface_h surf = NULL;
612                 int surf_cnt = 0;
613
614                 LIST_FOR_EACH_ENTRY(surf, &bufmgr->surf_list, item_link) {
615                         char data[512] = {0,};
616                         unsigned int pid;
617                         int i;
618
619                         pid = _tbm_surface_internal_get_debug_pid(surf);
620                         if (!pid) {
621                                 /* if pid is null, set the self_pid */
622                                 pid = getpid();
623                         }
624
625                         memset(app_name, 0x0, 255 * sizeof(char));
626                         _tbm_util_get_appname_from_pid(pid, app_name);
627                         _tbm_util_get_appname_brief(app_name);
628
629                         snprintf(data, 255, "%-2d  %-9p    %-4d  %-5u  %-6u  %-3u  %-6u   %-2d   %-2d    %-3d  %-8s  %-15s",
630                                   ++surf_cnt,
631                                   surf,
632                                   surf->refcnt,
633                                   surf->info.width,
634                                   surf->info.height,
635                                   surf->info.bpp,
636                                   surf->info.size / 1024,
637                                   surf->num_bos,
638                                   surf->num_planes,
639                                   surf->flags,
640                                   _tbm_surface_internal_format_to_str(surf->info.format) + 11,
641                                   app_name);
642
643                         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
644                                 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
645                                         char *value;
646
647                                         strncat(data, "  ", MAX_SIZE_N(title));
648
649                                         value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
650                                         if (value)
651                                                 strncat(data, value, MAX_SIZE_N(title));
652                                         else
653                                                 strncat(data, "none", MAX_SIZE_N(title));
654                                 }
655                         }
656                         TBM_SNRPRINTF(str, len, c, "%s\n", data);
657
658                         for (i = 0; i < surf->num_bos; i++) {
659                                 TBM_SNRPRINTF(str, len, c, " bo:%-12p  %-26d%-10d\n",
660                                           surf->bos[i],
661                                           surf->bos[i]->ref_cnt,
662                                           bufmgr->backend->bo_size(surf->bos[i]) / 1024);
663                         }
664                 }
665         } else
666                 TBM_SNRPRINTF(str, len, c, " no tbm_surfaces.\n");
667         TBM_SNRPRINTF(str, len, c, "\n");
668
669         TBM_SNRPRINTF(str, len, c, "[tbm_bo information]\n");
670         TBM_SNRPRINTF(str, len, c, "no  bo          refcnt  size    lock_cnt  map_cnt  flags  surface     name\n");
671
672         /* show the tbm_bo information in bo_list */
673         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
674                 int bo_cnt = 0;
675                 tbm_bo bo = NULL;
676
677                 LIST_FOR_EACH_ENTRY(bo, &bufmgr->bo_list, item_link) {
678                         TBM_SNRPRINTF(str, len, c, "%-4d%-11p   %-4d  %-6d     %-5d     %-4u    %-3d  %-11p  %-4d\n",
679                                   ++bo_cnt,
680                                   bo,
681                                   bo->ref_cnt,
682                                   bufmgr->backend->bo_size(bo) / 1024,
683                                   bo->lock_cnt,
684                                   bo->map_cnt,
685                                   bo->flags,
686                                   bo->surface,
687                                   bufmgr->backend->bo_export(bo));
688                 }
689         } else
690                 TBM_SNRPRINTF(str, len, c, "no tbm_bos.\n");
691         TBM_SNRPRINTF(str, len, c, "\n");
692
693         TBM_SNRPRINTF(str, len, c, "===============================================================\n");
694
695         pthread_mutex_unlock(&gLock);
696
697         return str;
698 }
699
700 void
701 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
702 {
703         char * str;
704         str = tbm_bufmgr_debug_tbm_info_get(bufmgr);
705         if (str) {
706                 TBM_DEBUG("     %s", str);
707                 free(str);
708         }
709 }
710
711 void
712 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
713 {
714         _tbm_bufmgr_mutex_lock();
715
716         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
717         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
718
719 #ifdef TRACE
720         TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
721         bTrace = onoff;
722 #endif
723
724         _tbm_bufmgr_mutex_unlock();
725 }
726
727 void
728 tbm_bufmgr_debug_dump_set_scale(double scale)
729 {
730         pthread_mutex_lock(&gLock);
731         scale_factor = scale;
732         pthread_mutex_unlock(&gLock);
733 }
734
735 int
736 tbm_bufmgr_debug_get_ref_count(void)
737 {
738         return (gBufMgr) ? gBufMgr->ref_count : 0;
739 }
740
741 int
742 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
743 {
744         pthread_mutex_lock(&gLock);
745
746         if (onoff == 0) {
747                 TBM_LOG_D("count=%d onoff=%d\n", count, onoff);
748                 b_dump_queue = 0;
749                 tbm_surface_internal_dump_end();
750         } else {
751                 int w, h;
752
753                 if (path == NULL) {
754                         TBM_LOG_E("path is null");
755                         pthread_mutex_unlock(&gLock);
756                         return 0;
757                 }
758                 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
759
760                 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
761                         TBM_LOG_E("Fail to get tbm_surface size.\n");
762                         pthread_mutex_unlock(&gLock);
763                         return 0;
764                 }
765
766                 tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
767                 scale_factor = 0;
768
769                 b_dump_queue = 1;
770         }
771
772         pthread_mutex_unlock(&gLock);
773         return 1;
774 }
775
776 int
777 tbm_bufmgr_debug_dump_all(char *path)
778 {
779         int w, h, count = 0;
780         tbm_surface_h surface = NULL;
781
782         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
783         TBM_LOG_D("path=%s\n", path);
784
785         pthread_mutex_lock(&gLock);
786
787         count = _tbm_util_get_max_surface_size(&w, &h);
788         if (count == 0) {
789                 TBM_LOG_E("No tbm_surface.\n");
790                 pthread_mutex_unlock(&gLock);
791                 return 1;
792         }
793
794         tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
795         scale_factor = 0;
796
797         LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link)
798                 tbm_surface_internal_dump_buffer(surface, "dump_all");
799
800         tbm_surface_internal_dump_end();
801
802         pthread_mutex_unlock(&gLock);
803
804         return 1;
805 }
806
807 /* internal function */
808 tbm_bufmgr
809 _tbm_bufmgr_get_bufmgr(void)
810 {
811         return gBufMgr;
812 }
813
814 int
815 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *native_display)
816 {
817         int ret;
818
819         _tbm_bufmgr_mutex_lock();
820
821         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
822
823         if (!bufmgr->backend->bufmgr_bind_native_display) {
824                 TBM_TRACE("skip: tbm_bufmgr(%p) native_display(%p)\n",
825                                 bufmgr, native_display);
826                 _tbm_bufmgr_mutex_unlock();
827                 return 1;
828         }
829
830         ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, native_display);
831         if (!ret) {
832                 TBM_LOG_E("error: tbm_bufmgr(%p) native_display(%p)\n",
833                                 bufmgr, native_display);
834                 _tbm_bufmgr_mutex_unlock();
835                 return 0;
836         }
837
838         TBM_TRACE("tbm_bufmgr(%p) native_display(%p)\n", bufmgr, native_display);
839
840         _tbm_bufmgr_mutex_unlock();
841
842         return 1;
843 }
844
845 tbm_bufmgr
846 tbm_bufmgr_server_init(void)
847 {
848         tbm_bufmgr bufmgr;
849
850         bufmgr = _tbm_bufmgr_init(-1, 1);
851
852         return bufmgr;
853 }
854
855 int
856 tbm_bufmgr_set_bo_lock_type(tbm_bufmgr bufmgr, tbm_bufmgr_bo_lock_type bo_lock_type)
857 {
858         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
859         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, 0);
860
861         gBufMgr->bo_lock_type = bo_lock_type;
862
863         TBM_LOG_I("The bo_lock_type of the bo is %d\n", bo_lock_type);
864
865         return 1;
866 }
867
868
869 int tbm_bufmgr_get_fd_limit(void)
870 {
871         struct rlimit lim;
872
873         if (getrlimit(RLIMIT_NOFILE, &lim))
874                 return 1024;
875
876         return (int)lim.rlim_cur;
877 }
878
879 tbm_bufmgr tbm_bufmgr_get(void)
880 {
881         return gBufMgr;
882 }
883 /* LCOV_EXCL_STOP */