tbm_bufmgr: lock the gLock before locking tbm_bufmgr_mutex
[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         pthread_mutex_lock(&gLock);
368         _tbm_bufmgr_mutex_lock();
369         _tbm_set_last_result(TBM_ERROR_NONE);
370
371         if (!gBufMgr) {
372                 TBM_ERR("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
373                 _tbm_bufmgr_mutex_unlock();
374                 pthread_mutex_unlock(&gLock);
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                 _tbm_bufmgr_mutex_unlock();
382                 pthread_mutex_unlock(&gLock);
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         _tbm_bufmgr_mutex_unlock();
419         pthread_mutex_unlock(&gLock);
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)
867 {
868         tbm_error_e error = TBM_ERROR_NONE;
869         tbm_bo bo;
870
871         _tbm_bufmgr_mutex_lock();
872
873         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
874         TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
875
876         _tbm_bufmgr_check_bo_cnt(bufmgr);
877
878         bo = calloc(1, sizeof(struct _tbm_bo));
879         if (!bo) {
880                 /* LCOV_EXCL_START */
881                 TBM_ERR("memory allocationc failed.");
882                 error = TBM_ERROR_OUT_OF_MEMORY;
883                 goto failed;
884                 /* LCOV_EXCL_STOP */
885         }
886
887         bo->bo_data = tbm_module_alloc_bo_data(bufmgr->module, bo, size, flags, &error);
888         if (!bo->bo_data) {
889                 /* LCOV_EXCL_START */
890                 TBM_ERR("tbm_module_alloc_bo_data failed. size:%d flags:%s error:%d", size, _tbm_flag_to_str(flags), error);
891                 free(bo);
892                 _tbm_set_last_result(error);
893                 _tbm_bufmgr_mutex_unlock();
894                 goto failed;
895                 /* LCOV_EXCL_STOP */
896         }
897
898         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
899
900         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)", bo, size, bo->ref_cnt, _tbm_flag_to_str(bo->flags));
901
902         _tbm_set_last_result(TBM_ERROR_NONE);
903         _tbm_bufmgr_mutex_unlock();
904
905         return bo;
906
907 /* LCOV_EXCL_START */
908 failed:
909         _tbm_set_last_result(error);
910         _tbm_bufmgr_mutex_unlock();
911
912         return NULL;
913 /* LCOV_EXCL_STOP */
914 }
915
916
917 /* LCOV_EXCL_START */
918
919 tbm_bo
920 tbm_bufmgr_internal_alloc_bo_with_format(tbm_bufmgr bufmgr, int format, int bo_idx, int width,
921                                                 int height, int bpp, tbm_bo_memory_type flags, tbm_error_e *error)
922 {
923         tbm_bo bo = NULL;
924
925         _tbm_bufmgr_mutex_lock();
926
927         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
928
929         _tbm_bufmgr_check_bo_cnt(bufmgr);
930
931         bo = calloc(1, sizeof(struct _tbm_bo));
932         if (!bo) {
933                 /* LCOV_EXCL_START */
934                 TBM_ERR("memory allocationc failed.");
935                 *error = TBM_ERROR_OUT_OF_MEMORY;
936                 goto failed;
937                 /* LCOV_EXCL_STOP */
938         }
939
940         bo->bo_data = tbm_module_alloc_bo_data_with_format(bufmgr->module, format, bo_idx, width, height, bpp, flags, error);
941         if (!bo->bo_data) {
942                 /* LCOV_EXCL_START */
943                 free(bo);
944                 goto failed;
945                 /* LCOV_EXCL_STOP */
946         }
947
948         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
949
950         _tbm_bufmgr_mutex_unlock();
951
952         return bo;
953
954 /* LCOV_EXCL_START */
955 failed:
956         _tbm_bufmgr_mutex_unlock();
957
958         return NULL;
959 /* LCOV_EXCL_STOP */
960 }
961
962 tbm_bo
963 tbm_bufmgr_internal_alloc_bo_with_bo_data(tbm_bufmgr bufmgr, tbm_bo_data *bo_data, int flags, tbm_error_e *error)
964 {
965         tbm_bo bo, bo2 = NULL;
966
967         _tbm_bufmgr_mutex_lock();
968
969         *error = TBM_ERROR_NONE;
970
971         TBM_BUFMGR_RETURN_VAL_SET_ERR_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL, *error, TBM_ERROR_INVALID_PARAMETER);
972         TBM_BUFMGR_RETURN_VAL_SET_ERR_IF_FAIL(bo_data, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
973
974         _tbm_bufmgr_check_bo_cnt(bufmgr);
975
976         bo = calloc(1, sizeof(struct _tbm_bo));
977         if (!bo) {
978                 /* LCOV_EXCL_START */
979                 TBM_ERR("memory allocationc failed.");
980                 *error = TBM_ERROR_OUT_OF_MEMORY;
981                 _tbm_bufmgr_mutex_unlock();
982                 return NULL;
983                 /* LCOV_EXCL_STOP */
984         }
985         bo->bo_data = bo_data;
986         bo->get_from_surface_data = 1;
987
988         // return an existed bo if the bo is already created with the same bo_data.
989         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
990         if (bo2) {
991                 bo2->ref_cnt++;
992                 free(bo);
993                 _tbm_bufmgr_mutex_unlock();
994                 return bo2;
995         }
996
997         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
998
999         TBM_TRACE_BO("bo(%p) refcnt(%d), flag(%s)", bo, bo->ref_cnt, _tbm_flag_to_str(bo->flags));
1000
1001         _tbm_bufmgr_mutex_unlock();
1002
1003         return bo;
1004 }
1005
1006 tbm_bo
1007 tbm_bufmgr_internal_import_bo_with_key(tbm_bufmgr bufmgr, unsigned int key)
1008 {
1009         tbm_error_e error = TBM_ERROR_NONE;
1010         tbm_bo bo, bo2;
1011         int flags;
1012
1013         _tbm_bufmgr_mutex_lock();
1014
1015         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1016
1017         _tbm_bufmgr_check_bo_cnt(bufmgr);
1018
1019         bo = calloc(1, sizeof(struct _tbm_bo));
1020         if (!bo) {
1021                 /* LCOV_EXCL_START */
1022                 TBM_ERR("memory allocationc failed.");
1023                 goto failed;
1024                 /* LCOV_EXCL_STOP */
1025         }
1026
1027         bo->bo_data = tbm_module_import_bo_data_with_key(bufmgr->module, bo, key, &error);
1028         if (!bo->bo_data) {
1029                 /* LCOV_EXCL_START */
1030                 TBM_ERR("tbm_module_import_bo_data_with_key failed. tbm_key:%d", key);
1031                 free(bo);
1032                 goto failed;
1033                 /* LCOV_EXCL_STOP */
1034         }
1035
1036         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
1037         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1038         if (bo2) {
1039                 TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list",
1040                                         bo2, bo2->ref_cnt, key, _tbm_flag_to_str(bo2->flags));
1041                 bo2->ref_cnt++;
1042                 free(bo);
1043                 _tbm_set_last_result(TBM_ERROR_NONE);
1044                 _tbm_bufmgr_mutex_unlock();
1045                 return bo2;
1046         }
1047
1048         flags = tbm_bo_data_get_memory_types(bo->bo_data, &error);
1049         if (error != TBM_ERROR_NONE) {
1050                 TBM_WRN("tbm_bo_data_get_memory_types filed. use the default flags:TBM_BO_DEFAULT.");
1051                 flags = TBM_BO_DEFAULT;
1052                 error = TBM_ERROR_NONE;
1053         }
1054
1055         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1056
1057         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list",
1058                                 bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
1059
1060         _tbm_set_last_result(TBM_ERROR_NONE);
1061         _tbm_bufmgr_mutex_unlock();
1062
1063         return bo;
1064
1065 failed:
1066         _tbm_set_last_result(error);
1067         _tbm_bufmgr_mutex_unlock();
1068
1069         return NULL;
1070 }
1071
1072 tbm_bo
1073 tbm_bufmgr_internal_import_bo_with_fd(tbm_bufmgr bufmgr, tbm_fd fd)
1074 {
1075         tbm_error_e error = TBM_ERROR_NONE;
1076         tbm_bo bo, bo2;
1077         int flags;
1078
1079         _tbm_bufmgr_mutex_lock();
1080
1081         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1082
1083         _tbm_bufmgr_check_bo_cnt(bufmgr);
1084
1085         bo = calloc(1, sizeof(struct _tbm_bo));
1086         if (!bo) {
1087                 /* LCOV_EXCL_START */
1088                 TBM_ERR("memory allocationc failed.");
1089                 goto failed;
1090                 /* LCOV_EXCL_STOP */
1091         }
1092
1093         bo->bo_data = tbm_module_import_bo_data_with_fd(bufmgr->module, bo, fd, &error);
1094         if (!bo->bo_data) {
1095                 /* LCOV_EXCL_START */
1096                 TBM_ERR("tbm_module_import_bo_data_with_fd failed. tbm_fd:%d", fd);
1097                 free(bo);
1098                 goto failed;
1099                 /* LCOV_EXCL_STOP */
1100         }
1101
1102         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
1103         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1104         if (bo2) {
1105                 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list",
1106                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1107                 bo2->ref_cnt++;
1108                 free(bo);
1109                 _tbm_set_last_result(TBM_ERROR_NONE);
1110                 _tbm_bufmgr_mutex_unlock();
1111                 return bo2;
1112         }
1113
1114         flags = tbm_bo_data_get_memory_types(bo->bo_data, &error);
1115         if (error != TBM_ERROR_NONE) {
1116                 TBM_WRN("tbm_bo_data_get_memory_types filed. use the default flags:TBM_BO_DEFAULT.");
1117                 flags = TBM_BO_DEFAULT;
1118                 error = TBM_ERROR_NONE;
1119         }
1120
1121         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)",
1122                                 bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1123
1124         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1125
1126         _tbm_set_last_result(TBM_ERROR_NONE);
1127         _tbm_bufmgr_mutex_unlock();
1128
1129         return bo;
1130
1131 failed:
1132         _tbm_set_last_result(error);
1133         _tbm_bufmgr_mutex_unlock();
1134
1135         return NULL;
1136 }
1137
1138 /* LCOV_EXCL_STOP */