tbm_drm_helper: fix Svace TAINTED_INT defect
[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_bufmgr_backend.h"
37 #include "list.h"
38
39 #include <sys/resource.h>
40
41 #ifdef DEBUG
42 int bDebug;
43 #endif
44
45 #ifdef TRACE
46 int bTrace;
47 #endif
48
49 #ifdef HAVE_DLOG
50 int bDlog;
51 #endif
52
53 tbm_bufmgr gBufMgr;
54 int b_dump_queue;
55
56 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
57 static pthread_mutex_t tbm_bufmgr_lock = PTHREAD_MUTEX_INITIALIZER;
58 static __thread tbm_error_e tbm_last_error = TBM_ERROR_NONE;
59
60 static void _tbm_bufmgr_mutex_unlock(void);
61
62 //#define TBM_BUFMGR_INIT_TIME
63
64 #define PREFIX_LIB    "libtbm_"
65 #define SUFFIX_LIB    ".so"
66 #define DEFAULT_LIB   PREFIX_LIB"default"SUFFIX_LIB
67
68 /* values to indicate unspecified fields in XF86ModReqInfo. */
69 #define MAJOR_UNSPEC        0xFF
70 #define MINOR_UNSPEC        0xFF
71 #define PATCH_UNSPEC        0xFFFF
72 #define ABI_VERS_UNSPEC   0xFFFFFFFF
73
74 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
75                         ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
76 #define GET_MODULE_MAJOR_VERSION(vers)    (((vers) >> 24) & 0xFF)
77 #define GET_MODULE_MINOR_VERSION(vers)    (((vers) >> 16) & 0xFF)
78 #define GET_MODULE_PATCHLEVEL(vers)    ((vers) & 0xFFFF)
79
80 /* check condition */
81 #define TBM_BUFMGR_RETURN_IF_FAIL(cond) {\
82         if (!(cond)) {\
83                 TBM_LOG_E("'%s' failed.\n", #cond);\
84                 _tbm_bufmgr_mutex_unlock();\
85                 return;\
86         } \
87 }
88
89 #define TBM_BUFMGR_RETURN_VAL_IF_FAIL(cond, val) {\
90         if (!(cond)) {\
91                 TBM_LOG_E("'%s' failed.\n", #cond);\
92                 _tbm_bufmgr_mutex_unlock();\
93                 return val;\
94         } \
95 }
96
97 enum {
98         LOCK_TRY_ONCE,
99         LOCK_TRY_ALWAYS,
100         LOCK_TRY_NEVER
101 };
102
103 static void
104 _tbm_set_last_result(tbm_error_e err)
105 {
106         tbm_last_error = err;
107 }
108
109 static bool
110 _tbm_bufmgr_mutex_init(void)
111 {
112         static bool tbm_bufmgr_mutex_init = false;
113
114         if (tbm_bufmgr_mutex_init)
115                 return true;
116
117         if (pthread_mutex_init(&tbm_bufmgr_lock, NULL)) {
118                 TBM_LOG_E("fail: Cannot pthread_mutex_init for tbm_bufmgr_lock.\n");
119                 return false;
120         }
121
122         tbm_bufmgr_mutex_init = true;
123
124         return true;
125 }
126
127 static void
128 _tbm_bufmgr_mutex_lock(void)
129 {
130         if (!_tbm_bufmgr_mutex_init()) {
131                 TBM_LOG_E("fail: _tbm_bufmgr_mutex_init()\n");
132                 return;
133         }
134
135         pthread_mutex_lock(&tbm_bufmgr_lock);
136 }
137
138 static void
139 _tbm_bufmgr_mutex_unlock(void)
140 {
141         pthread_mutex_unlock(&tbm_bufmgr_lock);
142 }
143
144 static char *
145 _tbm_flag_to_str(int f)
146 {
147         static char str[255];
148
149         if (f == TBM_BO_DEFAULT)
150                  snprintf(str, 255, "DEFAULT");
151         else {
152                 int c = 0;
153
154                 if (f & TBM_BO_SCANOUT)
155                         c = snprintf(&str[c], 255, "SCANOUT");
156
157                 if (f & TBM_BO_NONCACHABLE) {
158                         if (c)
159                                 c = snprintf(&str[c], 255, ", ");
160                         c = snprintf(&str[c], 255, "NONCACHABLE,");
161                 }
162
163                 if (f & TBM_BO_WC) {
164                         if (c)
165                                 c = snprintf(&str[c], 255, ", ");
166                         c = snprintf(&str[c], 255, "WC");
167                 }
168         }
169
170         return str;
171 }
172
173 /* LCOV_EXCL_START */
174 static void
175 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
176 {
177         static int last_chk_bo_cnt = 0;
178
179         if ((bufmgr->bo_cnt >= 500) && ((bufmgr->bo_cnt % 20) == 0) &&
180                 (bufmgr->bo_cnt > last_chk_bo_cnt)) {
181                 TBM_DEBUG("============TBM BO CNT DEBUG: bo_cnt=%d\n",
182                                 bufmgr->bo_cnt);
183
184                 tbm_bufmgr_debug_show(bufmgr);
185
186                 last_chk_bo_cnt = bufmgr->bo_cnt;
187         }
188 }
189
190 static int
191 _tbm_util_get_max_surface_size(int *w, int *h)
192 {
193         tbm_surface_info_s info;
194         tbm_surface_h surface = NULL;
195         int count = 0;
196
197         *w = 0;
198         *h = 0;
199
200         if (gBufMgr == NULL || LIST_IS_EMPTY(&gBufMgr->surf_list))
201                 return count;
202
203         LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link) {
204                 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
205                         count++;
206                         if (*w < info.width)
207                                 *w = info.width;
208                         if (*h < info.height)
209                                 *h = info.height;
210                 }
211         }
212
213         return count;
214 }
215
216 static void
217 _tbm_util_get_appname_brief(char *brief)
218 {
219         char delim[] = "/";
220         char *token = NULL;
221         char temp[255] = {0,};
222         char *saveptr = NULL;
223
224         token = strtok_r(brief, delim, &saveptr);
225
226         while (token != NULL) {
227                 memset(temp, 0x00, 255 * sizeof(char));
228                 strncpy(temp, token, 254 * sizeof(char));
229                 token = strtok_r(NULL, delim, &saveptr);
230         }
231
232         snprintf(brief, sizeof(temp), "%s", temp);
233 }
234
235 static void
236 _tbm_util_get_appname_from_pid(long pid, char *str)
237 {
238         char fn_cmdline[255] = {0, }, cmdline[255];
239         FILE *fp;
240         int len;
241
242         snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", pid);
243
244         fp = fopen(fn_cmdline, "r");
245         if (fp == 0) {
246                 TBM_LOG_E("cannot file open %s\n", fn_cmdline);
247                 return;
248         }
249
250         if (!fgets(cmdline, 255, fp)) {
251                 TBM_LOG_E("fail to get appname for pid(%ld)\n", pid);
252                 fclose(fp);
253                 return;
254         }
255
256         fclose(fp);
257
258         len = strlen(cmdline);
259         if (len < 1)
260                 memset(cmdline, 0x00, 255);
261         else
262                 cmdline[len] = 0;
263
264         snprintf(str, sizeof(cmdline), "%s", cmdline);
265 }
266 /* LCOV_EXCL_STOP */
267
268 tbm_user_data
269 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
270 {
271         tbm_user_data *old_data = NULL;
272
273         if (LIST_IS_EMPTY(user_data_list))
274                 return NULL;
275
276         LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
277                 if (old_data->key == key)
278                         return old_data;
279         }
280
281         return NULL;
282 }
283
284 tbm_user_data
285 *user_data_create(unsigned long key, tbm_data_free data_free_func)
286 {
287         tbm_user_data *user_data;
288
289         user_data = calloc(1, sizeof(tbm_user_data));
290         if (!user_data) {
291                 TBM_LOG_E("fail to allocate an user_date\n");
292                 return NULL;
293         }
294
295         user_data->key = key;
296         user_data->free_func = data_free_func;
297
298         return user_data;
299 }
300
301 void
302 user_data_delete(tbm_user_data *user_data)
303 {
304         if (user_data->data && user_data->free_func)
305                 user_data->free_func(user_data->data);
306
307         LIST_DEL(&user_data->item_link);
308
309         free(user_data);
310 }
311
312 static int
313 _bo_lock(tbm_bo bo, int device, int opt)
314 {
315         tbm_bufmgr bufmgr = bo->bufmgr;
316         int ret = 1;
317
318         if (bufmgr->backend->bo_lock)
319                 ret = bufmgr->backend->bo_lock(bo, device, opt);
320
321         return ret;
322 }
323
324 static void
325 _bo_unlock(tbm_bo bo)
326 {
327         tbm_bufmgr bufmgr = bo->bufmgr;
328
329         if (bufmgr->backend->bo_unlock)
330                 bufmgr->backend->bo_unlock(bo);
331 }
332
333 static int
334 _tbm_bo_lock(tbm_bo bo, int device, int opt)
335 {
336         tbm_bufmgr bufmgr;
337         int old, ret;
338
339         if (!bo)
340                 return 0;
341
342         bufmgr = bo->bufmgr;
343
344         /* do not try to lock the bo */
345         if (bufmgr->lock_type == LOCK_TRY_NEVER)
346                 return 1;
347
348         if (bo->lock_cnt < 0) {
349                 TBM_LOG_E("error bo:%p LOCK_CNT=%d\n",
350                         bo, bo->lock_cnt);
351                 return 0;
352         }
353
354         old = bo->lock_cnt;
355
356         switch (bufmgr->lock_type) {
357         case LOCK_TRY_ONCE:
358                 if (bo->lock_cnt == 0) {
359                         _tbm_bufmgr_mutex_unlock();
360                         ret = _bo_lock(bo, device, opt);
361                         _tbm_bufmgr_mutex_lock();
362                         if (ret)
363                                 bo->lock_cnt++;
364                 } else
365                         ret = 1;
366                 break;
367         case LOCK_TRY_ALWAYS:
368                 _tbm_bufmgr_mutex_unlock();
369                 ret = _bo_lock(bo, device, opt);
370                 _tbm_bufmgr_mutex_lock();
371                 if (ret)
372                         bo->lock_cnt++;
373                 break;
374         default:
375                 TBM_LOG_E("error bo:%p lock_type[%d] is wrong.\n",
376                                 bo, bufmgr->lock_type);
377                 ret = 0;
378                 break;
379         }
380
381         TBM_DBG_LOCK(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
382
383         return ret;
384 }
385
386 static void
387 _tbm_bo_unlock(tbm_bo bo)
388 {
389         tbm_bufmgr bufmgr;
390         int old;
391
392         if (!bo)
393                 return;
394
395         bufmgr = bo->bufmgr;
396
397         /* do not try to unlock the bo */
398         if (bufmgr->lock_type == LOCK_TRY_NEVER)
399                 return;
400
401         old = bo->lock_cnt;
402
403         switch (bufmgr->lock_type) {
404         case LOCK_TRY_ONCE:
405                 if (bo->lock_cnt > 0) {
406                         bo->lock_cnt--;
407                         if (bo->lock_cnt == 0)
408                                 _bo_unlock(bo);
409                 }
410                 break;
411         case LOCK_TRY_ALWAYS:
412                 if (bo->lock_cnt > 0) {
413                         bo->lock_cnt--;
414                         _bo_unlock(bo);
415                 }
416                 break;
417         default:
418                 TBM_LOG_E("error bo:%p lock_type[%d] is wrong.\n",
419                                 bo, bufmgr->lock_type);
420                 break;
421         }
422
423         if (bo->lock_cnt < 0)
424                 bo->lock_cnt = 0;
425
426         TBM_DBG_LOCK(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
427 }
428
429 static int
430 _tbm_bo_is_valid(tbm_bo bo)
431 {
432         tbm_bo old_data = NULL;
433
434         if (bo == NULL || gBufMgr == NULL) {
435                 TBM_LOG_E("error: bo is NULL or tbm_bufmgr was deinited\n");
436                 return 0;
437         }
438
439         if (LIST_IS_EMPTY(&gBufMgr->bo_list)) {
440                 TBM_LOG_E("error: gBufMgr->bo_list is EMPTY.\n");
441                 return 0;
442         }
443
444         LIST_FOR_EACH_ENTRY(old_data, &gBufMgr->bo_list, item_link) {
445                 if (old_data == bo)
446                         return 1;
447         }
448
449         TBM_LOG_E("error: No valid bo(%p).\n", bo);
450
451         return 0;
452 }
453
454 /* LCOV_EXCL_START */
455 static int
456 _check_version(TBMModuleVersionInfo *data)
457 {
458         int abimaj, abimin;
459         int vermaj, vermin;
460
461         abimaj = GET_ABI_MAJOR(data->abiversion);
462         abimin = GET_ABI_MINOR(data->abiversion);
463
464         TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
465             data->modname ? data->modname : "UNKNOWN!",
466             data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
467
468         vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
469         vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
470
471         TBM_DBG("TBM ABI version %d.%d\n",
472             vermaj, vermin);
473
474         if (abimaj != vermaj) {
475                 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
476                         abimaj, vermaj);
477                 return 0;
478         } else if (abimin > vermin) {
479                 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
480                         abimin, vermin);
481                 return 0;
482         }
483
484         return 1;
485 }
486
487 static int
488 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
489 {
490         char path[PATH_MAX] = {0, };
491         TBMModuleVersionInfo *vers;
492         TBMModuleData *initdata;
493         ModuleInitProc init;
494         void *module_data;
495
496         snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
497
498         module_data = dlopen(path, RTLD_LAZY);
499         if (!module_data) {
500                 TBM_LOG_E("failed to load module: %s(%s)\n", dlerror(), file);
501                 return 0;
502         }
503
504         initdata = dlsym(module_data, "tbmModuleData");
505         if (!initdata) {
506                 TBM_LOG_E("Error: module does not have data object.\n");
507                 goto err;
508         }
509
510         vers = initdata->vers;
511         if (!vers) {
512                 TBM_LOG_E("Error: module does not supply version information.\n");
513                 goto err;
514         }
515
516         init = initdata->init;
517         if (!init) {
518                 TBM_LOG_E("Error: module does not supply init symbol.\n");
519                 goto err;
520         }
521
522         if (!_check_version(vers)) {
523                 TBM_LOG_E("Fail to check version.\n");
524                 goto err;
525         }
526
527         if (!init(bufmgr, fd)) {
528                 TBM_LOG_E("Fail to init module(%s)\n", file);
529                 goto err;
530         }
531
532         if (!bufmgr->backend || !bufmgr->backend->priv) {
533                 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n", file);
534                 goto err;
535         }
536
537         bufmgr->module_data = module_data;
538
539         TBM_DBG("Success to load module(%s)\n", file);
540
541         return 1;
542
543 err:
544         dlclose(module_data);
545         return 0;
546 }
547
548 static int
549 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
550 {
551         struct dirent **namelist;
552         int ret = 0, n;
553
554         /* load bufmgr priv from default lib */
555         if (_tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB))
556                 return 1;
557
558         /* load bufmgr priv from configured path */
559         n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
560         if (n < 0) {
561                 TBM_LOG_E("no files : %s\n", BUFMGR_MODULE_DIR);
562                 return 0;
563         }
564
565         while (n--) {
566                 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
567                         const char *p = strstr(namelist[n]->d_name, SUFFIX_LIB);
568
569                         if (p && !strcmp(p, SUFFIX_LIB))
570                                 ret = _tbm_bufmgr_load_module(bufmgr, fd,
571                                                         namelist[n]->d_name);
572                 }
573
574                 free(namelist[n]);
575         }
576
577         free(namelist);
578
579         return ret;
580 }
581 /* LCOV_EXCL_STOP */
582
583 tbm_bufmgr
584 tbm_bufmgr_init(int fd)
585 {
586 #ifdef TBM_BUFMGR_INIT_TIME
587         struct timeval start_tv, end_tv;
588 #endif
589         char *env;
590
591 #ifdef TBM_BUFMGR_INIT_TIME
592         /* get the start tv */
593         gettimeofday(&start_tv, NULL);
594 #endif
595
596         /* LCOV_EXCL_START */
597 #ifdef HAVE_DLOG
598         env = getenv("TBM_DLOG");
599         if (env) {
600                 bDlog = atoi(env);
601                 TBM_LOG_D("TBM_DLOG=%s\n", env);
602         } else
603                 bDlog = 1;
604 #endif
605
606 #ifdef DEBUG
607         env = getenv("TBM_DEBUG");
608         if (env) {
609                 bDebug = atoi(env);
610                 TBM_LOG_D("TBM_DEBUG=%s\n", env);
611         } else
612                 bDebug = 0;
613 #endif
614
615 #ifdef TRACE
616         env = getenv("TBM_TRACE");
617         if (env) {
618                 bTrace = atoi(env);
619                 TBM_LOG_D("TBM_TRACE=%s\n", env);
620         } else
621                 bTrace = 0;
622 #endif
623         /* LCOV_EXCL_STOP */
624
625         pthread_mutex_lock(&gLock);
626
627         if (fd >= 0) {
628                 TBM_LOG_W("!!!!!WARNING:: The tbm_bufmgr_init DOSE NOT use argument fd ANYMORE.\n");
629                 TBM_LOG_W("!!!!!WARNING:: IT WILL BE CHANGED like tbm_bufmgr_init(int fd) --> tbm_bufmgr_init(void).\n");
630         }
631
632         /* initialize buffer manager */
633         if (gBufMgr) {
634                 gBufMgr->ref_count++;
635                 TBM_TRACE("reuse  tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
636                 pthread_mutex_unlock(&gLock);
637                 return gBufMgr;
638         }
639
640         TBM_DBG("bufmgr init\n");
641
642         /* allocate bufmgr */
643         gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
644         if (!gBufMgr) {
645                 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
646                 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
647                 pthread_mutex_unlock(&gLock);
648                 return NULL;
649         }
650
651         gBufMgr->fd = fd;
652
653         /* load bufmgr priv from env */
654         if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
655                 /* LCOV_EXCL_START */
656                 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
657                 TBM_LOG_E("error : Fail to load bufmgr backend\n");
658                 free(gBufMgr);
659                 gBufMgr = NULL;
660                 pthread_mutex_unlock(&gLock);
661                 return NULL;
662                 /* LCOV_EXCL_STOP */
663         }
664
665         /* log for tbm backend_flag */
666         TBM_DBG("backend flag:%x:", gBufMgr->backend->flags);
667         TBM_DBG("\n");
668
669         gBufMgr->ref_count = 1;
670
671         TBM_DBG("create tizen bufmgr:%p ref_count:%d\n",
672             gBufMgr, gBufMgr->ref_count);
673
674         /* setup the lock_type */
675         env = getenv("BUFMGR_LOCK_TYPE");
676         if (env && !strcmp(env, "always"))
677                 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
678         else if (env && !strcmp(env, "none"))
679                 gBufMgr->lock_type = LOCK_TRY_NEVER;
680         else if (env && !strcmp(env, "once"))
681                 gBufMgr->lock_type = LOCK_TRY_ONCE;
682         else
683                 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
684
685         TBM_DBG("BUFMGR_LOCK_TYPE=%s\n", env ? env : "default:once");
686
687         TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
688
689         /* intialize bo_list */
690         LIST_INITHEAD(&gBufMgr->bo_list);
691
692         /* intialize surf_list */
693         LIST_INITHEAD(&gBufMgr->surf_list);
694
695         /* intialize surf_queue_list */
696         LIST_INITHEAD(&gBufMgr->surf_queue_list);
697
698         /* intialize debug_key_list */
699         LIST_INITHEAD(&gBufMgr->debug_key_list);
700
701 #ifdef TBM_BUFMGR_INIT_TIME
702         /* get the end tv */
703         gettimeofday(&end_tv, NULL);
704         TBM_LOG_I("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)));
705 #endif
706
707         pthread_mutex_unlock(&gLock);
708
709         return gBufMgr;
710 }
711
712 void
713 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
714 {
715         TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
716
717         pthread_mutex_lock(&gLock);
718
719         if (!gBufMgr) {
720                 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
721                 pthread_mutex_unlock(&gLock);
722                 return;
723         }
724
725         bufmgr->ref_count--;
726         if (bufmgr->ref_count > 0) {
727                 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
728                 pthread_mutex_unlock(&gLock);
729                 return;
730         }
731
732         /* destroy bo_list */
733         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
734                 tbm_bo bo = NULL, tmp;
735
736                 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
737                         TBM_LOG_E("Un-freed bo(%p, ref:%d)\n", bo, bo->ref_cnt);
738                         bo->ref_cnt = 1;
739                         tbm_bo_unref(bo);
740                 }
741         }
742
743         /* destroy surf_list */
744         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
745                 tbm_surface_h surf = NULL, tmp;
746
747                 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &bufmgr->surf_list, item_link) {
748                         TBM_LOG_E("Un-freed surf(%p, ref:%d)\n", surf, surf->refcnt);
749                         tbm_surface_destroy(surf);
750                 }
751         }
752
753         /* destroy bufmgr priv */
754         bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
755         bufmgr->backend->priv = NULL;
756         tbm_backend_free(bufmgr->backend);
757         bufmgr->backend = NULL;
758
759         TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
760
761         dlclose(bufmgr->module_data);
762
763         if (bufmgr->fd > 0)
764                 close(bufmgr->fd);
765
766         free(bufmgr);
767         gBufMgr = NULL;
768
769         pthread_mutex_unlock(&gLock);
770 }
771
772 int
773 tbm_bo_size(tbm_bo bo)
774 {
775         tbm_bufmgr bufmgr = gBufMgr;
776         int size;
777
778         _tbm_bufmgr_mutex_lock();
779
780         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
781         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
782
783         size = bufmgr->backend->bo_size(bo);
784
785         TBM_TRACE("bo(%p) size(%d)\n", bo, size);
786
787         _tbm_bufmgr_mutex_unlock();
788
789         return size;
790 }
791
792 tbm_bo
793 tbm_bo_ref(tbm_bo bo)
794 {
795         _tbm_bufmgr_mutex_lock();
796
797         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
798         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
799
800         bo->ref_cnt++;
801
802         TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
803
804         _tbm_bufmgr_mutex_unlock();
805
806         return bo;
807 }
808
809 void
810 tbm_bo_unref(tbm_bo bo)
811 {
812         tbm_bufmgr bufmgr = gBufMgr;
813
814         _tbm_bufmgr_mutex_lock();
815
816         TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
817         TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
818
819         TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
820
821         if (bo->ref_cnt <= 0) {
822                 _tbm_bufmgr_mutex_unlock();
823                 return;
824         }
825
826         bo->ref_cnt--;
827         if (bo->ref_cnt == 0) {
828                 /* destory the user_data_list */
829                 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
830                         tbm_user_data *old_data = NULL, *tmp;
831
832                         LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
833                                         &bo->user_data_list, item_link) {
834                                 TBM_DBG("free user_data\n");
835                                 user_data_delete(old_data);
836                         }
837                 }
838
839                 while (bo->lock_cnt > 0) {
840                         TBM_LOG_E("error lock_cnt:%d\n", bo->lock_cnt);
841                         _bo_unlock(bo);
842                         bo->lock_cnt--;
843                 }
844
845                 /* call the bo_free */
846                 bufmgr->backend->bo_free(bo);
847                 bo->priv = NULL;
848
849                 LIST_DEL(&bo->item_link);
850                 free(bo);
851
852                 bufmgr->bo_cnt--;
853         }
854
855         _tbm_bufmgr_mutex_unlock();
856 }
857
858 tbm_bo
859 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
860 {
861         void *bo_priv;
862         tbm_bo bo;
863
864         _tbm_bufmgr_mutex_lock();
865
866         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
867         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
868         TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
869
870         bo = calloc(1, sizeof(struct _tbm_bo));
871         if (!bo) {
872                 TBM_LOG_E("error: fail to create of tbm_bo size(%d) flag(%s)\n",
873                                 size, _tbm_flag_to_str(flags));
874                 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
875                 _tbm_bufmgr_mutex_unlock();
876                 return NULL;
877         }
878
879         _tbm_util_check_bo_cnt(bufmgr);
880
881         bo->bufmgr = bufmgr;
882
883         bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
884         if (!bo_priv) {
885                 TBM_LOG_E("error: fail to create of tbm_bo size(%d) flag(%s)\n",
886                                 size, _tbm_flag_to_str(flags));
887                 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
888                 free(bo);
889                 _tbm_bufmgr_mutex_unlock();
890                 return NULL;
891         }
892
893         bufmgr->bo_cnt++;
894
895         bo->ref_cnt = 1;
896         bo->flags = flags;
897         bo->priv = bo_priv;
898
899         TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
900                         _tbm_flag_to_str(bo->flags));
901
902         LIST_INITHEAD(&bo->user_data_list);
903
904         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
905
906         _tbm_bufmgr_mutex_unlock();
907
908         return bo;
909 }
910
911 tbm_bo
912 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
913 {
914         void *bo_priv;
915         tbm_bo bo;
916
917         _tbm_bufmgr_mutex_lock();
918
919         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
920         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
921
922         if (!bufmgr->backend->bo_import) {
923                 _tbm_bufmgr_mutex_unlock();
924                 return NULL;
925         }
926
927         _tbm_util_check_bo_cnt(bufmgr);
928
929         bo = calloc(1, sizeof(struct _tbm_bo));
930         if (!bo) {
931                 TBM_LOG_E("error: fail to import of tbm_bo by key(%d)\n", key);
932                 _tbm_bufmgr_mutex_unlock();
933                 return NULL;
934         }
935
936         bo->bufmgr = bufmgr;
937
938         bo_priv = bufmgr->backend->bo_import(bo, key);
939         if (!bo_priv) {
940                 TBM_LOG_E("error: fail to import of tbm_bo by key(%d)\n", key);
941                 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
942                 free(bo);
943                 _tbm_bufmgr_mutex_unlock();
944                 return NULL;
945         }
946
947         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
948                 tbm_bo bo2 = NULL;
949
950                 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
951                         if (bo2->priv == bo_priv) {
952                                 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
953                                                 bo2, bo2->ref_cnt, key,
954                                                 _tbm_flag_to_str(bo2->flags));
955                                 bo2->ref_cnt++;
956                                 free(bo);
957                                 _tbm_bufmgr_mutex_unlock();
958                                 return bo2;
959                         }
960                 }
961         }
962
963         bufmgr->bo_cnt++;
964
965         bo->ref_cnt = 1;
966         bo->priv = bo_priv;
967
968         if (bufmgr->backend->bo_get_flags)
969                 bo->flags = bufmgr->backend->bo_get_flags(bo);
970         else
971                 bo->flags = TBM_BO_DEFAULT;
972
973         TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
974                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
975
976         LIST_INITHEAD(&bo->user_data_list);
977
978         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
979
980         _tbm_bufmgr_mutex_unlock();
981
982         return bo;
983 }
984
985 tbm_bo
986 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
987 {
988         void *bo_priv;
989         tbm_bo bo;
990
991         _tbm_bufmgr_mutex_lock();
992
993         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
994         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
995
996         if (!bufmgr->backend->bo_import_fd) {
997                 _tbm_bufmgr_mutex_unlock();
998                 return NULL;
999         }
1000
1001         _tbm_util_check_bo_cnt(bufmgr);
1002
1003         bo = calloc(1, sizeof(struct _tbm_bo));
1004         if (!bo) {
1005                 TBM_LOG_E("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1006                 _tbm_bufmgr_mutex_unlock();
1007                 return NULL;
1008         }
1009
1010         bo->bufmgr = bufmgr;
1011
1012         bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1013         if (!bo_priv) {
1014                 TBM_LOG_E("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1015                 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
1016                 free(bo);
1017                 _tbm_bufmgr_mutex_unlock();
1018                 return NULL;
1019         }
1020
1021         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1022                 tbm_bo bo2 = NULL;
1023
1024                 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1025                         if (bo2->priv == bo_priv) {
1026                                 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1027                                                 bo2, bo2->ref_cnt, fd,
1028                                                 _tbm_flag_to_str(bo2->flags));
1029                                 bo2->ref_cnt++;
1030                                 free(bo);
1031                                 _tbm_bufmgr_mutex_unlock();
1032                                 return bo2;
1033                         }
1034                 }
1035         }
1036
1037         bufmgr->bo_cnt++;
1038
1039         bo->ref_cnt = 1;
1040         bo->priv = bo_priv;
1041
1042         if (bufmgr->backend->bo_get_flags)
1043                 bo->flags = bufmgr->backend->bo_get_flags(bo);
1044         else
1045                 bo->flags = TBM_BO_DEFAULT;
1046
1047         TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
1048                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1049
1050         LIST_INITHEAD(&bo->user_data_list);
1051
1052         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1053
1054         _tbm_bufmgr_mutex_unlock();
1055
1056         return bo;
1057 }
1058
1059 tbm_key
1060 tbm_bo_export(tbm_bo bo)
1061 {
1062         tbm_bufmgr bufmgr = gBufMgr;
1063         tbm_key ret;
1064
1065         _tbm_bufmgr_mutex_lock();
1066
1067         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1068         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1069
1070         if (!bufmgr->backend->bo_export) {
1071                 _tbm_bufmgr_mutex_unlock();
1072                 return 0;
1073         }
1074
1075         ret = bufmgr->backend->bo_export(bo);
1076         if (!ret) {
1077                 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1078                 TBM_LOG_E("error: bo(%p) tbm_key(%d)\n", bo, ret);
1079                 _tbm_bufmgr_mutex_unlock();
1080                 return ret;
1081         }
1082
1083         TBM_TRACE("bo(%p) tbm_key(%u)\n", bo, ret);
1084
1085         _tbm_bufmgr_mutex_unlock();
1086
1087         return ret;
1088 }
1089
1090 tbm_fd
1091 tbm_bo_export_fd(tbm_bo bo)
1092 {
1093         tbm_bufmgr bufmgr = gBufMgr;
1094         tbm_fd ret;
1095
1096         _tbm_bufmgr_mutex_lock();
1097
1098         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), -1);
1099         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1100
1101         if (!bufmgr->backend->bo_export_fd) {
1102                 _tbm_bufmgr_mutex_unlock();
1103                 return -1;
1104         }
1105
1106         ret = bufmgr->backend->bo_export_fd(bo);
1107         if (ret < 0) {
1108                 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1109                 TBM_LOG_E("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1110                 _tbm_bufmgr_mutex_unlock();
1111                 return ret;
1112         }
1113
1114         TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1115
1116         _tbm_bufmgr_mutex_unlock();
1117
1118         return ret;
1119 }
1120
1121 tbm_bo_handle
1122 tbm_bo_get_handle(tbm_bo bo, int device)
1123 {
1124         tbm_bufmgr bufmgr = gBufMgr;
1125         tbm_bo_handle bo_handle;
1126
1127         _tbm_bufmgr_mutex_lock();
1128
1129         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1130         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1131
1132         bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1133         if (bo_handle.ptr == NULL) {
1134                 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1135                 TBM_LOG_E("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1136                 _tbm_bufmgr_mutex_unlock();
1137                 return (tbm_bo_handle) NULL;
1138         }
1139
1140         TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1141
1142         _tbm_bufmgr_mutex_unlock();
1143
1144         return bo_handle;
1145 }
1146
1147 tbm_bo_handle
1148 tbm_bo_map(tbm_bo bo, int device, int opt)
1149 {
1150         tbm_bufmgr bufmgr = gBufMgr;
1151         tbm_bo_handle bo_handle;
1152
1153         _tbm_bufmgr_mutex_lock();
1154
1155         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1156         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1157
1158         if (!_tbm_bo_lock(bo, device, opt)) {
1159                 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1160                 TBM_LOG_E("error: fail to lock bo:%p)\n", bo);
1161                 _tbm_bufmgr_mutex_unlock();
1162                 return (tbm_bo_handle) NULL;
1163         }
1164
1165         bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1166         if (bo_handle.ptr == NULL) {
1167                 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1168                 TBM_LOG_E("error: fail to map bo:%p\n", bo);
1169                 _tbm_bo_unlock(bo);
1170                 _tbm_bufmgr_mutex_unlock();
1171                 return (tbm_bo_handle) NULL;
1172         }
1173
1174         /* increase the map_count */
1175         bo->map_cnt++;
1176
1177         TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1178
1179         _tbm_bufmgr_mutex_unlock();
1180
1181         return bo_handle;
1182 }
1183
1184 int
1185 tbm_bo_unmap(tbm_bo bo)
1186 {
1187         tbm_bufmgr bufmgr = gBufMgr;
1188         int ret;
1189
1190         _tbm_bufmgr_mutex_lock();
1191
1192         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1193         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1194
1195         ret = bufmgr->backend->bo_unmap(bo);
1196         if (!ret) {
1197                 TBM_LOG_E("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1198                 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1199                 _tbm_bufmgr_mutex_unlock();
1200                 return ret;
1201         }
1202
1203         /* decrease the map_count */
1204         bo->map_cnt--;
1205
1206         TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1207
1208         _tbm_bo_unlock(bo);
1209
1210         _tbm_bufmgr_mutex_unlock();
1211
1212         return ret;
1213 }
1214
1215 int
1216 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1217 {
1218         tbm_bufmgr bufmgr = gBufMgr;
1219         void *temp;
1220
1221         _tbm_bufmgr_mutex_lock();
1222
1223         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1224         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1225         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1226
1227         TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1228
1229         if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1230                 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1231                 TBM_LOG_E("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1232                 _tbm_bufmgr_mutex_unlock();
1233                 return 0;
1234         }
1235
1236         TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1237
1238         temp = bo1->priv;
1239         bo1->priv = bo2->priv;
1240         bo2->priv = temp;
1241
1242         _tbm_bufmgr_mutex_unlock();
1243
1244         return 1;
1245 }
1246
1247 int
1248 tbm_bo_locked(tbm_bo bo)
1249 {
1250         tbm_bufmgr bufmgr = gBufMgr;
1251
1252         _tbm_bufmgr_mutex_lock();
1253
1254         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1255         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1256
1257         if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1258                 TBM_LOG_E("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1259                 _tbm_bufmgr_mutex_unlock();
1260                 return 0;
1261         }
1262
1263         if (bo->lock_cnt > 0) {
1264                 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1265                 _tbm_bufmgr_mutex_unlock();
1266                 return 1;
1267         }
1268
1269         TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1270         _tbm_bufmgr_mutex_unlock();
1271
1272         return 0;
1273 }
1274
1275 int
1276 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1277                      tbm_data_free data_free_func)
1278 {
1279         tbm_user_data *data;
1280
1281         _tbm_bufmgr_mutex_lock();
1282
1283         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1284         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1285
1286         /* check if the data according to the key exist if so, return false. */
1287         data = user_data_lookup(&bo->user_data_list, key);
1288         if (data) {
1289                 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1290                 _tbm_bufmgr_mutex_unlock();
1291                 return 0;
1292         }
1293
1294         data = user_data_create(key, data_free_func);
1295         if (!data) {
1296                 TBM_LOG_E("error: bo(%p) key(%lu)\n", bo, key);
1297                 _tbm_bufmgr_mutex_unlock();
1298                 return 0;
1299         }
1300
1301         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1302
1303         LIST_ADD(&data->item_link, &bo->user_data_list);
1304
1305         _tbm_bufmgr_mutex_unlock();
1306
1307         return 1;
1308 }
1309
1310 int
1311 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1312 {
1313         tbm_user_data *old_data;
1314
1315         _tbm_bufmgr_mutex_lock();
1316
1317         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1318         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1319
1320         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1321                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1322                 _tbm_bufmgr_mutex_unlock();
1323                 return 0;
1324         }
1325
1326         old_data = user_data_lookup(&bo->user_data_list, key);
1327         if (!old_data) {
1328                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1329                 _tbm_bufmgr_mutex_unlock();
1330                 return 0;
1331         }
1332
1333         if (old_data->data && old_data->free_func)
1334                 old_data->free_func(old_data->data);
1335         old_data->data = data;
1336
1337         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1338
1339         _tbm_bufmgr_mutex_unlock();
1340
1341         return 1;
1342 }
1343
1344 int
1345 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1346 {
1347         tbm_user_data *old_data;
1348
1349         _tbm_bufmgr_mutex_lock();
1350
1351         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1352         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1353
1354         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1355                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1356                 _tbm_bufmgr_mutex_unlock();
1357                 return 0;
1358         }
1359
1360         old_data = user_data_lookup(&bo->user_data_list, key);
1361         if (!old_data) {
1362                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1363                 *data = NULL;
1364                 _tbm_bufmgr_mutex_unlock();
1365                 return 0;
1366         }
1367
1368         *data = old_data->data;
1369
1370         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1371
1372         _tbm_bufmgr_mutex_unlock();
1373
1374         return 1;
1375 }
1376
1377 int
1378 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1379 {
1380         tbm_user_data *old_data;
1381
1382         _tbm_bufmgr_mutex_lock();
1383
1384         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1385         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1386
1387         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1388                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1389                 _tbm_bufmgr_mutex_unlock();
1390                 return 0;
1391         }
1392
1393         old_data = user_data_lookup(&bo->user_data_list, key);
1394         if (!old_data) {
1395                 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1396                 _tbm_bufmgr_mutex_unlock();
1397                 return 0;
1398         }
1399
1400         TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1401
1402         user_data_delete(old_data);
1403
1404         _tbm_bufmgr_mutex_unlock();
1405
1406         return 1;
1407 }
1408
1409 unsigned int
1410 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1411 {
1412         unsigned int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1413
1414         _tbm_bufmgr_mutex_lock();
1415
1416         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1417         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1418
1419         TBM_TRACE("tbm_bufmgr(%p) capability(%u)\n", bufmgr, bufmgr->capabilities);
1420
1421         capabilities = bufmgr->capabilities;
1422
1423         _tbm_bufmgr_mutex_unlock();
1424
1425         return capabilities;
1426 }
1427
1428 int
1429 tbm_bo_get_flags(tbm_bo bo)
1430 {
1431         int flags;
1432
1433         _tbm_bufmgr_mutex_lock();
1434
1435         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1436         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1437
1438         flags = bo->flags;
1439
1440         TBM_TRACE("bo(%p)\n", bo);
1441
1442         _tbm_bufmgr_mutex_unlock();
1443
1444         return flags;
1445 }
1446
1447 /* LCOV_EXCL_START */
1448 tbm_error_e
1449 tbm_get_last_error(void)
1450 {
1451         return tbm_last_error;
1452 }
1453
1454 void
1455 tbm_bufmgr_debug_tbm_info_get(tbm_bufmgr bufmgr, char *str, int *len)
1456 {
1457         char app_name[255] = {0,}, title[512] = {0,};
1458         tbm_surface_debug_data *debug_old_data = NULL;
1459
1460         pthread_mutex_lock(&gLock);
1461
1462         if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
1463                 TBM_LOG_E("invalid bufmgr\n");
1464                 pthread_mutex_unlock(&gLock);
1465                 return;
1466         }
1467
1468         TBM_SNPRINTF(str, len, "\n");
1469         _tbm_util_get_appname_from_pid(getpid(), app_name);
1470         _tbm_util_get_appname_brief(app_name);
1471         TBM_SNPRINTF(str, len, "============TBM DEBUG: %s(%d)===========================\n",
1472                   app_name, getpid());
1473
1474         snprintf(title, 255, "%s", "no  surface     refcnt  width  height  bpp  size    n_b  n_p  flags  format    app_name       ");
1475
1476         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1477                 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
1478                         strncat(title, "  ", 3);
1479                         strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1480                 }
1481         }
1482
1483         TBM_SNPRINTF(str, len, "[tbm_surface information]\n");
1484         TBM_SNPRINTF(str, len, "%s\n", title);
1485
1486         /* show the tbm_surface information in surf_list */
1487         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1488                 tbm_surface_h surf = NULL;
1489                 int surf_cnt = 0;
1490
1491                 LIST_FOR_EACH_ENTRY(surf, &bufmgr->surf_list, item_link) {
1492                         char data[512] = {0,};
1493                         unsigned int pid;
1494                         int i;
1495
1496                         pid = _tbm_surface_internal_get_debug_pid(surf);
1497                         if (!pid) {
1498                                 /* if pid is null, set the self_pid */
1499                                 pid = getpid();
1500                         }
1501
1502                         memset(app_name, 0x0, 255 * sizeof(char));
1503                         _tbm_util_get_appname_from_pid(pid, app_name);
1504                         _tbm_util_get_appname_brief(app_name);
1505
1506                         snprintf(data, 255, "%-2d  %-9p    %-4d  %-5u  %-6u  %-3u  %-6u   %-2d   %-2d    %-3d  %-8s  %-15s",
1507                                   ++surf_cnt,
1508                                   surf,
1509                                   surf->refcnt,
1510                                   surf->info.width,
1511                                   surf->info.height,
1512                                   surf->info.bpp,
1513                                   surf->info.size / 1024,
1514                                   surf->num_bos,
1515                                   surf->num_planes,
1516                                   surf->flags,
1517                                   _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1518                                   app_name);
1519
1520                         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1521                                 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
1522                                         char *value;
1523
1524                                         strncat(data, "  ", 3);
1525
1526                                         value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1527                                         if (value)
1528                                                 strncat(data, value, strlen(value) + 1);
1529                                         else
1530                                                 strncat(data, "none", 5);
1531                                 }
1532                         }
1533                         TBM_SNPRINTF(str, len, "%s\n", data);
1534
1535                         for (i = 0; i < surf->num_bos; i++) {
1536                                 TBM_SNPRINTF(str, len, " bo:%-12p  %-26d%-10d\n",
1537                                           surf->bos[i],
1538                                           surf->bos[i]->ref_cnt,
1539                                           bufmgr->backend->bo_size(surf->bos[i]) / 1024);
1540                         }
1541                 }
1542         } else
1543                 TBM_SNPRINTF(str, len, " no tbm_surfaces.\n");
1544         TBM_SNPRINTF(str, len, "\n");
1545
1546         TBM_SNPRINTF(str, len, "[tbm_bo information]\n");
1547         TBM_SNPRINTF(str, len, "no  bo          refcnt  size    lock_cnt  map_cnt  flags  surface\n");
1548
1549         /* show the tbm_bo information in bo_list */
1550         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1551                 int bo_cnt = 0;
1552                 tbm_bo bo = NULL;
1553
1554                 LIST_FOR_EACH_ENTRY(bo, &bufmgr->bo_list, item_link) {
1555                         TBM_SNPRINTF(str, len, "%-4d%-11p   %-4d  %-6d     %-5d     %-4u    %-3d  %-11p\n",
1556                                   ++bo_cnt,
1557                                   bo,
1558                                   bo->ref_cnt,
1559                                   bufmgr->backend->bo_size(bo) / 1024,
1560                                   bo->lock_cnt,
1561                                   bo->map_cnt,
1562                                   bo->flags,
1563                                   bo->surface);
1564                 }
1565         } else
1566                 TBM_SNPRINTF(str, len, "no tbm_bos.\n");
1567         TBM_SNPRINTF(str, len, "\n");
1568
1569         TBM_SNPRINTF(str, len, "===============================================================\n");
1570
1571         pthread_mutex_unlock(&gLock);
1572 }
1573
1574 void
1575 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1576 {
1577         char str[1024*4];
1578         int len = sizeof(str);
1579         tbm_bufmgr_debug_tbm_info_get(bufmgr, str, &len);
1580         TBM_DEBUG("     %s", str);
1581 }
1582
1583 void
1584 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1585 {
1586         _tbm_bufmgr_mutex_lock();
1587
1588         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1589         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1590
1591 #ifdef TRACE
1592         TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1593         bTrace = onoff;
1594 #endif
1595
1596         _tbm_bufmgr_mutex_unlock();
1597 }
1598
1599 int
1600 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1601 {
1602         pthread_mutex_lock(&gLock);
1603
1604         if (onoff == 0) {
1605                 TBM_LOG_D("count=%d onoff=%d\n", count, onoff);
1606                 b_dump_queue = 0;
1607                 tbm_surface_internal_dump_end();
1608         } else {
1609                 int w, h;
1610
1611                 if (path == NULL) {
1612                         TBM_LOG_E("path is null");
1613                         pthread_mutex_unlock(&gLock);
1614                         return 0;
1615                 }
1616                 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1617
1618                 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1619                         TBM_LOG_E("Fail to get tbm_surface size.\n");
1620                         pthread_mutex_unlock(&gLock);
1621                         return 0;
1622                 }
1623
1624                 tbm_surface_internal_dump_start(path, w, h, count);
1625                 b_dump_queue = 1;
1626         }
1627
1628         pthread_mutex_unlock(&gLock);
1629         return 1;
1630 }
1631
1632 int
1633 tbm_bufmgr_debug_dump_all(char *path)
1634 {
1635         int w, h, count = 0;
1636         tbm_surface_h surface = NULL;
1637
1638         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1639         TBM_LOG_D("path=%s\n", path);
1640
1641         pthread_mutex_lock(&gLock);
1642
1643         count = _tbm_util_get_max_surface_size(&w, &h);
1644         if (count == 0) {
1645                 TBM_LOG_E("No tbm_surface.\n");
1646                 pthread_mutex_unlock(&gLock);
1647                 return 1;
1648         }
1649
1650         tbm_surface_internal_dump_start(path, w, h, count);
1651
1652         LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link)
1653                 tbm_surface_internal_dump_buffer(surface, "dump_all");
1654
1655         tbm_surface_internal_dump_end();
1656
1657         pthread_mutex_unlock(&gLock);
1658
1659         return 1;
1660 }
1661
1662 /* internal function */
1663 tbm_bufmgr
1664 _tbm_bufmgr_get_bufmgr(void)
1665 {
1666         return gBufMgr;
1667 }
1668
1669 int
1670 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1671 {
1672         _tbm_bufmgr_mutex_lock();
1673
1674         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1675         TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1676
1677         bo->surface = surface;
1678
1679         _tbm_bufmgr_mutex_unlock();
1680
1681         return 1;
1682 }
1683
1684 int
1685 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1686 {
1687         int ret;
1688
1689         _tbm_bufmgr_mutex_lock();
1690
1691         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1692
1693         if (!bufmgr->backend->bufmgr_bind_native_display) {
1694                 TBM_TRACE("skip: tbm_bufmgr(%p) NativeDisplay(%p)\n",
1695                                 bufmgr, NativeDisplay);
1696                 _tbm_bufmgr_mutex_unlock();
1697                 return 1;
1698         }
1699
1700         ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1701         if (!ret) {
1702                 TBM_LOG_E("error: tbm_bufmgr(%p) NativeDisplay(%p)\n",
1703                                 bufmgr, NativeDisplay);
1704                 _tbm_bufmgr_mutex_unlock();
1705                 return 0;
1706         }
1707
1708         TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1709
1710         _tbm_bufmgr_mutex_unlock();
1711
1712         return 1;
1713 }
1714 /* LCOV_EXCL_STOP */
1715
1716 int tbm_bufmgr_get_fd_limit(void)
1717 {
1718         struct rlimit lim;
1719
1720         if (getrlimit(RLIMIT_NOFILE, &lim))
1721                 return 1024;
1722
1723         return (int)lim.rlim_cur;
1724 }
1725