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