tbm_module: change tbm_module_bufmgr symbol names
[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 static void
81 _tbm_bufmgr_check_bo_cnt(tbm_bufmgr bufmgr)
82 {
83         static int last_chk_bo_cnt = 0;
84
85         if ((bufmgr->bo_cnt >= 500) && ((bufmgr->bo_cnt % 20) == 0) &&
86                 (bufmgr->bo_cnt > last_chk_bo_cnt)) {
87                 TBM_DBG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
88                 tbm_bufmgr_debug_show(bufmgr);
89                 last_chk_bo_cnt = bufmgr->bo_cnt;
90         }
91 }
92
93 static void
94 _tbm_bufmgr_initialize_bo(tbm_bufmgr bufmgr, tbm_bo bo, int flags)
95 {
96         bo->bufmgr = bufmgr;
97         bo->flags = flags;
98         bo->magic = TBM_BO_MAGIC;
99         bo->ref_cnt = 1;
100
101         LIST_INITHEAD(&bo->user_data_list);
102
103         bufmgr->bo_cnt++;
104         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
105 }
106
107 void
108 _tbm_bufmgr_mutex_lock(void)
109 {
110         pthread_mutex_lock(&tbm_bufmgr_lock);
111 }
112
113 void
114 _tbm_bufmgr_mutex_unlock(void)
115 {
116         pthread_mutex_unlock(&tbm_bufmgr_lock);
117 }
118
119 static int
120 _tbm_util_get_max_surface_size(int *w, int *h)
121 {
122         tbm_surface_info_s info;
123         tbm_surface_h surface = NULL;
124         int count = 0;
125
126         *w = 0;
127         *h = 0;
128
129         if (gBufMgr == NULL || LIST_IS_EMPTY(&gBufMgr->surf_list))
130                 return count;
131
132         LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link) {
133                 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
134                         count++;
135                         if (*w < info.width)
136                                 *w = info.width;
137                         if (*h < info.height)
138                                 *h = info.height;
139                 }
140         }
141
142         return count;
143 }
144
145 static void
146 _tbm_util_get_appname_brief(char *brief)
147 {
148         char delim[] = "/";
149         char *token = NULL;
150         char temp[255] = {0,};
151         char *saveptr = NULL;
152
153         token = strtok_r(brief, delim, &saveptr);
154
155         while (token != NULL) {
156                 memset(temp, 0x00, 255 * sizeof(char));
157                 strncpy(temp, token, 254 * sizeof(char));
158                 token = strtok_r(NULL, delim, &saveptr);
159         }
160
161         snprintf(brief, sizeof(temp), "%s", temp);
162 }
163
164 static void
165 _tbm_util_get_appname_from_pid(long pid, char *str)
166 {
167         char fn_cmdline[255] = {0, }, cmdline[255];
168         FILE *fp;
169         int len;
170
171         if (pid <= 0) return;
172
173         snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", pid);
174
175         fp = fopen(fn_cmdline, "r");
176         if (fp == 0) {
177                 TBM_ERR("cannot file open %s\n", fn_cmdline);
178                 return;
179         }
180
181         if (!fgets(cmdline, 255, fp)) {
182                 TBM_ERR("fail to get appname for pid(%ld)\n", pid);
183                 fclose(fp);
184                 return;
185         }
186
187         fclose(fp);
188
189         len = strlen(cmdline);
190         if (len < 1)
191                 memset(cmdline, 0x00, 255);
192         else
193                 cmdline[len] = 0;
194
195         snprintf(str, sizeof(cmdline), "%s", cmdline);
196 }
197
198 static void
199 _tbm_bufmgr_copy_module_data(tbm_bufmgr bufmgr, tbm_module *module)
200 {
201         bufmgr->module_data = module->module_data;
202         bufmgr->backend = module->backend;
203
204         bufmgr->backend_module_data = module->backend_module_data;
205         bufmgr->bufmgr_data = module->bufmgr_data;
206         bufmgr->bufmgr_func = module->bufmgr_func;
207         bufmgr->bo_func = module->bo_func;
208
209         bufmgr->use_hal_tbm = module->use_hal_tbm;
210         bufmgr->auth_wl_socket_created = module->auth_wl_socket_created;
211         bufmgr->auth_fd = module->auth_fd;
212         bufmgr->hal_backend = module->hal_backend;
213         bufmgr->hal_bufmgr = module->hal_bufmgr;
214 }
215
216 static void
217 _tbm_bufmgr_reset_modlue_data(tbm_bufmgr bufmgr)
218 {
219         bufmgr->module_data = NULL;
220         bufmgr->backend = NULL;
221
222         bufmgr->backend_module_data = NULL;
223         bufmgr->bufmgr_data = NULL;
224         bufmgr->bufmgr_func = NULL;
225         bufmgr->bo_func = NULL;
226
227         bufmgr->use_hal_tbm = 0;
228         bufmgr->auth_wl_socket_created = 0;
229         bufmgr->auth_fd = -1;
230         bufmgr->hal_backend = NULL;
231         bufmgr->hal_bufmgr = NULL;
232 }
233
234 /* LCOV_EXCL_STOP */
235
236 static tbm_bufmgr
237 _tbm_bufmgr_init(int fd, int server)
238 {
239         tbm_error_e error = TBM_ERROR_NONE;
240
241 #ifdef TBM_BUFMGR_INIT_TIME
242         struct timeval start_tv, end_tv;
243 #endif
244         char *env;
245
246 #ifdef TBM_BUFMGR_INIT_TIME
247         /* get the start tv */
248         gettimeofday(&start_tv, NULL);
249 #endif
250
251         bDlog = 1;
252
253         /* LCOV_EXCL_START */
254 #ifdef TRACE
255         env = getenv("TBM_TRACE");
256         if (env) {
257                 trace_mask = atoi(env);
258                 TBM_DBG("TBM_TRACE=%s\n", env);
259         } else
260                 trace_mask = 0;
261 #endif
262
263         pthread_mutex_lock(&gLock);
264
265         _tbm_set_last_result(TBM_ERROR_NONE);
266
267         if (fd >= 0) {
268                 TBM_WRN("!!!!!WARNING:: The tbm_bufmgr_init DOSE NOT use argument fd ANYMORE.\n");
269                 TBM_WRN("!!!!!WARNING:: IT WILL BE CHANGED like tbm_bufmgr_init(int fd) --> tbm_bufmgr_init(void).\n");
270         }
271
272
273         /* initialize buffer manager */
274         if (gBufMgr) {
275                 gBufMgr->ref_count++;
276                 TBM_DBG("reuse  tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
277                 pthread_mutex_unlock(&gLock);
278                 return gBufMgr;
279         }
280
281         TBM_DBG("bufmgr init\n");
282
283         /* allocate bufmgr */
284         gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
285         if (!gBufMgr) {
286                 TBM_ERR("error: fail to alloc bufmgr fd(%d)\n", fd);
287                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
288                 pthread_mutex_unlock(&gLock);
289                 return NULL;
290         }
291
292         gBufMgr->fd = fd;
293
294         /* set the display_server flag before loading the backend module */
295         if (server) {
296                 TBM_INFO("The tbm_bufmgr(%p) is used by display server. Need to bind the native_display.\n", gBufMgr);
297                 gBufMgr->display_server = 1;
298         }
299
300         /* load bufmgr priv from env */
301         gBufMgr->module = tbm_module_load(gBufMgr->fd);
302         if (!gBufMgr->module) {
303                 TBM_ERR("error : Fail to load bufmgr backend\n");
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
312         // TODO: this is temporary. it will be removed after finishing refactoring the tbm_module.
313         _tbm_bufmgr_copy_module_data(gBufMgr, gBufMgr->module);
314
315         /* check the essential capabilities of tbm_module */
316         gBufMgr->capabilities = tbm_module_bufmgr_get_capabilities(gBufMgr->module, &error);
317         if (gBufMgr->capabilities == TBM_BUFMGR_CAPABILITY_NONE) {
318                 TBM_ERR("The capabilities of the backend module is TBM_BUFMGR_CAPABILITY_NONE.");
319                 TBM_ERR("TBM_BUFMGR_CAPABILITY_SHARE_FD is the essential capability.");
320                 tbm_module_unload(gBufMgr->module);
321                 _tbm_set_last_result(error);
322                 free(gBufMgr);
323                 gBufMgr = NULL;
324                 pthread_mutex_unlock(&gLock);
325                 return NULL;
326         }
327
328         if (!(gBufMgr->capabilities & TBM_BUFMGR_CAPABILITY_SHARE_FD)) {
329                 TBM_ERR("The capabilities of the backend module had no TBM_BUFMGR_CAPABILITY_SHARE_FD.");
330                 TBM_ERR("The tbm backend has to get TBM_BUFMGR_CAPABILITY_SHARE_FD. ");
331                 tbm_module_unload(gBufMgr->module);
332                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
333                 free(gBufMgr);
334                 gBufMgr = NULL;
335                 pthread_mutex_unlock(&gLock);
336                 return NULL;
337         }
338
339         /* LCOV_EXCL_STOP */
340
341         gBufMgr->ref_count = 1;
342
343         TBM_INFO("create tizen bufmgr:%p ref_count:%d\n",
344             gBufMgr, gBufMgr->ref_count);
345
346         /* setup the bo_lock_type */
347         env = getenv("BUFMGR_LOCK_TYPE");
348         if (env && !strcmp(env, "always"))
349                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS;
350         else if (env && !strcmp(env, "none"))
351                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_NEVER;
352         else if (env && !strcmp(env, "once"))
353                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ONCE;
354         else
355                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS;
356
357         TBM_DBG("BUFMGR_LOCK_TYPE=%s\n", env ? env : "default:once");
358
359         /* intialize bo_list */
360         LIST_INITHEAD(&gBufMgr->bo_list);
361
362         /* intialize surf_list */
363         LIST_INITHEAD(&gBufMgr->surf_list);
364
365         /* intialize surf_queue_list */
366         LIST_INITHEAD(&gBufMgr->surf_queue_list);
367
368         /* intialize debug_key_list */
369         LIST_INITHEAD(&gBufMgr->debug_key_list);
370
371 #ifdef TBM_BUFMGR_INIT_TIME
372         /* get the end tv */
373         gettimeofday(&end_tv, NULL);
374         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)));
375 #endif
376
377         pthread_mutex_unlock(&gLock);
378
379         return gBufMgr;
380 }
381
382 tbm_bufmgr
383 tbm_bufmgr_init(int fd)
384 {
385         tbm_bufmgr bufmgr;
386
387         bufmgr = _tbm_bufmgr_init(fd, 0);
388
389         return bufmgr;
390 }
391
392 void
393 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
394 {
395         TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
396
397         _tbm_bufmgr_mutex_lock();
398         pthread_mutex_lock(&gLock);
399         _tbm_set_last_result(TBM_ERROR_NONE);
400
401         if (!gBufMgr) {
402                 TBM_ERR("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
403                 pthread_mutex_unlock(&gLock);
404                 _tbm_bufmgr_mutex_unlock();
405                 return;
406         }
407
408         bufmgr->ref_count--;
409         if (bufmgr->ref_count > 0) {
410                 TBM_DBG("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
411                 pthread_mutex_unlock(&gLock);
412                 _tbm_bufmgr_mutex_unlock();
413                 return;
414         }
415
416         /* destroy bo_list */
417         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
418                 tbm_bo bo = NULL, tmp;
419
420                 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
421                         TBM_ERR("Un-freed bo(%p, ref:%d)\n", bo, bo->ref_cnt);
422                         _tbm_bo_free(bo);
423                 }
424                 LIST_DELINIT(&bufmgr->bo_list);
425         }
426
427         /* destroy surf_list */
428         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
429                 tbm_surface_h surf = NULL, tmp;
430
431                 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &bufmgr->surf_list, item_link) {
432                         TBM_ERR("Un-freed surf(%p, ref:%d)\n", surf, surf->refcnt);
433                         tbm_surface_destroy(surf);
434                 }
435                 LIST_DELINIT(&bufmgr->surf_list);
436         }
437
438         tbm_module_unload(bufmgr->module);
439
440         // TODO: this is temporary. it will be removed after finishing refactoring the tbm_module.
441         _tbm_bufmgr_reset_modlue_data(bufmgr);
442
443         if (bufmgr->fd > 0)
444                 close(bufmgr->fd);
445
446         TBM_INFO("destroy tbm_bufmgr(%p)\n", bufmgr);
447
448         free(bufmgr);
449         gBufMgr = NULL;
450
451         pthread_mutex_unlock(&gLock);
452         _tbm_bufmgr_mutex_unlock();
453 }
454
455 unsigned int
456 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
457 {
458         unsigned int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
459
460         _tbm_bufmgr_mutex_lock();
461         _tbm_set_last_result(TBM_ERROR_NONE);
462
463         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
464         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
465
466         capabilities = bufmgr->capabilities;
467
468         _tbm_bufmgr_mutex_unlock();
469
470         return capabilities;
471 }
472
473 /* LCOV_EXCL_START */
474 char *
475 tbm_bufmgr_debug_tbm_info_get(tbm_bufmgr bufmgr)
476 {
477         char app_name[255] = {0,}, title[512] = {0,};
478         tbm_surface_debug_data *debug_old_data = NULL;
479         char *str;
480         int len = 1024*4;
481         int c = 0;
482         int size;
483         tbm_error_e error;
484         long pid = 0;
485
486         pthread_mutex_lock(&gLock);
487         _tbm_set_last_result(TBM_ERROR_NONE);
488
489         if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
490                 TBM_ERR("invalid bufmgr\n");
491                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
492                 pthread_mutex_unlock(&gLock);
493                 return NULL;
494         }
495
496         str = malloc(len);
497         if (!str) {
498                 TBM_ERR("Fail to allocate the string.\n");
499                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
500                 pthread_mutex_unlock(&gLock);
501                 return NULL;
502         }
503
504         TBM_SNRPRINTF(str, len, c, "\n");
505         pid = syscall(SYS_getpid);
506         _tbm_util_get_appname_from_pid(pid, app_name);
507         _tbm_util_get_appname_brief(app_name);
508         TBM_SNRPRINTF(str, len, c, "===========================================TBM DEBUG: %s(%ld)===========================================\n",
509                   app_name, pid);
510
511         snprintf(title, 255, "%s", "no  surface     refcnt  width  height  bpp  size    n_b  n_p  flags    format    app_name              ");
512
513         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
514                 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
515                         strncat(title, "  ", MAX_SIZE_N(title));
516                         strncat(title, debug_old_data->key, MAX_SIZE_N(title));
517                 }
518         }
519
520         TBM_SNRPRINTF(str, len, c, "[tbm_surface information]\n");
521         TBM_SNRPRINTF(str, len, c, "%s\n", title);
522
523         /* show the tbm_surface information in surf_list */
524         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
525                 tbm_surface_h surf = NULL;
526                 int surf_cnt = 0;
527
528                 LIST_FOR_EACH_ENTRY(surf, &bufmgr->surf_list, item_link) {
529                         char data[512] = {0,};
530                         unsigned int surf_pid = 0;
531                         int i;
532
533                         surf_pid = _tbm_surface_internal_get_debug_pid(surf);
534                         if (!surf_pid) {
535                                 /* if pid is null, set the self_pid */
536                                 surf_pid = syscall(SYS_getpid);;
537                         }
538
539                         memset(app_name, 0x0, 255 * sizeof(char));
540                         if (geteuid() == 0) {
541                                 _tbm_util_get_appname_from_pid(surf_pid, app_name);
542                                 _tbm_util_get_appname_brief(app_name);
543                         } else {
544                                 snprintf(app_name, sizeof(app_name), "%d", surf_pid);
545                         }
546
547                         snprintf(data, 255, "%-3d %-11p   %-5d %-6u %-7u %-4u %-7u  %-3d  %-3d %-8d %-9s %-22s",
548                                   ++surf_cnt,
549                                   surf,
550                                   surf->refcnt,
551                                   surf->info.width,
552                                   surf->info.height,
553                                   surf->info.bpp,
554                                   surf->info.size / 1024,
555                                   surf->num_bos,
556                                   surf->num_planes,
557                                   surf->flags,
558                                   _tbm_surface_internal_format_to_str(surf->info.format) + 11,
559                                   app_name);
560
561                         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
562                                 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
563                                         char *value;
564
565                                         strncat(data, "  ", MAX_SIZE_N(title));
566
567                                         value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
568                                         if (value)
569                                                 strncat(data, value, MAX_SIZE_N(title));
570                                         else
571                                                 strncat(data, "none", MAX_SIZE_N(title));
572                                 }
573                         }
574                         TBM_SNRPRINTF(str, len, c, "%s\n", data);
575
576                         for (i = 0; i < surf->num_bos; i++) {
577                                 size = tbm_module_bo_get_size(bufmgr->module, surf->bos[i], surf->bos[i]->bo_data, &error);
578                                 if (error != TBM_ERROR_NONE)
579                                         TBM_WRN("fail to get the size of bo.");
580                                 TBM_SNRPRINTF(str, len, c, " bo:%-12p  %-26d%-10d\n",
581                                           surf->bos[i],
582                                           surf->bos[i]->ref_cnt,
583                                           size / 1024);
584                         }
585                 }
586         } else
587                 TBM_SNRPRINTF(str, len, c, " no tbm_surfaces.\n");
588         TBM_SNRPRINTF(str, len, c, "\n");
589
590         TBM_SNRPRINTF(str, len, c, "[tbm_bo information]\n");
591         TBM_SNRPRINTF(str, len, c, "no  bo          refcnt  size    lock_cnt  map_cnt  flags   surface     name\n");
592
593         /* show the tbm_bo information in bo_list */
594         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
595                 int bo_cnt = 0;
596                 tbm_bo bo = NULL;
597                 tbm_key key = 0;
598
599                 LIST_FOR_EACH_ENTRY(bo, &bufmgr->bo_list, item_link) {
600                         size = tbm_module_bo_get_size(bufmgr->module, bo, bo->bo_data, &error);
601                         if (error != TBM_ERROR_NONE)
602                                 TBM_WRN("fail to get the size of bo.");
603                         key = tbm_module_bo_export_key(bufmgr->module, bo, bo->bo_data, &error);
604                         if (error != TBM_ERROR_NONE)
605                                 TBM_WRN("fail to get the tdm_key of bo.");
606                         TBM_SNRPRINTF(str, len, c, "%-3d %-11p   %-5d %-7d    %-6d    %-5u %-7d %-11p  %-4d\n",
607                                   ++bo_cnt,
608                                   bo,
609                                   bo->ref_cnt,
610                                   size / 1024,
611                                   bo->lock_cnt,
612                                   bo->map_cnt,
613                                   bo->flags,
614                                   bo->surface,
615                                   key);
616                 }
617         } else
618                 TBM_SNRPRINTF(str, len, c, "no tbm_bos.\n");
619         TBM_SNRPRINTF(str, len, c, "\n");
620
621         TBM_SNRPRINTF(str, len, c, "========================================================================================================\n");
622
623         pthread_mutex_unlock(&gLock);
624
625         return str;
626 }
627
628 void
629 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
630 {
631         char * str;
632         str = tbm_bufmgr_debug_tbm_info_get(bufmgr);
633         if (str) {
634                 TBM_DBG("       %s", str);
635                 free(str);
636         }
637 }
638
639 void
640 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
641 {
642         _tbm_bufmgr_mutex_lock();
643         _tbm_set_last_result(TBM_ERROR_NONE);
644
645         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
646         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
647
648 #ifdef TRACE
649         TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
650         bTrace = onoff;
651 #endif
652
653         _tbm_bufmgr_mutex_unlock();
654 }
655
656 void
657 tbm_bufmgr_debug_set_trace_mask(tbm_bufmgr bufmgr, tbm_bufmgr_debug_trace_mask mask, int set)
658 {
659         _tbm_bufmgr_mutex_lock();
660         _tbm_set_last_result(TBM_ERROR_NONE);
661
662         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
663         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
664
665         if (set == 1) {
666                 trace_mask |= mask;
667
668                 TBM_INFO("bufmgr=%p sets the trace_mask=%d\n", bufmgr, mask);
669                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_BO)
670                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_BO");
671                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL)
672                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL");
673                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE)
674                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE");
675                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE)
676                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE");
677         } else if (set == 0) {
678                 trace_mask &= ~mask;
679
680                 TBM_INFO("bufmgr=%p unsets the trace_mask=%d\n", bufmgr, mask);
681                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_BO)
682                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_BO");
683                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL)
684                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL");
685                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE)
686                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE");
687                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE)
688                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE");
689         } else {
690                 TBM_WRN("set value is wrong.(set=%d)", set);
691         }
692
693         _tbm_bufmgr_mutex_unlock();
694 }
695
696 void
697 tbm_bufmgr_debug_dump_set_scale(double scale)
698 {
699         pthread_mutex_lock(&gLock);
700         _tbm_set_last_result(TBM_ERROR_NONE);
701         scale_factor = scale;
702         pthread_mutex_unlock(&gLock);
703 }
704
705 int
706 tbm_bufmgr_debug_get_ref_count(void)
707 {
708         int refcnt;
709
710         pthread_mutex_lock(&gLock);
711
712         _tbm_set_last_result(TBM_ERROR_NONE);
713
714         refcnt = (gBufMgr) ? gBufMgr->ref_count : 0;
715
716         pthread_mutex_unlock(&gLock);
717
718         return refcnt;
719 }
720
721 int
722 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
723 {
724         pthread_mutex_lock(&gLock);
725         _tbm_set_last_result(TBM_ERROR_NONE);
726
727         if (onoff == 0) {
728                 TBM_DBG("count=%d onoff=%d\n", count, onoff);
729                 b_dump_queue = 0;
730                 tbm_surface_internal_dump_end();
731         } else {
732                 int w, h;
733
734                 if (path == NULL) {
735                         TBM_ERR("path is null");
736                         pthread_mutex_unlock(&gLock);
737                         return 0;
738                 }
739                 TBM_DBG("path=%s count=%d onoff=%d\n", path, count, onoff);
740
741                 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
742                         TBM_ERR("Fail to get tbm_surface size.\n");
743                         pthread_mutex_unlock(&gLock);
744                         return 0;
745                 }
746
747                 tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
748                 scale_factor = 0;
749
750                 b_dump_queue = 1;
751         }
752
753         pthread_mutex_unlock(&gLock);
754
755         return 1;
756 }
757
758 int
759 tbm_bufmgr_debug_dump_all(char *path)
760 {
761         int w, h, count = 0;
762         tbm_surface_h surface = NULL;
763
764         pthread_mutex_lock(&gLock);
765         _tbm_set_last_result(TBM_ERROR_NONE);
766
767         if (!path) {
768                 TBM_ERR("path is null.\n");
769                 pthread_mutex_unlock(&gLock);
770                 return 0;
771         }
772
773         TBM_DBG("path=%s\n", path);
774
775         count = _tbm_util_get_max_surface_size(&w, &h);
776         if (count == 0) {
777                 TBM_ERR("No tbm_surface.\n");
778                 pthread_mutex_unlock(&gLock);
779                 return 0;
780         }
781
782         tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
783         scale_factor = 0;
784
785         LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link)
786                 tbm_surface_internal_dump_buffer(surface, "dump_all");
787
788         tbm_surface_internal_dump_end();
789
790         pthread_mutex_unlock(&gLock);
791
792         return 1;
793 }
794
795 /* internal function */
796 tbm_bufmgr
797 _tbm_bufmgr_get_bufmgr(void)
798 {
799         return gBufMgr;
800 }
801
802 int
803 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *native_display)
804 {
805         tbm_error_e error;
806
807         _tbm_bufmgr_mutex_lock();
808         _tbm_set_last_result(TBM_ERROR_NONE);
809
810         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
811
812         error = tbm_module_bufmgr_bind_native_display(bufmgr->module, native_display);
813         if (error != TBM_ERROR_NONE) {
814                 _tbm_set_last_result(error);
815                 _tbm_bufmgr_mutex_unlock();
816
817                 if (error == TBM_ERROR_NOT_SUPPORTED) {
818                         TBM_WRN("Not supported, so skip: tbm_bufmgr(%p) native_display(%p)", bufmgr, native_display);
819                         return 1;
820                 }
821
822                 return 0;
823         }
824
825         TBM_INFO("tbm_bufmgr(%p) native_display(%p)\n", bufmgr, native_display);
826
827         _tbm_bufmgr_mutex_unlock();
828
829         return 1;
830 }
831
832 tbm_bufmgr
833 tbm_bufmgr_server_init(void)
834 {
835         tbm_bufmgr bufmgr;
836
837         bufmgr = _tbm_bufmgr_init(-1, 1);
838
839         return bufmgr;
840 }
841
842 int
843 tbm_bufmgr_set_bo_lock_type(tbm_bufmgr bufmgr, tbm_bufmgr_bo_lock_type bo_lock_type)
844 {
845         _tbm_bufmgr_mutex_lock();
846         _tbm_set_last_result(TBM_ERROR_NONE);
847
848         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
849         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, 0);
850
851         pthread_mutex_lock(&gLock);
852         gBufMgr->bo_lock_type = bo_lock_type;
853         pthread_mutex_unlock(&gLock);
854
855         TBM_INFO("The bo_lock_type of the bo is %d\n", bo_lock_type);
856
857         _tbm_bufmgr_mutex_unlock();
858
859         return 1;
860 }
861
862
863 int tbm_bufmgr_get_fd_limit(void)
864 {
865         struct rlimit lim;
866
867         if (getrlimit(RLIMIT_NOFILE, &lim))
868                 return 1024;
869
870         return (int)lim.rlim_cur;
871 }
872
873 tbm_bufmgr tbm_bufmgr_get(void)
874 {
875         return gBufMgr;
876 }
877
878
879 tbm_bo
880 tbm_bufmgr_internal_find_bo(tbm_bufmgr bufmgr, tbm_bo bo)
881 {
882         tbm_bo bo2 = NULL;
883
884         TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
885         TBM_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
886
887         if (LIST_IS_EMPTY(&bufmgr->bo_list))
888                 return NULL;
889
890         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
891                 if (bo2->bo_data == bo->bo_data) {
892                         return bo2;
893                 }
894         }
895
896         return NULL;
897 }
898
899 tbm_bo
900 tbm_bufmgr_internal_alloc_bo(tbm_bufmgr bufmgr, int size, int flags, tbm_error_e *error)
901 {
902         tbm_bo bo;
903         tbm_backend_bo_data *bo_data;
904
905         _tbm_bufmgr_check_bo_cnt(bufmgr);
906
907         bo = calloc(1, sizeof(struct _tbm_bo));
908         if (!bo) {
909                 /* LCOV_EXCL_START */
910                 TBM_ERR("memory allocationc failed.");
911                 *error = TBM_ERROR_OUT_OF_MEMORY;
912                 return NULL;
913                 /* LCOV_EXCL_STOP */
914         }
915
916         bo_data = tbm_module_bufmgr_alloc_bo(bufmgr->module, bo, size, flags, error);
917         if (!bo_data) {
918                 /* LCOV_EXCL_START */
919                 TBM_ERR("tbm_module_bufmgr_alloc_bo failed. size:%d flags:%s error:%d", size, _tbm_flag_to_str(flags), *error);
920                 free(bo);
921                 return NULL;
922                 /* LCOV_EXCL_STOP */
923         }
924         bo->bo_data = bo_data;
925         bo->priv = (void *)bo_data; // TODO: this will be DEPRECATED.
926
927         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
928
929         return bo;
930 }
931
932
933 /* LCOV_EXCL_START */
934
935 tbm_bo
936 tbm_bufmgr_internal_alloc_bo_with_format(tbm_bufmgr bufmgr, int format, int bo_idx, int width,
937                                                 int height, int bpp, tbm_bo_memory_type flags, tbm_error_e *error)
938 {
939         tbm_bo bo = NULL;
940
941         _tbm_bufmgr_mutex_lock();
942         _tbm_set_last_result(TBM_ERROR_NONE);
943
944         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
945
946         _tbm_bufmgr_check_bo_cnt(bufmgr);
947
948         bo = calloc(1, sizeof(struct _tbm_bo));
949         if (!bo) {
950                 /* LCOV_EXCL_START */
951                 TBM_ERR("memory allocationc failed.");
952                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
953                 /* LCOV_EXCL_STOP */
954                 goto fail;
955         }
956
957         bo->bo_data = tbm_module_bufmgr_alloc_bo_with_format(bufmgr->module, format, bo_idx, width, height, bpp, flags, error);
958         if (!bo->bo_data) {
959                 /* LCOV_EXCL_START */
960                 _tbm_set_last_result(*error);
961                 /* LCOV_EXCL_STOP */
962                 goto fail;
963         }
964
965         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
966
967         _tbm_bufmgr_mutex_unlock();
968
969         return bo;
970
971 fail:
972         if (bo)
973                 free(bo);
974         _tbm_bufmgr_mutex_unlock();
975
976         return NULL;
977 }
978
979 tbm_bo
980 tbm_bufmgr_internal_alloc_bo_with_bo_data(tbm_bufmgr bufmgr, tbm_backend_bo_data *bo_data, int flags)
981 {
982         tbm_bo bo, bo2 = NULL;
983
984         _tbm_bufmgr_mutex_lock();
985         _tbm_set_last_result(TBM_ERROR_NONE);
986
987         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
988         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bo_data, NULL);
989
990         _tbm_bufmgr_check_bo_cnt(bufmgr);
991
992         bo = calloc(1, sizeof(struct _tbm_bo));
993         if (!bo) {
994                 /* LCOV_EXCL_START */
995                 TBM_ERR("memory allocationc failed.");
996                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
997                 _tbm_bufmgr_mutex_unlock();
998                 return NULL;
999                 /* LCOV_EXCL_STOP */
1000         }
1001         bo->bo_data = bo_data;
1002         bo->get_from_hal_surface = 1;
1003
1004         // return an existed bo if the bo is already created with the same bo_data.
1005         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1006         if (bo2) {
1007                 bo2->ref_cnt++;
1008                 free(bo);
1009                 _tbm_bufmgr_mutex_unlock();
1010                 return bo2;
1011         }
1012
1013         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1014
1015         TBM_TRACE_BO("bo(%p) refcnt(%d), flag(%s)", bo, bo->ref_cnt, _tbm_flag_to_str(bo->flags));
1016
1017         _tbm_bufmgr_mutex_unlock();
1018
1019         return bo;
1020 }
1021
1022 tbm_bo
1023 tbm_bufmgr_internal_import_bo_with_key(tbm_bufmgr bufmgr, unsigned int key, tbm_error_e *error)
1024 {
1025         tbm_bo bo, bo2;
1026         int flags;
1027
1028         _tbm_bufmgr_check_bo_cnt(bufmgr);
1029
1030         bo = calloc(1, sizeof(struct _tbm_bo));
1031         if (!bo) {
1032                 /* LCOV_EXCL_START */
1033                 TBM_ERR("memory allocationc failed.");
1034                 *error = TBM_ERROR_OUT_OF_MEMORY;
1035                 return NULL;
1036                 /* LCOV_EXCL_STOP */
1037         }
1038
1039         bo->bo_data = tbm_module_bufmgr_import_bo_with_key(bufmgr->module, bo, key, error);
1040         if (!bo->bo_data) {
1041                 /* LCOV_EXCL_START */
1042                 TBM_ERR("tbm_module_bufmgr_import_bo_with_key failed. tbm_key:%d", key);
1043                 free(bo);
1044                 return NULL;
1045                 /* LCOV_EXCL_STOP */
1046         }
1047
1048         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
1049         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1050         if (bo2) {
1051                 TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list",
1052                                         bo2, bo2->ref_cnt, key, _tbm_flag_to_str(bo2->flags));
1053                 bo2->ref_cnt++;
1054                 free(bo);
1055                 return bo2;
1056         }
1057
1058         flags = tbm_module_bo_get_memory_types(bufmgr->module, bo, bo->bo_data, error);
1059         if (*error != TBM_ERROR_NONE) {
1060                 TBM_ERR("fail to get the bo flags(memory_types)");
1061                 flags = TBM_BO_DEFAULT;
1062         }
1063
1064         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1065
1066         return bo;
1067 }
1068
1069 tbm_bo
1070 tbm_bufmgr_internal_import_bo_with_fd(tbm_bufmgr bufmgr, tbm_fd fd, tbm_error_e *error)
1071 {
1072         tbm_bo bo, bo2;
1073         int flags;
1074
1075         _tbm_bufmgr_check_bo_cnt(bufmgr);
1076
1077         bo = calloc(1, sizeof(struct _tbm_bo));
1078         if (!bo) {
1079                 /* LCOV_EXCL_START */
1080                 TBM_ERR("memory allocationc failed.");
1081                 *error = TBM_ERROR_OUT_OF_MEMORY;
1082                 return NULL;
1083                 /* LCOV_EXCL_STOP */
1084         }
1085
1086         bo->bo_data = tbm_module_bufmgr_import_bo_with_fd(bufmgr->module, bo, fd, error);
1087         if (!bo->bo_data) {
1088                 /* LCOV_EXCL_START */
1089                 TBM_ERR("tbm_module_bufmgr_import_bo_with_fd failed. tbm_fd:%d", fd);
1090                 free(bo);
1091                 return NULL;
1092                 /* LCOV_EXCL_STOP */
1093         }
1094
1095         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
1096         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1097         if (bo2) {
1098                 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list",
1099                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1100                 bo2->ref_cnt++;
1101                 free(bo);
1102                 return bo2;
1103         }
1104
1105         flags = tbm_module_bo_get_memory_types(bufmgr->module, bo, bo->bo_data, error);
1106         if (*error != TBM_ERROR_NONE) {
1107                 TBM_ERR("fail to get the bo flags(memory_types)");
1108                 flags = TBM_BO_DEFAULT;
1109         }
1110
1111         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1112
1113         return bo;
1114 }
1115
1116 /* LCOV_EXCL_STOP */