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