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