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