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