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