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