tbm_module: add tbm_module_bo_get_size and use it
[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
604                         if (bo->bufmgr->use_hal_tbm) {
605                                 key = (tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
606                         } else if (bufmgr->backend_module_data) {
607                                 key = bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
608                                 if (error != TBM_ERROR_NONE)
609                                         TBM_WRN("fail to get the tdm_key of bo.");
610                         } else {
611                                 key = bufmgr->backend->bo_export(bo);
612                         }
613                         TBM_SNRPRINTF(str, len, c, "%-3d %-11p   %-5d %-7d    %-6d    %-5u %-7d %-11p  %-4d\n",
614                                   ++bo_cnt,
615                                   bo,
616                                   bo->ref_cnt,
617                                   size / 1024,
618                                   bo->lock_cnt,
619                                   bo->map_cnt,
620                                   bo->flags,
621                                   bo->surface,
622                                   key);
623                 }
624         } else
625                 TBM_SNRPRINTF(str, len, c, "no tbm_bos.\n");
626         TBM_SNRPRINTF(str, len, c, "\n");
627
628         TBM_SNRPRINTF(str, len, c, "========================================================================================================\n");
629
630         pthread_mutex_unlock(&gLock);
631
632         return str;
633 }
634
635 void
636 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
637 {
638         char * str;
639         str = tbm_bufmgr_debug_tbm_info_get(bufmgr);
640         if (str) {
641                 TBM_DBG("       %s", str);
642                 free(str);
643         }
644 }
645
646 void
647 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
648 {
649         _tbm_bufmgr_mutex_lock();
650         _tbm_set_last_result(TBM_ERROR_NONE);
651
652         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
653         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
654
655 #ifdef TRACE
656         TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
657         bTrace = onoff;
658 #endif
659
660         _tbm_bufmgr_mutex_unlock();
661 }
662
663 void
664 tbm_bufmgr_debug_set_trace_mask(tbm_bufmgr bufmgr, tbm_bufmgr_debug_trace_mask mask, int set)
665 {
666         _tbm_bufmgr_mutex_lock();
667         _tbm_set_last_result(TBM_ERROR_NONE);
668
669         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
670         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
671
672         if (set == 1) {
673                 trace_mask |= mask;
674
675                 TBM_INFO("bufmgr=%p sets the trace_mask=%d\n", bufmgr, mask);
676                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_BO)
677                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_BO");
678                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL)
679                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL");
680                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE)
681                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE");
682                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE)
683                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE");
684         } else if (set == 0) {
685                 trace_mask &= ~mask;
686
687                 TBM_INFO("bufmgr=%p unsets the trace_mask=%d\n", bufmgr, mask);
688                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_BO)
689                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_BO");
690                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL)
691                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL");
692                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE)
693                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE");
694                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE)
695                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE");
696         } else {
697                 TBM_WRN("set value is wrong.(set=%d)", set);
698         }
699
700         _tbm_bufmgr_mutex_unlock();
701 }
702
703 void
704 tbm_bufmgr_debug_dump_set_scale(double scale)
705 {
706         pthread_mutex_lock(&gLock);
707         _tbm_set_last_result(TBM_ERROR_NONE);
708         scale_factor = scale;
709         pthread_mutex_unlock(&gLock);
710 }
711
712 int
713 tbm_bufmgr_debug_get_ref_count(void)
714 {
715         int refcnt;
716
717         pthread_mutex_lock(&gLock);
718
719         _tbm_set_last_result(TBM_ERROR_NONE);
720
721         refcnt = (gBufMgr) ? gBufMgr->ref_count : 0;
722
723         pthread_mutex_unlock(&gLock);
724
725         return refcnt;
726 }
727
728 int
729 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
730 {
731         pthread_mutex_lock(&gLock);
732         _tbm_set_last_result(TBM_ERROR_NONE);
733
734         if (onoff == 0) {
735                 TBM_DBG("count=%d onoff=%d\n", count, onoff);
736                 b_dump_queue = 0;
737                 tbm_surface_internal_dump_end();
738         } else {
739                 int w, h;
740
741                 if (path == NULL) {
742                         TBM_ERR("path is null");
743                         pthread_mutex_unlock(&gLock);
744                         return 0;
745                 }
746                 TBM_DBG("path=%s count=%d onoff=%d\n", path, count, onoff);
747
748                 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
749                         TBM_ERR("Fail to get tbm_surface size.\n");
750                         pthread_mutex_unlock(&gLock);
751                         return 0;
752                 }
753
754                 tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
755                 scale_factor = 0;
756
757                 b_dump_queue = 1;
758         }
759
760         pthread_mutex_unlock(&gLock);
761
762         return 1;
763 }
764
765 int
766 tbm_bufmgr_debug_dump_all(char *path)
767 {
768         int w, h, count = 0;
769         tbm_surface_h surface = NULL;
770
771         pthread_mutex_lock(&gLock);
772         _tbm_set_last_result(TBM_ERROR_NONE);
773
774         if (!path) {
775                 TBM_ERR("path is null.\n");
776                 pthread_mutex_unlock(&gLock);
777                 return 0;
778         }
779
780         TBM_DBG("path=%s\n", path);
781
782         count = _tbm_util_get_max_surface_size(&w, &h);
783         if (count == 0) {
784                 TBM_ERR("No tbm_surface.\n");
785                 pthread_mutex_unlock(&gLock);
786                 return 0;
787         }
788
789         tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
790         scale_factor = 0;
791
792         LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link)
793                 tbm_surface_internal_dump_buffer(surface, "dump_all");
794
795         tbm_surface_internal_dump_end();
796
797         pthread_mutex_unlock(&gLock);
798
799         return 1;
800 }
801
802 /* internal function */
803 tbm_bufmgr
804 _tbm_bufmgr_get_bufmgr(void)
805 {
806         return gBufMgr;
807 }
808
809 int
810 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *native_display)
811 {
812         tbm_error_e error;
813
814         _tbm_bufmgr_mutex_lock();
815         _tbm_set_last_result(TBM_ERROR_NONE);
816
817         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
818
819         error = tbm_module_bufmgr_bind_native_display(bufmgr->module, native_display);
820         if (error != TBM_ERROR_NONE) {
821                 _tbm_set_last_result(error);
822                 _tbm_bufmgr_mutex_unlock();
823
824                 if (error == TBM_ERROR_NOT_SUPPORTED) {
825                         TBM_WRN("Not supported, so skip: tbm_bufmgr(%p) native_display(%p)", bufmgr, native_display);
826                         return 1;
827                 }
828
829                 return 0;
830         }
831
832         TBM_INFO("tbm_bufmgr(%p) native_display(%p)\n", bufmgr, native_display);
833
834         _tbm_bufmgr_mutex_unlock();
835
836         return 1;
837 }
838
839 tbm_bufmgr
840 tbm_bufmgr_server_init(void)
841 {
842         tbm_bufmgr bufmgr;
843
844         bufmgr = _tbm_bufmgr_init(-1, 1);
845
846         return bufmgr;
847 }
848
849 int
850 tbm_bufmgr_set_bo_lock_type(tbm_bufmgr bufmgr, tbm_bufmgr_bo_lock_type bo_lock_type)
851 {
852         _tbm_bufmgr_mutex_lock();
853         _tbm_set_last_result(TBM_ERROR_NONE);
854
855         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
856         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, 0);
857
858         pthread_mutex_lock(&gLock);
859         gBufMgr->bo_lock_type = bo_lock_type;
860         pthread_mutex_unlock(&gLock);
861
862         TBM_INFO("The bo_lock_type of the bo is %d\n", bo_lock_type);
863
864         _tbm_bufmgr_mutex_unlock();
865
866         return 1;
867 }
868
869
870 int tbm_bufmgr_get_fd_limit(void)
871 {
872         struct rlimit lim;
873
874         if (getrlimit(RLIMIT_NOFILE, &lim))
875                 return 1024;
876
877         return (int)lim.rlim_cur;
878 }
879
880 tbm_bufmgr tbm_bufmgr_get(void)
881 {
882         return gBufMgr;
883 }
884
885
886 tbm_bo
887 tbm_bufmgr_internal_find_bo(tbm_bufmgr bufmgr, tbm_bo bo)
888 {
889         tbm_bo bo2 = NULL;
890
891         TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
892         TBM_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
893
894         if (LIST_IS_EMPTY(&bufmgr->bo_list))
895                 return NULL;
896
897         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
898                 if (bo2->bo_data == bo->bo_data) {
899                         return bo2;
900                 }
901         }
902
903         return NULL;
904 }
905
906 tbm_bo
907 tbm_bufmgr_internal_alloc_bo(tbm_bufmgr bufmgr, int size, int flags, tbm_error_e *error)
908 {
909         tbm_bo bo;
910         tbm_backend_bo_data *bo_data;
911
912         _tbm_bufmgr_check_bo_cnt(bufmgr);
913
914         bo = calloc(1, sizeof(struct _tbm_bo));
915         if (!bo) {
916                 /* LCOV_EXCL_START */
917                 TBM_ERR("memory allocationc failed.");
918                 *error = TBM_ERROR_OUT_OF_MEMORY;
919                 return NULL;
920                 /* LCOV_EXCL_STOP */
921         }
922
923         bo_data = tbm_module_bufmgr_bo_alloc(bufmgr->module, bo, size, flags, error);
924         if (!bo_data) {
925                 /* LCOV_EXCL_START */
926                 TBM_ERR("tbm_module_bufmgr_bo_alloc failed. size:%d flags:%s error:%d", size, _tbm_flag_to_str(flags), *error);
927                 free(bo);
928                 return NULL;
929                 /* LCOV_EXCL_STOP */
930         }
931         bo->bo_data = bo_data;
932         bo->priv = (void *)bo_data; // TODO: this will be DEPRECATED.
933
934         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
935
936         return bo;
937 }
938
939
940 /* LCOV_EXCL_START */
941
942 tbm_bo
943 tbm_bufmgr_internal_alloc_bo_with_format(tbm_bufmgr bufmgr, int format, int bo_idx, int width,
944                                                 int height, int bpp, tbm_bo_memory_type flags, tbm_error_e *error)
945 {
946         tbm_bo bo = NULL;
947
948         _tbm_bufmgr_mutex_lock();
949         _tbm_set_last_result(TBM_ERROR_NONE);
950
951         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
952
953         _tbm_bufmgr_check_bo_cnt(bufmgr);
954
955         bo = calloc(1, sizeof(struct _tbm_bo));
956         if (!bo) {
957                 /* LCOV_EXCL_START */
958                 TBM_ERR("memory allocationc failed.");
959                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
960                 /* LCOV_EXCL_STOP */
961                 goto fail;
962         }
963
964         bo->bo_data = tbm_module_bufmgr_bo_alloc_with_format(bufmgr->module, format, bo_idx, width, height, bpp, flags, error);
965         if (!bo->bo_data) {
966                 /* LCOV_EXCL_START */
967                 _tbm_set_last_result(*error);
968                 /* LCOV_EXCL_STOP */
969                 goto fail;
970         }
971
972         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
973
974         _tbm_bufmgr_mutex_unlock();
975
976         return bo;
977
978 fail:
979         if (bo)
980                 free(bo);
981         _tbm_bufmgr_mutex_unlock();
982
983         return NULL;
984 }
985
986 tbm_bo
987 tbm_bufmgr_internal_alloc_bo_with_bo_data(tbm_bufmgr bufmgr, tbm_backend_bo_data *bo_data, int flags)
988 {
989         tbm_bo bo, bo2 = NULL;
990
991         _tbm_bufmgr_mutex_lock();
992         _tbm_set_last_result(TBM_ERROR_NONE);
993
994         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
995         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bo_data, NULL);
996
997         _tbm_bufmgr_check_bo_cnt(bufmgr);
998
999         bo = calloc(1, sizeof(struct _tbm_bo));
1000         if (!bo) {
1001                 /* LCOV_EXCL_START */
1002                 TBM_ERR("memory allocationc failed.");
1003                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1004                 _tbm_bufmgr_mutex_unlock();
1005                 return NULL;
1006                 /* LCOV_EXCL_STOP */
1007         }
1008         bo->bo_data = bo_data;
1009         bo->get_from_hal_surface = 1;
1010
1011         // return an existed bo if the bo is already created with the same bo_data.
1012         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1013         if (bo2) {
1014                 bo2->ref_cnt++;
1015                 free(bo);
1016                 _tbm_bufmgr_mutex_unlock();
1017                 return bo2;
1018         }
1019
1020         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1021
1022         TBM_TRACE_BO("bo(%p) refcnt(%d), flag(%s)", bo, bo->ref_cnt, _tbm_flag_to_str(bo->flags));
1023
1024         _tbm_bufmgr_mutex_unlock();
1025
1026         return bo;
1027 }
1028
1029 tbm_bo
1030 tbm_bufmgr_internal_import_bo_with_key(tbm_bufmgr bufmgr, unsigned int key, tbm_error_e *error)
1031 {
1032         tbm_bo bo, bo2;
1033         int flags;
1034
1035         _tbm_bufmgr_check_bo_cnt(bufmgr);
1036
1037         bo = calloc(1, sizeof(struct _tbm_bo));
1038         if (!bo) {
1039                 /* LCOV_EXCL_START */
1040                 TBM_ERR("memory allocationc failed.");
1041                 *error = TBM_ERROR_OUT_OF_MEMORY;
1042                 return NULL;
1043                 /* LCOV_EXCL_STOP */
1044         }
1045
1046         bo->bo_data = tbm_module_bufmgr_bo_import_key(bufmgr->module, bo, key, error);
1047         if (!bo->bo_data) {
1048                 /* LCOV_EXCL_START */
1049                 TBM_ERR("tbm_module_bufmgr_bo_import_key failed. tbm_key:%d", key);
1050                 free(bo);
1051                 return NULL;
1052                 /* LCOV_EXCL_STOP */
1053         }
1054
1055         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
1056         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1057         if (bo2) {
1058                 TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list",
1059                                         bo2, bo2->ref_cnt, key, _tbm_flag_to_str(bo2->flags));
1060                 bo2->ref_cnt++;
1061                 free(bo);
1062                 return bo2;
1063         }
1064
1065         // TODO: refactoring tbm_module_bo
1066         if (bufmgr->use_hal_tbm) {
1067                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)error);
1068                 if (*error != TBM_ERROR_NONE) {
1069                         TBM_ERR("fail to get the bo flags(memory_types)");
1070                         flags = TBM_BO_DEFAULT;
1071                 }
1072         } else if (bufmgr->backend_module_data) {
1073                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, error);
1074                 if (error != TBM_ERROR_NONE) {
1075                         TBM_ERR("fail to get the bo flags(memory_types)");
1076                         flags = TBM_BO_DEFAULT;
1077                 }
1078         } else {
1079                 if (bufmgr->backend->bo_get_flags)
1080                         flags = bufmgr->backend->bo_get_flags(bo);
1081                 else
1082                         flags = TBM_BO_DEFAULT;
1083         }
1084
1085         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1086
1087         return bo;
1088 }
1089
1090 tbm_bo
1091 tbm_bufmgr_internal_import_bo_with_fd(tbm_bufmgr bufmgr, tbm_fd fd, tbm_error_e *error)
1092 {
1093         tbm_bo bo, bo2;
1094         int flags;
1095
1096         _tbm_bufmgr_check_bo_cnt(bufmgr);
1097
1098         bo = calloc(1, sizeof(struct _tbm_bo));
1099         if (!bo) {
1100                 /* LCOV_EXCL_START */
1101                 TBM_ERR("memory allocationc failed.");
1102                 *error = TBM_ERROR_OUT_OF_MEMORY;
1103                 return NULL;
1104                 /* LCOV_EXCL_STOP */
1105         }
1106
1107         bo->bo_data = tbm_module_bufmgr_bo_import_fd(bufmgr->module, bo, fd, error);
1108         if (!bo->bo_data) {
1109                 /* LCOV_EXCL_START */
1110                 TBM_ERR("tbm_module_bufmgr_bo_import_fd failed. tbm_fd:%d", fd);
1111                 free(bo);
1112                 return NULL;
1113                 /* LCOV_EXCL_STOP */
1114         }
1115
1116         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
1117         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1118         if (bo2) {
1119                 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list",
1120                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1121                 bo2->ref_cnt++;
1122                 free(bo);
1123                 return bo2;
1124         }
1125
1126         // TODO: refactoring tbm_module_bo
1127         if (bufmgr->use_hal_tbm) {
1128                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)error);
1129                 if (error != TBM_ERROR_NONE) {
1130                         TBM_ERR("fail to get the bo flags(memory_types)");
1131                         flags = TBM_BO_DEFAULT;
1132                 }
1133         } else if (bufmgr->backend_module_data) {
1134                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, error);
1135                 if (error != TBM_ERROR_NONE) {
1136                         TBM_ERR("fail to get the bo flags(memory_types)");
1137                         flags = TBM_BO_DEFAULT;
1138                 }
1139         } else {
1140                 if (bufmgr->backend->bo_get_flags)
1141                         flags = bufmgr->backend->bo_get_flags(bo);
1142                 else
1143                         flags = TBM_BO_DEFAULT;
1144         }
1145
1146         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1147
1148         return bo;
1149 }
1150
1151 /* LCOV_EXCL_STOP */