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