0f4210f8d17c11f49887ecefe71ea66fbceca254
[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_ERR("tbm_module_bufmgr_bo_alloc_with_format failed. fmt:%d idx:%d wxh:%dx%d mem_types:%s\n",
432                                 format, bo_idx, width, height, _tbm_flag_to_str(flags));
433                 _tbm_set_last_result(*error);
434                 /* LCOV_EXCL_STOP */
435                 goto fail;
436         }
437
438         _tbm_bo_init(bufmgr, bo, flags);
439
440         _tbm_bufmgr_mutex_unlock();
441
442         return bo;
443
444 fail:
445         if (bo)
446                 free(bo);
447         _tbm_bufmgr_mutex_unlock();
448
449         return NULL;
450 }
451
452 tbm_bo
453 tbm_bo_alloc_with_bo_data(tbm_bufmgr bufmgr, tbm_backend_bo_data *bo_data, int flags)
454 {
455         tbm_bo bo, bo2 = NULL;
456
457         _tbm_bufmgr_mutex_lock();
458         _tbm_set_last_result(TBM_ERROR_NONE);
459
460         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
461         TBM_BO_RETURN_VAL_IF_FAIL(bo_data, NULL);
462
463         // return an existed bo if the bo is already created with the same bo_data.
464         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
465                 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
466                         if (bo2->bo_data == bo_data) {
467                                 TBM_ERR("find bo(%p) ref(%d) flag(%s) in list\n",
468                                                 bo2, bo2->ref_cnt, _tbm_flag_to_str(bo2->flags));
469                                 bo2->ref_cnt++;
470                                 _tbm_bufmgr_mutex_unlock();
471                                 return bo2;
472                         }
473                 }
474         }
475
476         bo = calloc(1, sizeof(struct _tbm_bo));
477         if (!bo) {
478                 /* LCOV_EXCL_START */
479                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
480                 _tbm_bufmgr_mutex_unlock();
481                 return NULL;
482                 /* LCOV_EXCL_STOP */
483         }
484
485         _tbm_util_check_bo_cnt(bufmgr);
486
487         bo->get_from_hal_surface = 1;
488         bo->bo_data = bo_data;
489
490         _tbm_bo_init(bufmgr, bo, flags);
491
492         TBM_TRACE_BO("bo(%p) refcnt(%d), flag(%s)\n", bo, bo->ref_cnt, _tbm_flag_to_str(bo->flags));
493
494         _tbm_bufmgr_mutex_unlock();
495
496         return bo;
497 }
498
499 /* LCOV_EXCL_STOP */
500
501 tbm_bo
502 tbm_bo_ref(tbm_bo bo)
503 {
504         _tbm_bufmgr_mutex_lock();
505         _tbm_set_last_result(TBM_ERROR_NONE);
506
507         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
508
509         bo->ref_cnt++;
510
511         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
512
513         _tbm_bufmgr_mutex_unlock();
514
515         return bo;
516 }
517
518 void
519 tbm_bo_unref(tbm_bo bo)
520 {
521         _tbm_bufmgr_mutex_lock();
522         _tbm_set_last_result(TBM_ERROR_NONE);
523
524         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
525
526         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
527
528         if (bo->ref_cnt <= 0) {
529                 _tbm_bufmgr_mutex_unlock();
530                 return;
531         }
532
533         bo->ref_cnt--;
534         if (bo->ref_cnt == 0)
535                 _tbm_bo_free(bo);
536
537         _tbm_bufmgr_mutex_unlock();
538 }
539
540 tbm_bo_handle
541 tbm_bo_map(tbm_bo bo, int device, int opt)
542 {
543         tbm_bo_handle bo_handle;
544         tbm_error_e error;
545
546         _tbm_bufmgr_mutex_lock();
547         _tbm_set_last_result(TBM_ERROR_NONE);
548
549         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
550
551         if (!_tbm_bo_lock(bo, device, opt)) {
552                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
553                 _tbm_bufmgr_mutex_unlock();
554                 return (tbm_bo_handle) NULL;
555         }
556
557         if (bo->bufmgr->use_hal_tbm) {
558                 hal_tbm_bo_handle hbo_handle;
559                 hbo_handle = hal_tbm_bo_map((hal_tbm_bo *)bo->bo_data, device, opt, (hal_tbm_error *)&error);
560                 if (hbo_handle.ptr == NULL) {
561                         /* LCOV_EXCL_START */
562                         _tbm_set_last_result(error);
563                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
564                         goto bo_map_fail;
565                         /* LCOV_EXCL_STOP */
566                 }
567                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
568         } else if (bo->bufmgr->backend_module_data) {
569                 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
570                 if (bo_handle.ptr == NULL) {
571                         /* LCOV_EXCL_START */
572                         _tbm_set_last_result(error);
573                         TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
574                         goto bo_map_fail;
575                         /* LCOV_EXCL_STOP */
576                 }
577         } else {
578                 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
579                 if (bo_handle.ptr == NULL) {
580                         /* LCOV_EXCL_START */
581                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
582                         TBM_ERR("error: fail to map bo:%p\n", bo);
583                         goto bo_map_fail;
584                         /* LCOV_EXCL_STOP */
585                 }
586         }
587
588         /* increase the map_count */
589         bo->map_cnt++;
590
591         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
592
593         _tbm_bufmgr_mutex_unlock();
594
595         return bo_handle;
596
597 bo_map_fail:
598         _tbm_bo_unlock(bo);
599         _tbm_bufmgr_mutex_unlock();
600         return (tbm_bo_handle) NULL;
601 }
602
603 int
604 tbm_bo_unmap(tbm_bo bo)
605 {
606         int ret = 1;
607         tbm_error_e error;
608
609         _tbm_bufmgr_mutex_lock();
610         _tbm_set_last_result(TBM_ERROR_NONE);
611
612         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
613         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
614
615         if (bo->bufmgr->use_hal_tbm) {
616                 error = (hal_tbm_error)hal_tbm_bo_unmap((hal_tbm_bo *)bo->bo_data);
617                 if (error != TBM_ERROR_NONE) {
618                         /* LCOV_EXCL_START */
619                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
620                         _tbm_set_last_result(error);
621                         ret = 0;
622                         goto done;
623                         /* LCOV_EXCL_STOP */
624                 }
625         } else if (bo->bufmgr->backend_module_data) {
626                 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
627                 if (error != TBM_ERROR_NONE) {
628                         /* LCOV_EXCL_START */
629                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
630                         _tbm_set_last_result(error);
631                         ret = 0;
632                         goto done;
633                         /* LCOV_EXCL_STOP */
634                 }
635         } else {
636                 ret = bo->bufmgr->backend->bo_unmap(bo);
637                 if (!ret) {
638                         /* LCOV_EXCL_START */
639                         TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
640                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
641                         goto done;
642                         /* LCOV_EXCL_STOP */
643                 }
644         }
645
646         /* decrease the map_count */
647         bo->map_cnt--;
648
649         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
650
651         _tbm_bo_unlock(bo);
652
653 done:
654         _tbm_bufmgr_mutex_unlock();
655
656         return ret;
657 }
658
659 tbm_bo_handle
660 tbm_bo_get_handle(tbm_bo bo, int device)
661 {
662         tbm_bo_handle bo_handle;
663         tbm_error_e error;
664
665         _tbm_bufmgr_mutex_lock();
666         _tbm_set_last_result(TBM_ERROR_NONE);
667
668         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
669
670         if (bo->bufmgr->use_hal_tbm) {
671                 hal_tbm_bo_handle hbo_handle;
672                 hbo_handle = hal_tbm_bo_get_handle((hal_tbm_bo *)bo->bo_data, device, (hal_tbm_error *)&error);
673                 if (hbo_handle.ptr == NULL) {
674                         /* LCOV_EXCL_START */
675                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
676                         _tbm_set_last_result(error);
677                         goto bo_handle_fail;
678                         /* LCOV_EXCL_STOP */
679                 }
680                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
681         } else if (bo->bufmgr->backend_module_data) {
682                 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
683                 if (bo_handle.ptr == NULL) {
684                         /* LCOV_EXCL_START */
685                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
686                         _tbm_set_last_result(error);
687                         goto bo_handle_fail;
688                         /* LCOV_EXCL_STOP */
689                 }
690         } else {
691                 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
692                 if (bo_handle.ptr == NULL) {
693                         /* LCOV_EXCL_START */
694                         TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
695                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
696                         goto bo_handle_fail;
697                         /* LCOV_EXCL_STOP */
698                 }
699         }
700
701         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
702
703         _tbm_bufmgr_mutex_unlock();
704
705         return bo_handle;
706
707 bo_handle_fail:
708         _tbm_bufmgr_mutex_unlock();
709         return (tbm_bo_handle) NULL;
710 }
711
712 tbm_key
713 tbm_bo_export(tbm_bo bo)
714 {
715         tbm_key ret;
716         tbm_error_e error;
717
718         _tbm_bufmgr_mutex_lock();
719         _tbm_set_last_result(TBM_ERROR_NONE);
720
721         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
722
723         if (bo->bufmgr->use_hal_tbm) {
724                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
725                 if (!ret) {
726                         /* LCOV_EXCL_START */
727                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
728                         _tbm_set_last_result(error);
729                         goto done;
730                         /* LCOV_EXCL_STOP */
731                 }
732         } else if (bo->bufmgr->backend_module_data) {
733                 if (!bo->bufmgr->bo_func->bo_export_key) {
734                         /* LCOV_EXCL_START */
735                         _tbm_bufmgr_mutex_unlock();
736                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
737                         return 0;
738                         /* LCOV_EXCL_STOP */
739                 }
740
741                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
742                 if (!ret) {
743                         /* LCOV_EXCL_START */
744                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
745                         _tbm_set_last_result(error);
746                         goto done;
747                         /* LCOV_EXCL_STOP */
748                 }
749         } else {
750                 if (!bo->bufmgr->backend->bo_export) {
751                         /* LCOV_EXCL_START */
752                         _tbm_bufmgr_mutex_unlock();
753                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
754                         return 0;
755                         /* LCOV_EXCL_STOP */
756                 }
757
758                 ret = bo->bufmgr->backend->bo_export(bo);
759                 if (!ret) {
760                         /* LCOV_EXCL_START */
761                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
762                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
763                         goto done;
764                         /* LCOV_EXCL_STOP */
765                 }
766         }
767
768         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
769
770 done:
771         _tbm_bufmgr_mutex_unlock();
772
773         return ret;
774 }
775
776 tbm_fd
777 tbm_bo_export_fd(tbm_bo bo)
778 {
779         tbm_fd ret;
780         tbm_error_e error;
781
782         _tbm_bufmgr_mutex_lock();
783         _tbm_set_last_result(TBM_ERROR_NONE);
784
785         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
786
787         if (bo->bufmgr->use_hal_tbm) {
788                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
789                 if (ret < 0) {
790                         /* LCOV_EXCL_START */
791                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
792                         _tbm_set_last_result(error);
793                         goto done;
794                         /* LCOV_EXCL_STOP */
795                 }
796         } else if (bo->bufmgr->backend_module_data) {
797                 if (!bo->bufmgr->bo_func->bo_export_fd) {
798                         /* LCOV_EXCL_START */
799                         _tbm_bufmgr_mutex_unlock();
800                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
801                         return -1;
802                         /* LCOV_EXCL_STOP */
803                 }
804
805                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
806                 if (ret < 0) {
807                         /* LCOV_EXCL_START */
808                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
809                         _tbm_set_last_result(error);
810                         goto done;
811                         /* LCOV_EXCL_STOP */
812                 }
813         } else {
814                 if (!bo->bufmgr->backend->bo_export_fd) {
815                         /* LCOV_EXCL_START */
816                         _tbm_bufmgr_mutex_unlock();
817                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
818                         return -1;
819                         /* LCOV_EXCL_STOP */
820                 }
821
822                 ret = bo->bufmgr->backend->bo_export_fd(bo);
823                 if (ret < 0) {
824                         /* LCOV_EXCL_START */
825                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
826                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
827                         goto done;
828                         /* LCOV_EXCL_STOP */
829                 }
830         }
831
832         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
833
834 done:
835         _tbm_bufmgr_mutex_unlock();
836
837         return ret;
838 }
839
840 tbm_bo
841 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
842 {
843         tbm_bo bo, bo2 = NULL;
844         tbm_error_e error;
845         int flags;
846
847         _tbm_bufmgr_mutex_lock();
848         _tbm_set_last_result(TBM_ERROR_NONE);
849
850         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
851
852         _tbm_util_check_bo_cnt(bufmgr);
853
854         bo = calloc(1, sizeof(struct _tbm_bo));
855         if (!bo) {
856                 /* LCOV_EXCL_START */
857                 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
858                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
859                 _tbm_bufmgr_mutex_unlock();
860                 return NULL;
861                 /* LCOV_EXCL_STOP */
862         }
863
864         bo->bo_data = tbm_module_bufmgr_bo_import_key(bufmgr->module, bo, key, &error);
865         if (!bo->bo_data) {
866                 /* LCOV_EXCL_START */
867                 TBM_ERR("tbm_module_bufmgr_bo_import_key failed. tbm_key:%d", key);
868                 _tbm_set_last_result(error);
869                 _tbm_bufmgr_mutex_unlock();
870                 return NULL;
871                 /* LCOV_EXCL_STOP */
872         }
873
874         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
875                 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
876                         if (bo2->bo_data == bo->bo_data) {
877                                 TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list",
878                                                 bo2, bo2->ref_cnt, key, _tbm_flag_to_str(bo2->flags));
879                                 bo2->ref_cnt++;
880                                 free(bo);
881                                 _tbm_bufmgr_mutex_unlock();
882                                 return bo2;
883                         }
884                 }
885         }
886
887         if (bufmgr->use_hal_tbm) {
888                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
889                 if (error != TBM_ERROR_NONE) {
890                         TBM_ERR("fail to get the bo flags(memory_types)");
891                         _tbm_set_last_result(error);
892                         flags = TBM_BO_DEFAULT;
893                 }
894         } else if (bufmgr->backend_module_data) {
895                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
896                 if (error != TBM_ERROR_NONE) {
897                         TBM_ERR("fail to get the bo flags(memory_types)");
898                         _tbm_set_last_result(error);
899                         flags = TBM_BO_DEFAULT;
900                 }
901         } else {
902                 if (bufmgr->backend->bo_get_flags)
903                         flags = bufmgr->backend->bo_get_flags(bo);
904                 else
905                         flags = TBM_BO_DEFAULT;
906         }
907
908         _tbm_bo_init(bufmgr, bo, flags);
909
910         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
911                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
912
913         _tbm_bufmgr_mutex_unlock();
914
915         return bo;
916 }
917
918 tbm_bo
919 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
920 {
921         tbm_bo bo, bo2 = NULL;
922         tbm_error_e error;
923         int flags;
924
925         _tbm_bufmgr_mutex_lock();
926         _tbm_set_last_result(TBM_ERROR_NONE);
927
928         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
929
930         _tbm_util_check_bo_cnt(bufmgr);
931
932         bo = calloc(1, sizeof(struct _tbm_bo));
933         if (!bo) {
934                 /* LCOV_EXCL_START */
935                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
936                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
937                 _tbm_bufmgr_mutex_unlock();
938                 return NULL;
939                 /* LCOV_EXCL_STOP */
940         }
941
942         bo->bo_data = tbm_module_bufmgr_bo_import_fd(bufmgr->module, bo, fd, &error);
943         if (!bo->bo_data) {
944                 /* LCOV_EXCL_START */
945                 TBM_ERR("tbm_module_bufmgr_bo_import_fd failed. tbm_fd:%d", fd);
946                 _tbm_set_last_result(error);
947                 _tbm_bufmgr_mutex_unlock();
948                 return NULL;
949                 /* LCOV_EXCL_STOP */
950         }
951
952         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
953                 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
954                         if (bo2->bo_data == bo->bo_data) {
955                                 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
956                                                 bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
957                                 bo2->ref_cnt++;
958                                 free(bo);
959                                 _tbm_bufmgr_mutex_unlock();
960                                 return bo2;
961                         }
962                 }
963         }
964
965         if (bufmgr->use_hal_tbm) {
966                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
967                 if (error != TBM_ERROR_NONE) {
968                         TBM_ERR("fail to get the bo flags(memory_types)");
969                         _tbm_set_last_result(error);
970                         flags = TBM_BO_DEFAULT;
971                 }
972         } else if (bufmgr->backend_module_data) {
973                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
974                 if (error != TBM_ERROR_NONE) {
975                         TBM_ERR("fail to get the bo flags(memory_types)");
976                         _tbm_set_last_result(error);
977                         flags = TBM_BO_DEFAULT;
978                 }
979         } else {
980                 if (bufmgr->backend->bo_get_flags)
981                         flags = bufmgr->backend->bo_get_flags(bo);
982                 else
983                         flags = TBM_BO_DEFAULT;
984         }
985
986         _tbm_bo_init(bufmgr, bo, flags);
987
988         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
989                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
990
991         _tbm_bufmgr_mutex_unlock();
992
993         return bo;
994 }
995
996 int
997 tbm_bo_size(tbm_bo bo)
998 {
999         int size;
1000         tbm_error_e error;
1001
1002         _tbm_bufmgr_mutex_lock();
1003         _tbm_set_last_result(TBM_ERROR_NONE);
1004
1005         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1006
1007         if (bo->bufmgr->use_hal_tbm) {
1008                 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&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 if (bo->bufmgr->backend_module_data) {
1014                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
1015                 if (error != TBM_ERROR_NONE) {
1016                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
1017                         _tbm_set_last_result(TBM_ERROR_NONE);
1018                 }
1019         } else
1020                 size = bo->bufmgr->backend->bo_size(bo);
1021
1022         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
1023
1024         _tbm_bufmgr_mutex_unlock();
1025
1026         return size;
1027 }
1028
1029 int
1030 tbm_bo_locked(tbm_bo bo)
1031 {
1032         _tbm_bufmgr_mutex_lock();
1033         _tbm_set_last_result(TBM_ERROR_NONE);
1034
1035         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1036
1037         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
1038                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1039                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1040                 _tbm_bufmgr_mutex_unlock();
1041                 return 0;
1042         }
1043
1044         if (bo->lock_cnt > 0) {
1045                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1046                 _tbm_bufmgr_mutex_unlock();
1047                 return 1;
1048         }
1049
1050         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1051         _tbm_bufmgr_mutex_unlock();
1052
1053         return 0;
1054 }
1055
1056 int
1057 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1058 {
1059         tbm_error_e error1, error2;
1060         int size1 = -1, size2 = -2;
1061         void *temp;
1062
1063         _tbm_bufmgr_mutex_lock();
1064         _tbm_set_last_result(TBM_ERROR_NONE);
1065
1066         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1067         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1068
1069         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1070
1071         if (bo1->bufmgr->use_hal_tbm) {
1072                 size1 = hal_tbm_bo_get_size((hal_tbm_bo *)bo1->bo_data, (hal_tbm_error *)&error1);
1073                 if (error1 != TBM_ERROR_NONE) {
1074                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1075                         _tbm_set_last_result(error1);
1076                         goto fail;
1077                 }
1078                 size2 = hal_tbm_bo_get_size((hal_tbm_bo *)bo2->bo_data, (hal_tbm_error *)&error2);
1079                 if (error2 != TBM_ERROR_NONE) {
1080                         TBM_ERR("fail to get the size of bo1.(%d)", error2);
1081                         _tbm_set_last_result(error2);
1082                         goto fail;
1083                 }
1084         } else if (bo1->bufmgr->backend_module_data) {
1085                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
1086                 if (error1 != TBM_ERROR_NONE) {
1087                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1088                         _tbm_set_last_result(error1);
1089                         goto fail;
1090                 }
1091                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
1092                 if (error2 != TBM_ERROR_NONE) {
1093                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
1094                         _tbm_set_last_result(error2);
1095                         goto fail;
1096                 }
1097         } else {
1098                 size1 = bo1->bufmgr->backend->bo_size(bo1);
1099                 size2 = bo2->bufmgr->backend->bo_size(bo2);
1100         }
1101
1102         if (size1 != size2) {
1103                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
1104                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1105                 goto fail;
1106         }
1107
1108         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1109
1110         temp = bo1->priv;
1111         bo1->priv = bo2->priv;
1112         bo2->priv = temp;
1113
1114         _tbm_bufmgr_mutex_unlock();
1115
1116         return 1;
1117
1118 fail:
1119         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1120         _tbm_bufmgr_mutex_unlock();
1121
1122         return 0;
1123 }
1124
1125 int
1126 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1127                      tbm_data_free data_free_func)
1128 {
1129         tbm_user_data *data;
1130
1131         _tbm_bufmgr_mutex_lock();
1132         _tbm_set_last_result(TBM_ERROR_NONE);
1133
1134         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1135
1136         /* check if the data according to the key exist if so, return false. */
1137         data = user_data_lookup(&bo->user_data_list, key);
1138         if (data) {
1139                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1140                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1141                 _tbm_bufmgr_mutex_unlock();
1142                 return 0;
1143         }
1144
1145         data = user_data_create(key, data_free_func);
1146         if (!data) {
1147                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1148                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1149                 _tbm_bufmgr_mutex_unlock();
1150                 return 0;
1151         }
1152
1153         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1154
1155         LIST_ADD(&data->item_link, &bo->user_data_list);
1156
1157         _tbm_bufmgr_mutex_unlock();
1158
1159         return 1;
1160 }
1161
1162 int
1163 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1164 {
1165         tbm_user_data *old_data;
1166
1167         _tbm_bufmgr_mutex_lock();
1168         _tbm_set_last_result(TBM_ERROR_NONE);
1169
1170         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1171
1172         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1173                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1174                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1175                 _tbm_bufmgr_mutex_unlock();
1176                 return 0;
1177         }
1178
1179         old_data = user_data_lookup(&bo->user_data_list, key);
1180         if (!old_data) {
1181                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1182                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1183                 _tbm_bufmgr_mutex_unlock();
1184                 return 0;
1185         }
1186
1187         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1188
1189         user_data_delete(old_data);
1190
1191         _tbm_bufmgr_mutex_unlock();
1192
1193         return 1;
1194 }
1195
1196 int
1197 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1198 {
1199         tbm_user_data *old_data;
1200
1201         _tbm_bufmgr_mutex_lock();
1202         _tbm_set_last_result(TBM_ERROR_NONE);
1203
1204         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1205
1206         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1207                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1208                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1209                 _tbm_bufmgr_mutex_unlock();
1210                 return 0;
1211         }
1212
1213         old_data = user_data_lookup(&bo->user_data_list, key);
1214         if (!old_data) {
1215                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1216                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1217                 _tbm_bufmgr_mutex_unlock();
1218                 return 0;
1219         }
1220
1221         if (old_data->data && old_data->free_func)
1222                 old_data->free_func(old_data->data);
1223         old_data->data = data;
1224
1225         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1226
1227         _tbm_bufmgr_mutex_unlock();
1228
1229         return 1;
1230 }
1231
1232 int
1233 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1234 {
1235         tbm_user_data *old_data;
1236
1237         _tbm_bufmgr_mutex_lock();
1238         _tbm_set_last_result(TBM_ERROR_NONE);
1239
1240         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1241
1242         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1243                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1244                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1245                 _tbm_bufmgr_mutex_unlock();
1246                 return 0;
1247         }
1248
1249         old_data = user_data_lookup(&bo->user_data_list, key);
1250         if (!old_data) {
1251                 *data = NULL;
1252                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1253                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1254                 _tbm_bufmgr_mutex_unlock();
1255                 return 0;
1256         }
1257
1258         *data = old_data->data;
1259
1260         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1261
1262         _tbm_bufmgr_mutex_unlock();
1263
1264         return 1;
1265 }
1266
1267 int
1268 tbm_bo_get_flags(tbm_bo bo)
1269 {
1270         int flags;
1271
1272         _tbm_bufmgr_mutex_lock();
1273
1274         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1275
1276         flags = bo->flags;
1277
1278         TBM_TRACE_BO("bo(%p)\n", bo);
1279
1280         _tbm_bufmgr_mutex_unlock();
1281
1282         return flags;
1283 }
1284
1285 /* LCOV_EXCL_START */
1286 /* internal function */
1287 int
1288 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1289 {
1290         _tbm_bufmgr_mutex_lock();
1291
1292         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1293
1294         bo->surface = surface;
1295
1296         _tbm_bufmgr_mutex_unlock();
1297
1298         return 1;
1299 }
1300
1301 void
1302 _tbm_bo_free(tbm_bo bo)
1303 {
1304         /* destory the user_data_list */
1305         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1306                 tbm_user_data *old_data = NULL, *tmp;
1307
1308                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1309                                 &bo->user_data_list, item_link) {
1310                         TBM_DBG("free user_data\n");
1311                         user_data_delete(old_data);
1312                 }
1313         }
1314
1315         while (bo->lock_cnt > 0) {
1316                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1317                 _bo_unlock(bo);
1318                 bo->lock_cnt--;
1319         }
1320
1321         /* call the bo_free */
1322         if (bo->bufmgr->use_hal_tbm) {
1323                 // call hal_tbm_bo_free when bo is created by tbm_bo_alloc api.
1324                 if (!bo->get_from_hal_surface) {
1325                         bo->get_from_hal_surface = 0;
1326
1327                         hal_tbm_bo_free(bo->bo_data);
1328                         bo->bo_data = NULL;
1329                 }
1330         } else if (bo->bufmgr->backend_module_data) {
1331                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1332                 bo->bo_data = NULL;
1333         } else {
1334                 bo->bufmgr->backend->bo_free(bo);
1335                 bo->priv = NULL;
1336         }
1337
1338         _tbm_bo_deinit(bo);
1339
1340         free(bo);
1341 }
1342 /* LCOV_EXCL_STOP */