tbm_bufmgr: change tbm_bo_alloc_with_format name
[platform/core/uifw/libtbm.git] / src / tbm_bo.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 #include "tbm_bufmgr.h"
34 #include "tbm_bufmgr_int.h"
35 #include "list.h"
36
37 /* check condition */
38 #define TBM_BO_RETURN_IF_FAIL(cond) {\
39         if (!(cond)) {\
40                 TBM_ERR("'%s' failed.\n", #cond);\
41                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
42                 _tbm_bufmgr_mutex_unlock();\
43                 return;\
44         } \
45 }
46
47 #define TBM_BO_RETURN_VAL_IF_FAIL(cond, val) {\
48         if (!(cond)) {\
49                 TBM_ERR("'%s' failed.\n", #cond);\
50                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
51                 _tbm_bufmgr_mutex_unlock();\
52                 return val;\
53         } \
54 }
55
56 static char *
57 _tbm_flag_to_str(int f)
58 {
59         static char str[255];
60
61         if (f == TBM_BO_DEFAULT)
62                  snprintf(str, 255, "DEFAULT");
63         else {
64                 int c = 0;
65
66                 if (f & TBM_BO_SCANOUT)
67                         c += snprintf(&str[c], 255-c, "SCANOUT");
68
69                 if (f & TBM_BO_NONCACHABLE) {
70                         if (c >= 0 && c < 255)
71                                 c += snprintf(&str[c], 255-c, ", ");
72
73                         if (c >= 0 && c < 255)
74                                 c += snprintf(&str[c], 255-c, "NONCACHABLE,");
75                 }
76
77                 if (f & TBM_BO_WC) {
78                         if (c >= 0 && c < 255)
79                                 c += snprintf(&str[c], 255-c, ", ");
80
81                         if (c >= 0 && c < 255)
82                                 c += snprintf(&str[c], 255-c, "WC");
83                 }
84         }
85
86         return str;
87 }
88
89 static void
90 _tbm_util_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 /* LCOV_EXCL_STOP */
102
103 tbm_user_data *
104 user_data_lookup(struct list_head *user_data_list, unsigned long key)
105 {
106         tbm_user_data *old_data = NULL;
107
108         if (LIST_IS_EMPTY(user_data_list))
109                 return NULL;
110
111         LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
112                 if (old_data->key == key)
113                         return old_data;
114         }
115
116         return NULL;
117 }
118
119 tbm_user_data *
120 user_data_create(unsigned long key, tbm_data_free data_free_func)
121 {
122         tbm_user_data *user_data;
123
124         user_data = calloc(1, sizeof(tbm_user_data));
125         if (!user_data) {
126                 /* LCOV_EXCL_START */
127                 TBM_ERR("fail to allocate an user_date\n");
128                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
129                 return NULL;
130                 /* LCOV_EXCL_STOP */
131         }
132
133         user_data->key = key;
134         user_data->free_func = data_free_func;
135
136         return user_data;
137 }
138
139 void
140 user_data_delete(tbm_user_data *user_data)
141 {
142         if (user_data->data && user_data->free_func)
143                 user_data->free_func(user_data->data);
144
145         LIST_DEL(&user_data->item_link);
146
147         free(user_data);
148 }
149
150 static int
151 _bo_lock(tbm_bo bo, int device, int opt)
152 {
153         int ret = 1;
154         tbm_error_e error;
155
156         if (bo->bufmgr->use_hal_tbm) {
157                 error = (tbm_error_e)hal_tbm_bo_lock((hal_tbm_bo *)bo->bo_data, device, opt);
158                 if (error == TBM_ERROR_NOT_SUPPORTED) {
159                         _tbm_set_last_result(TBM_ERROR_NONE);
160                 } else {
161                         if (error != TBM_ERROR_NONE) {
162                                 TBM_WRN("fail to lock");
163                                 _tbm_set_last_result(error);
164                                 ret = 0;
165                         }
166                 }
167         } else if (bo->bufmgr->backend_module_data) {
168                 if (bo->bufmgr->bo_func->bo_lock) {
169                         error = bo->bufmgr->bo_func->bo_lock(bo->bo_data, device, opt);
170                         if (error != TBM_ERROR_NONE) {
171                                 TBM_WRN("fail to lock");
172                                 _tbm_set_last_result(error);
173                                 ret = 0;
174                         }
175                 }
176         } else {
177                 if (bo->bufmgr->backend->bo_lock) {
178                         ret = bo->bufmgr->backend->bo_lock(bo, device, opt);
179                         if (!ret)
180                                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
181                 }
182         }
183
184         return ret;
185 }
186
187 static void
188 _bo_unlock(tbm_bo bo)
189 {
190         tbm_error_e error;
191
192         if (bo->bufmgr->use_hal_tbm) {
193                 error = (tbm_error_e)hal_tbm_bo_unlock((hal_tbm_bo *)bo->bo_data);
194                 if (error == TBM_ERROR_NOT_SUPPORTED) {
195                         _tbm_set_last_result(TBM_ERROR_NONE);
196                 } else {
197                         if (error != TBM_ERROR_NONE) {
198                                 TBM_WRN("fail to lock");
199                                 _tbm_set_last_result(error);
200                         }
201                 }
202         } else if (bo->bufmgr->backend_module_data) {
203                 if (bo->bufmgr->bo_func->bo_unlock) {
204                         error = bo->bufmgr->bo_func->bo_unlock(bo->bo_data);
205                         if (error != TBM_ERROR_NONE) {
206                                 TBM_WRN("fail to unlock");
207                                 _tbm_set_last_result(error);
208                         }
209                 }
210         } else {
211                 if (bo->bufmgr->backend->bo_unlock)
212                         bo->bufmgr->backend->bo_unlock(bo);
213         }
214 }
215
216 static int
217 _tbm_bo_lock(tbm_bo bo, int device, int opt)
218 {
219         int old, ret;
220
221         if (!bo)
222                 return 0;
223
224         /* do not try to lock the bo */
225         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
226                 return 1;
227
228         if (bo->lock_cnt < 0) {
229                 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
230                         bo, bo->lock_cnt);
231                 return 0;
232         }
233
234         old = bo->lock_cnt;
235
236         switch (bo->bufmgr->bo_lock_type) {
237         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
238                 if (bo->lock_cnt == 0) {
239                         _tbm_bufmgr_mutex_unlock();
240                         ret = _bo_lock(bo, device, opt);
241                         _tbm_bufmgr_mutex_lock();
242                         if (ret)
243                                 bo->lock_cnt++;
244                 } else
245                         ret = 1;
246                 break;
247         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
248                 _tbm_bufmgr_mutex_unlock();
249                 ret = _bo_lock(bo, device, opt);
250                 _tbm_bufmgr_mutex_lock();
251                 if (ret)
252                         bo->lock_cnt++;
253                 break;
254         default:
255                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
256                                 bo, bo->bufmgr->bo_lock_type);
257                 ret = 0;
258                 break;
259         }
260
261         TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
262
263         return ret;
264 }
265
266 static void
267 _tbm_bo_unlock(tbm_bo bo)
268 {
269         int old;
270
271         /* do not try to unlock the bo */
272         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
273                 return;
274
275         old = bo->lock_cnt;
276
277         switch (bo->bufmgr->bo_lock_type) {
278         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
279                 if (bo->lock_cnt > 0) {
280                         bo->lock_cnt--;
281                         if (bo->lock_cnt == 0)
282                                 _bo_unlock(bo);
283                 }
284                 break;
285         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
286                 if (bo->lock_cnt > 0) {
287                         bo->lock_cnt--;
288                         _bo_unlock(bo);
289                 }
290                 break;
291         default:
292                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
293                                 bo, bo->bufmgr->bo_lock_type);
294                 break;
295         }
296
297         if (bo->lock_cnt < 0)
298                 bo->lock_cnt = 0;
299
300         TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
301 }
302
303 static int
304 _tbm_bo_magic_check(tbm_bo bo)
305 {
306         if (bo->magic != TBM_BO_MAGIC)
307                 return 0;
308
309         return 1;
310 }
311
312 static int
313 _tbm_bo_is_valid(tbm_bo bo)
314 {
315         if (!bo) {
316                 TBM_ERR("error: bo is NULL.\n");
317                 return 0;
318         }
319
320         if (!_tbm_bo_magic_check(bo)) {
321                 TBM_ERR("error: No valid bo(%p).\n", bo);
322                 return 0;
323         }
324
325         return 1;
326 }
327
328 static void
329 _tbm_bo_init(tbm_bufmgr bufmgr, tbm_bo bo, int flags)
330 {
331         bo->bufmgr = bufmgr;
332         bo->flags = flags;
333         bo->magic = TBM_BO_MAGIC;
334         bo->ref_cnt = 1;
335
336         LIST_INITHEAD(&bo->user_data_list);
337
338         bufmgr->bo_cnt++;
339         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
340 }
341
342 static void
343 _tbm_bo_deinit(tbm_bo bo)
344 {
345         bo->magic = 0;
346
347         bo->bufmgr->bo_cnt--;
348         LIST_DEL(&bo->item_link);
349 }
350
351 tbm_bo
352 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
353 {
354         tbm_bo bo;
355         tbm_backend_bo_data *bo_data;
356         tbm_error_e error;
357
358         _tbm_bufmgr_mutex_lock();
359         _tbm_set_last_result(TBM_ERROR_NONE);
360
361         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
362         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
363
364         bo = calloc(1, sizeof(struct _tbm_bo));
365         if (!bo) {
366                 /* LCOV_EXCL_START */
367                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
368                 _tbm_bufmgr_mutex_unlock();
369                 return NULL;
370                 /* LCOV_EXCL_STOP */
371         }
372
373         _tbm_util_check_bo_cnt(bufmgr);
374
375         bo_data = tbm_module_bufmgr_bo_alloc(bufmgr->module, bo, size, flags, &error);
376         if (!bo_data || error != TBM_ERROR_NONE) {
377                 /* LCOV_EXCL_START */
378                 TBM_ERR("tbm_module_bufmgr_bo_alloc failed. error:%d", error);
379                 _tbm_set_last_result(error);
380                 goto alloc_fail;
381                 /* LCOV_EXCL_STOP */
382         }
383         bo->bo_data = bo_data;
384         bo->priv = (void *)bo_data; // TODO: this will be DEPRECATED.
385
386         _tbm_bo_init(bufmgr, bo, flags);
387
388         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
389                         _tbm_flag_to_str(bo->flags));
390
391         _tbm_bufmgr_mutex_unlock();
392
393         return bo;
394
395 alloc_fail:
396         TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, _tbm_flag_to_str(flags));
397         free(bo);
398         _tbm_bufmgr_mutex_unlock();
399         return NULL;
400 }
401
402 /* LCOV_EXCL_START */
403 tbm_bo
404 tbm_bo_alloc_with_bo_data(tbm_bufmgr bufmgr, tbm_backend_bo_data *bo_data, int flags)
405 {
406         tbm_bo bo, bo2 = NULL;
407
408         _tbm_bufmgr_mutex_lock();
409         _tbm_set_last_result(TBM_ERROR_NONE);
410
411         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
412         TBM_BO_RETURN_VAL_IF_FAIL(bo_data, NULL);
413
414         // return an existed bo if the bo is already created with the same bo_data.
415         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
416                 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
417                         if (bo2->bo_data == bo_data) {
418                                 TBM_ERR("find bo(%p) ref(%d) flag(%s) in list\n",
419                                                 bo2, bo2->ref_cnt, _tbm_flag_to_str(bo2->flags));
420                                 bo2->ref_cnt++;
421                                 _tbm_bufmgr_mutex_unlock();
422                                 return bo2;
423                         }
424                 }
425         }
426
427         bo = calloc(1, sizeof(struct _tbm_bo));
428         if (!bo) {
429                 /* LCOV_EXCL_START */
430                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
431                 _tbm_bufmgr_mutex_unlock();
432                 return NULL;
433                 /* LCOV_EXCL_STOP */
434         }
435
436         _tbm_util_check_bo_cnt(bufmgr);
437
438         bo->get_from_hal_surface = 1;
439         bo->bo_data = bo_data;
440
441         _tbm_bo_init(bufmgr, bo, flags);
442
443         TBM_TRACE_BO("bo(%p) refcnt(%d), flag(%s)\n", bo, bo->ref_cnt, _tbm_flag_to_str(bo->flags));
444
445         _tbm_bufmgr_mutex_unlock();
446
447         return bo;
448 }
449
450 /* LCOV_EXCL_STOP */
451
452 tbm_bo
453 tbm_bo_ref(tbm_bo bo)
454 {
455         _tbm_bufmgr_mutex_lock();
456         _tbm_set_last_result(TBM_ERROR_NONE);
457
458         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
459
460         bo->ref_cnt++;
461
462         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
463
464         _tbm_bufmgr_mutex_unlock();
465
466         return bo;
467 }
468
469 void
470 tbm_bo_unref(tbm_bo bo)
471 {
472         _tbm_bufmgr_mutex_lock();
473         _tbm_set_last_result(TBM_ERROR_NONE);
474
475         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
476
477         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
478
479         if (bo->ref_cnt <= 0) {
480                 _tbm_bufmgr_mutex_unlock();
481                 return;
482         }
483
484         bo->ref_cnt--;
485         if (bo->ref_cnt == 0)
486                 _tbm_bo_free(bo);
487
488         _tbm_bufmgr_mutex_unlock();
489 }
490
491 tbm_bo_handle
492 tbm_bo_map(tbm_bo bo, int device, int opt)
493 {
494         tbm_bo_handle bo_handle;
495         tbm_error_e error;
496
497         _tbm_bufmgr_mutex_lock();
498         _tbm_set_last_result(TBM_ERROR_NONE);
499
500         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
501
502         if (!_tbm_bo_lock(bo, device, opt)) {
503                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
504                 _tbm_bufmgr_mutex_unlock();
505                 return (tbm_bo_handle) NULL;
506         }
507
508         if (bo->bufmgr->use_hal_tbm) {
509                 hal_tbm_bo_handle hbo_handle;
510                 hbo_handle = hal_tbm_bo_map((hal_tbm_bo *)bo->bo_data, device, opt, (hal_tbm_error *)&error);
511                 if (hbo_handle.ptr == NULL) {
512                         /* LCOV_EXCL_START */
513                         _tbm_set_last_result(error);
514                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
515                         goto bo_map_fail;
516                         /* LCOV_EXCL_STOP */
517                 }
518                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
519         } else if (bo->bufmgr->backend_module_data) {
520                 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
521                 if (bo_handle.ptr == NULL) {
522                         /* LCOV_EXCL_START */
523                         _tbm_set_last_result(error);
524                         TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
525                         goto bo_map_fail;
526                         /* LCOV_EXCL_STOP */
527                 }
528         } else {
529                 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
530                 if (bo_handle.ptr == NULL) {
531                         /* LCOV_EXCL_START */
532                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
533                         TBM_ERR("error: fail to map bo:%p\n", bo);
534                         goto bo_map_fail;
535                         /* LCOV_EXCL_STOP */
536                 }
537         }
538
539         /* increase the map_count */
540         bo->map_cnt++;
541
542         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
543
544         _tbm_bufmgr_mutex_unlock();
545
546         return bo_handle;
547
548 bo_map_fail:
549         _tbm_bo_unlock(bo);
550         _tbm_bufmgr_mutex_unlock();
551         return (tbm_bo_handle) NULL;
552 }
553
554 int
555 tbm_bo_unmap(tbm_bo bo)
556 {
557         int ret = 1;
558         tbm_error_e error;
559
560         _tbm_bufmgr_mutex_lock();
561         _tbm_set_last_result(TBM_ERROR_NONE);
562
563         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
564         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
565
566         if (bo->bufmgr->use_hal_tbm) {
567                 error = (hal_tbm_error)hal_tbm_bo_unmap((hal_tbm_bo *)bo->bo_data);
568                 if (error != TBM_ERROR_NONE) {
569                         /* LCOV_EXCL_START */
570                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
571                         _tbm_set_last_result(error);
572                         ret = 0;
573                         goto done;
574                         /* LCOV_EXCL_STOP */
575                 }
576         } else if (bo->bufmgr->backend_module_data) {
577                 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
578                 if (error != TBM_ERROR_NONE) {
579                         /* LCOV_EXCL_START */
580                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
581                         _tbm_set_last_result(error);
582                         ret = 0;
583                         goto done;
584                         /* LCOV_EXCL_STOP */
585                 }
586         } else {
587                 ret = bo->bufmgr->backend->bo_unmap(bo);
588                 if (!ret) {
589                         /* LCOV_EXCL_START */
590                         TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
591                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
592                         goto done;
593                         /* LCOV_EXCL_STOP */
594                 }
595         }
596
597         /* decrease the map_count */
598         bo->map_cnt--;
599
600         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
601
602         _tbm_bo_unlock(bo);
603
604 done:
605         _tbm_bufmgr_mutex_unlock();
606
607         return ret;
608 }
609
610 tbm_bo_handle
611 tbm_bo_get_handle(tbm_bo bo, int device)
612 {
613         tbm_bo_handle bo_handle;
614         tbm_error_e error;
615
616         _tbm_bufmgr_mutex_lock();
617         _tbm_set_last_result(TBM_ERROR_NONE);
618
619         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
620
621         if (bo->bufmgr->use_hal_tbm) {
622                 hal_tbm_bo_handle hbo_handle;
623                 hbo_handle = hal_tbm_bo_get_handle((hal_tbm_bo *)bo->bo_data, device, (hal_tbm_error *)&error);
624                 if (hbo_handle.ptr == NULL) {
625                         /* LCOV_EXCL_START */
626                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
627                         _tbm_set_last_result(error);
628                         goto bo_handle_fail;
629                         /* LCOV_EXCL_STOP */
630                 }
631                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
632         } else if (bo->bufmgr->backend_module_data) {
633                 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
634                 if (bo_handle.ptr == NULL) {
635                         /* LCOV_EXCL_START */
636                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
637                         _tbm_set_last_result(error);
638                         goto bo_handle_fail;
639                         /* LCOV_EXCL_STOP */
640                 }
641         } else {
642                 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
643                 if (bo_handle.ptr == NULL) {
644                         /* LCOV_EXCL_START */
645                         TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
646                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
647                         goto bo_handle_fail;
648                         /* LCOV_EXCL_STOP */
649                 }
650         }
651
652         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
653
654         _tbm_bufmgr_mutex_unlock();
655
656         return bo_handle;
657
658 bo_handle_fail:
659         _tbm_bufmgr_mutex_unlock();
660         return (tbm_bo_handle) NULL;
661 }
662
663 tbm_key
664 tbm_bo_export(tbm_bo bo)
665 {
666         tbm_key ret;
667         tbm_error_e error;
668
669         _tbm_bufmgr_mutex_lock();
670         _tbm_set_last_result(TBM_ERROR_NONE);
671
672         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
673
674         if (bo->bufmgr->use_hal_tbm) {
675                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
676                 if (!ret) {
677                         /* LCOV_EXCL_START */
678                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
679                         _tbm_set_last_result(error);
680                         goto done;
681                         /* LCOV_EXCL_STOP */
682                 }
683         } else if (bo->bufmgr->backend_module_data) {
684                 if (!bo->bufmgr->bo_func->bo_export_key) {
685                         /* LCOV_EXCL_START */
686                         _tbm_bufmgr_mutex_unlock();
687                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
688                         return 0;
689                         /* LCOV_EXCL_STOP */
690                 }
691
692                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
693                 if (!ret) {
694                         /* LCOV_EXCL_START */
695                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
696                         _tbm_set_last_result(error);
697                         goto done;
698                         /* LCOV_EXCL_STOP */
699                 }
700         } else {
701                 if (!bo->bufmgr->backend->bo_export) {
702                         /* LCOV_EXCL_START */
703                         _tbm_bufmgr_mutex_unlock();
704                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
705                         return 0;
706                         /* LCOV_EXCL_STOP */
707                 }
708
709                 ret = bo->bufmgr->backend->bo_export(bo);
710                 if (!ret) {
711                         /* LCOV_EXCL_START */
712                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
713                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
714                         goto done;
715                         /* LCOV_EXCL_STOP */
716                 }
717         }
718
719         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
720
721 done:
722         _tbm_bufmgr_mutex_unlock();
723
724         return ret;
725 }
726
727 tbm_fd
728 tbm_bo_export_fd(tbm_bo bo)
729 {
730         tbm_fd ret;
731         tbm_error_e error;
732
733         _tbm_bufmgr_mutex_lock();
734         _tbm_set_last_result(TBM_ERROR_NONE);
735
736         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
737
738         if (bo->bufmgr->use_hal_tbm) {
739                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
740                 if (ret < 0) {
741                         /* LCOV_EXCL_START */
742                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
743                         _tbm_set_last_result(error);
744                         goto done;
745                         /* LCOV_EXCL_STOP */
746                 }
747         } else if (bo->bufmgr->backend_module_data) {
748                 if (!bo->bufmgr->bo_func->bo_export_fd) {
749                         /* LCOV_EXCL_START */
750                         _tbm_bufmgr_mutex_unlock();
751                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
752                         return -1;
753                         /* LCOV_EXCL_STOP */
754                 }
755
756                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
757                 if (ret < 0) {
758                         /* LCOV_EXCL_START */
759                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
760                         _tbm_set_last_result(error);
761                         goto done;
762                         /* LCOV_EXCL_STOP */
763                 }
764         } else {
765                 if (!bo->bufmgr->backend->bo_export_fd) {
766                         /* LCOV_EXCL_START */
767                         _tbm_bufmgr_mutex_unlock();
768                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
769                         return -1;
770                         /* LCOV_EXCL_STOP */
771                 }
772
773                 ret = bo->bufmgr->backend->bo_export_fd(bo);
774                 if (ret < 0) {
775                         /* LCOV_EXCL_START */
776                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
777                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
778                         goto done;
779                         /* LCOV_EXCL_STOP */
780                 }
781         }
782
783         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
784
785 done:
786         _tbm_bufmgr_mutex_unlock();
787
788         return ret;
789 }
790
791 tbm_bo
792 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
793 {
794         tbm_bo bo, bo2 = NULL;
795         tbm_error_e error;
796         int flags;
797
798         _tbm_bufmgr_mutex_lock();
799         _tbm_set_last_result(TBM_ERROR_NONE);
800
801         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
802
803         _tbm_util_check_bo_cnt(bufmgr);
804
805         bo = calloc(1, sizeof(struct _tbm_bo));
806         if (!bo) {
807                 /* LCOV_EXCL_START */
808                 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
809                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
810                 _tbm_bufmgr_mutex_unlock();
811                 return NULL;
812                 /* LCOV_EXCL_STOP */
813         }
814
815         bo->bo_data = tbm_module_bufmgr_bo_import_key(bufmgr->module, bo, key, &error);
816         if (!bo->bo_data) {
817                 /* LCOV_EXCL_START */
818                 TBM_ERR("tbm_module_bufmgr_bo_import_key failed. tbm_key:%d", key);
819                 _tbm_set_last_result(error);
820                 _tbm_bufmgr_mutex_unlock();
821                 return NULL;
822                 /* LCOV_EXCL_STOP */
823         }
824
825         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
826         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
827         if (bo2) {
828                 TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list",
829                                         bo2, bo2->ref_cnt, key, _tbm_flag_to_str(bo2->flags));
830                 bo2->ref_cnt++;
831                 free(bo);
832                 _tbm_bufmgr_mutex_unlock();
833                 return bo2;
834         }
835
836         if (bufmgr->use_hal_tbm) {
837                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
838                 if (error != TBM_ERROR_NONE) {
839                         TBM_ERR("fail to get the bo flags(memory_types)");
840                         _tbm_set_last_result(error);
841                         flags = TBM_BO_DEFAULT;
842                 }
843         } else if (bufmgr->backend_module_data) {
844                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
845                 if (error != TBM_ERROR_NONE) {
846                         TBM_ERR("fail to get the bo flags(memory_types)");
847                         _tbm_set_last_result(error);
848                         flags = TBM_BO_DEFAULT;
849                 }
850         } else {
851                 if (bufmgr->backend->bo_get_flags)
852                         flags = bufmgr->backend->bo_get_flags(bo);
853                 else
854                         flags = TBM_BO_DEFAULT;
855         }
856
857         _tbm_bo_init(bufmgr, bo, flags);
858
859         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
860                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
861
862         _tbm_bufmgr_mutex_unlock();
863
864         return bo;
865 }
866
867 tbm_bo
868 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
869 {
870         tbm_bo bo, bo2 = NULL;
871         tbm_error_e error;
872         int flags;
873
874         _tbm_bufmgr_mutex_lock();
875         _tbm_set_last_result(TBM_ERROR_NONE);
876
877         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
878
879         _tbm_util_check_bo_cnt(bufmgr);
880
881         bo = calloc(1, sizeof(struct _tbm_bo));
882         if (!bo) {
883                 /* LCOV_EXCL_START */
884                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
885                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
886                 _tbm_bufmgr_mutex_unlock();
887                 return NULL;
888                 /* LCOV_EXCL_STOP */
889         }
890
891         bo->bo_data = tbm_module_bufmgr_bo_import_fd(bufmgr->module, bo, fd, &error);
892         if (!bo->bo_data) {
893                 /* LCOV_EXCL_START */
894                 TBM_ERR("tbm_module_bufmgr_bo_import_fd failed. tbm_fd:%d", fd);
895                 _tbm_set_last_result(error);
896                 _tbm_bufmgr_mutex_unlock();
897                 return NULL;
898                 /* LCOV_EXCL_STOP */
899         }
900
901         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
902         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
903         if (bo2) {
904                 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list",
905                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
906                 bo2->ref_cnt++;
907                 free(bo);
908                 _tbm_bufmgr_mutex_unlock();
909                 return bo2;
910         }
911
912         if (bufmgr->use_hal_tbm) {
913                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
914                 if (error != TBM_ERROR_NONE) {
915                         TBM_ERR("fail to get the bo flags(memory_types)");
916                         _tbm_set_last_result(error);
917                         flags = TBM_BO_DEFAULT;
918                 }
919         } else if (bufmgr->backend_module_data) {
920                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
921                 if (error != TBM_ERROR_NONE) {
922                         TBM_ERR("fail to get the bo flags(memory_types)");
923                         _tbm_set_last_result(error);
924                         flags = TBM_BO_DEFAULT;
925                 }
926         } else {
927                 if (bufmgr->backend->bo_get_flags)
928                         flags = bufmgr->backend->bo_get_flags(bo);
929                 else
930                         flags = TBM_BO_DEFAULT;
931         }
932
933         _tbm_bo_init(bufmgr, bo, flags);
934
935         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
936                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
937
938         _tbm_bufmgr_mutex_unlock();
939
940         return bo;
941 }
942
943 int
944 tbm_bo_size(tbm_bo bo)
945 {
946         int size;
947         tbm_error_e error;
948
949         _tbm_bufmgr_mutex_lock();
950         _tbm_set_last_result(TBM_ERROR_NONE);
951
952         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
953
954         if (bo->bufmgr->use_hal_tbm) {
955                 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
956                 if (error != TBM_ERROR_NONE) {
957                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
958                         _tbm_set_last_result(TBM_ERROR_NONE);
959                 }
960         } else if (bo->bufmgr->backend_module_data) {
961                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
962                 if (error != TBM_ERROR_NONE) {
963                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
964                         _tbm_set_last_result(TBM_ERROR_NONE);
965                 }
966         } else
967                 size = bo->bufmgr->backend->bo_size(bo);
968
969         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
970
971         _tbm_bufmgr_mutex_unlock();
972
973         return size;
974 }
975
976 int
977 tbm_bo_locked(tbm_bo bo)
978 {
979         _tbm_bufmgr_mutex_lock();
980         _tbm_set_last_result(TBM_ERROR_NONE);
981
982         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
983
984         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
985                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
986                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
987                 _tbm_bufmgr_mutex_unlock();
988                 return 0;
989         }
990
991         if (bo->lock_cnt > 0) {
992                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
993                 _tbm_bufmgr_mutex_unlock();
994                 return 1;
995         }
996
997         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
998         _tbm_bufmgr_mutex_unlock();
999
1000         return 0;
1001 }
1002
1003 int
1004 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1005 {
1006         tbm_error_e error1, error2;
1007         int size1 = -1, size2 = -2;
1008         void *temp;
1009
1010         _tbm_bufmgr_mutex_lock();
1011         _tbm_set_last_result(TBM_ERROR_NONE);
1012
1013         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1014         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1015
1016         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1017
1018         if (bo1->bufmgr->use_hal_tbm) {
1019                 size1 = hal_tbm_bo_get_size((hal_tbm_bo *)bo1->bo_data, (hal_tbm_error *)&error1);
1020                 if (error1 != TBM_ERROR_NONE) {
1021                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1022                         _tbm_set_last_result(error1);
1023                         goto fail;
1024                 }
1025                 size2 = hal_tbm_bo_get_size((hal_tbm_bo *)bo2->bo_data, (hal_tbm_error *)&error2);
1026                 if (error2 != TBM_ERROR_NONE) {
1027                         TBM_ERR("fail to get the size of bo1.(%d)", error2);
1028                         _tbm_set_last_result(error2);
1029                         goto fail;
1030                 }
1031         } else if (bo1->bufmgr->backend_module_data) {
1032                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
1033                 if (error1 != TBM_ERROR_NONE) {
1034                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1035                         _tbm_set_last_result(error1);
1036                         goto fail;
1037                 }
1038                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
1039                 if (error2 != TBM_ERROR_NONE) {
1040                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
1041                         _tbm_set_last_result(error2);
1042                         goto fail;
1043                 }
1044         } else {
1045                 size1 = bo1->bufmgr->backend->bo_size(bo1);
1046                 size2 = bo2->bufmgr->backend->bo_size(bo2);
1047         }
1048
1049         if (size1 != size2) {
1050                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
1051                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1052                 goto fail;
1053         }
1054
1055         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1056
1057         temp = bo1->priv;
1058         bo1->priv = bo2->priv;
1059         bo2->priv = temp;
1060
1061         _tbm_bufmgr_mutex_unlock();
1062
1063         return 1;
1064
1065 fail:
1066         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1067         _tbm_bufmgr_mutex_unlock();
1068
1069         return 0;
1070 }
1071
1072 int
1073 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1074                      tbm_data_free data_free_func)
1075 {
1076         tbm_user_data *data;
1077
1078         _tbm_bufmgr_mutex_lock();
1079         _tbm_set_last_result(TBM_ERROR_NONE);
1080
1081         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1082
1083         /* check if the data according to the key exist if so, return false. */
1084         data = user_data_lookup(&bo->user_data_list, key);
1085         if (data) {
1086                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1087                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1088                 _tbm_bufmgr_mutex_unlock();
1089                 return 0;
1090         }
1091
1092         data = user_data_create(key, data_free_func);
1093         if (!data) {
1094                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1095                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1096                 _tbm_bufmgr_mutex_unlock();
1097                 return 0;
1098         }
1099
1100         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1101
1102         LIST_ADD(&data->item_link, &bo->user_data_list);
1103
1104         _tbm_bufmgr_mutex_unlock();
1105
1106         return 1;
1107 }
1108
1109 int
1110 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1111 {
1112         tbm_user_data *old_data;
1113
1114         _tbm_bufmgr_mutex_lock();
1115         _tbm_set_last_result(TBM_ERROR_NONE);
1116
1117         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1118
1119         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1120                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1121                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1122                 _tbm_bufmgr_mutex_unlock();
1123                 return 0;
1124         }
1125
1126         old_data = user_data_lookup(&bo->user_data_list, key);
1127         if (!old_data) {
1128                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1129                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1130                 _tbm_bufmgr_mutex_unlock();
1131                 return 0;
1132         }
1133
1134         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1135
1136         user_data_delete(old_data);
1137
1138         _tbm_bufmgr_mutex_unlock();
1139
1140         return 1;
1141 }
1142
1143 int
1144 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1145 {
1146         tbm_user_data *old_data;
1147
1148         _tbm_bufmgr_mutex_lock();
1149         _tbm_set_last_result(TBM_ERROR_NONE);
1150
1151         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1152
1153         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1154                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1155                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1156                 _tbm_bufmgr_mutex_unlock();
1157                 return 0;
1158         }
1159
1160         old_data = user_data_lookup(&bo->user_data_list, key);
1161         if (!old_data) {
1162                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1163                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1164                 _tbm_bufmgr_mutex_unlock();
1165                 return 0;
1166         }
1167
1168         if (old_data->data && old_data->free_func)
1169                 old_data->free_func(old_data->data);
1170         old_data->data = data;
1171
1172         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1173
1174         _tbm_bufmgr_mutex_unlock();
1175
1176         return 1;
1177 }
1178
1179 int
1180 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1181 {
1182         tbm_user_data *old_data;
1183
1184         _tbm_bufmgr_mutex_lock();
1185         _tbm_set_last_result(TBM_ERROR_NONE);
1186
1187         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1188
1189         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1190                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1191                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1192                 _tbm_bufmgr_mutex_unlock();
1193                 return 0;
1194         }
1195
1196         old_data = user_data_lookup(&bo->user_data_list, key);
1197         if (!old_data) {
1198                 *data = NULL;
1199                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1200                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1201                 _tbm_bufmgr_mutex_unlock();
1202                 return 0;
1203         }
1204
1205         *data = old_data->data;
1206
1207         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1208
1209         _tbm_bufmgr_mutex_unlock();
1210
1211         return 1;
1212 }
1213
1214 int
1215 tbm_bo_get_flags(tbm_bo bo)
1216 {
1217         int flags;
1218
1219         _tbm_bufmgr_mutex_lock();
1220
1221         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1222
1223         flags = bo->flags;
1224
1225         TBM_TRACE_BO("bo(%p)\n", bo);
1226
1227         _tbm_bufmgr_mutex_unlock();
1228
1229         return flags;
1230 }
1231
1232 /* LCOV_EXCL_START */
1233 /* internal function */
1234 int
1235 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1236 {
1237         _tbm_bufmgr_mutex_lock();
1238
1239         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1240
1241         bo->surface = surface;
1242
1243         _tbm_bufmgr_mutex_unlock();
1244
1245         return 1;
1246 }
1247
1248 void
1249 _tbm_bo_free(tbm_bo bo)
1250 {
1251         /* destory the user_data_list */
1252         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1253                 tbm_user_data *old_data = NULL, *tmp;
1254
1255                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1256                                 &bo->user_data_list, item_link) {
1257                         TBM_DBG("free user_data\n");
1258                         user_data_delete(old_data);
1259                 }
1260         }
1261
1262         while (bo->lock_cnt > 0) {
1263                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1264                 _bo_unlock(bo);
1265                 bo->lock_cnt--;
1266         }
1267
1268         /* call the bo_free */
1269         if (bo->bufmgr->use_hal_tbm) {
1270                 // call hal_tbm_bo_free when bo is created by tbm_bo_alloc api.
1271                 if (!bo->get_from_hal_surface) {
1272                         bo->get_from_hal_surface = 0;
1273
1274                         hal_tbm_bo_free(bo->bo_data);
1275                         bo->bo_data = NULL;
1276                 }
1277         } else if (bo->bufmgr->backend_module_data) {
1278                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1279                 bo->bo_data = NULL;
1280         } else {
1281                 bo->bufmgr->backend->bo_free(bo);
1282                 bo->priv = NULL;
1283         }
1284
1285         _tbm_bo_deinit(bo);
1286
1287         free(bo);
1288 }
1289 /* LCOV_EXCL_STOP */