tbm_bo: remove tbm_bo_alloc_with_surface
[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;
844         tbm_bo bo2 = NULL;
845         void *bo_priv;
846         tbm_error_e error;
847         tbm_backend_bo_data *bo_data;
848         int flags;
849
850         _tbm_bufmgr_mutex_lock();
851         _tbm_set_last_result(TBM_ERROR_NONE);
852
853         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
854
855         if (!bufmgr->use_hal_tbm) {
856                 if (bufmgr->backend_module_data) {
857                         if (!bufmgr->bufmgr_func->bufmgr_import_key) {
858                                 /* LCOV_EXCL_START */
859                                 _tbm_bufmgr_mutex_unlock();
860                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
861                                 return NULL;
862                                 /* LCOV_EXCL_STOP */
863                         }
864                 } else {
865                         if (!bufmgr->backend->bo_import) {
866                                 /* LCOV_EXCL_START */
867                                 _tbm_bufmgr_mutex_unlock();
868                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
869                                 return NULL;
870                                 /* LCOV_EXCL_STOP */
871                         }
872                 }
873         }
874
875         _tbm_util_check_bo_cnt(bufmgr);
876
877         bo = calloc(1, sizeof(struct _tbm_bo));
878         if (!bo) {
879                 /* LCOV_EXCL_START */
880                 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
881                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
882                 _tbm_bufmgr_mutex_unlock();
883                 return NULL;
884                 /* LCOV_EXCL_STOP */
885         }
886
887         if (bufmgr->use_hal_tbm) {
888                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_import_key(bufmgr->hal_bufmgr, key, (hal_tbm_error *)&error);
889                 /* LCOV_EXCL_START */
890                 if (!bo_data) {
891                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
892                         _tbm_set_last_result(error);
893                         goto import_fail;
894                 }
895                 /* LCOV_EXCL_STOP */
896                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
897                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
898                                 if (bo2->bo_data == bo_data) {
899                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
900                                                         bo2, bo2->ref_cnt, key,
901                                                         _tbm_flag_to_str(bo2->flags));
902                                         bo2->ref_cnt++;
903                                         free(bo);
904                                         _tbm_bufmgr_mutex_unlock();
905                                         return bo2;
906                                 }
907                         }
908                 }
909                 bo->bo_data = bo_data;
910         } else if (bufmgr->backend_module_data) {
911                 bo_data = bufmgr->bufmgr_func->bufmgr_import_key(bufmgr->bufmgr_data, key, &error);
912                 if (!bo_data) {
913                         /* LCOV_EXCL_START */
914                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
915                         _tbm_set_last_result(error);
916                         goto import_fail;
917                         /* LCOV_EXCL_STOP */
918                 }
919
920                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
921                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
922                                 if (bo2->bo_data == bo_data) {
923                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
924                                                         bo2, bo2->ref_cnt, key,
925                                                         _tbm_flag_to_str(bo2->flags));
926                                         bo2->ref_cnt++;
927                                         free(bo);
928                                         _tbm_bufmgr_mutex_unlock();
929                                         return bo2;
930                                 }
931                         }
932                 }
933                 bo->bo_data = bo_data;
934         } else {
935                 bo_priv = bufmgr->backend->bo_import(bo, key);
936                 if (!bo_priv) {
937                         /* LCOV_EXCL_START */
938                         TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
939                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
940                         goto import_fail;
941                         /* LCOV_EXCL_STOP */
942                 }
943
944                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
945                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
946                                 if (bo2->priv == bo_priv) {
947                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
948                                                         bo2, bo2->ref_cnt, key,
949                                                         _tbm_flag_to_str(bo2->flags));
950                                         bo2->ref_cnt++;
951                                         free(bo);
952                                         _tbm_bufmgr_mutex_unlock();
953                                         return bo2;
954                                 }
955                         }
956                 }
957                 bo->priv = bo_priv;
958         }
959
960         if (bufmgr->use_hal_tbm) {
961                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
962                 if (error != TBM_ERROR_NONE) {
963                         TBM_ERR("fail to get the bo flags(memory_types)");
964                         _tbm_set_last_result(error);
965                         flags = TBM_BO_DEFAULT;
966                 }
967         } else if (bufmgr->backend_module_data) {
968                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
969                 if (error != TBM_ERROR_NONE) {
970                         TBM_ERR("fail to get the bo flags(memory_types)");
971                         _tbm_set_last_result(error);
972                         flags = TBM_BO_DEFAULT;
973                 }
974         } else {
975                 if (bufmgr->backend->bo_get_flags)
976                         flags = bufmgr->backend->bo_get_flags(bo);
977                 else
978                         flags = TBM_BO_DEFAULT;
979         }
980
981         _tbm_bo_init(bufmgr, bo, flags);
982
983         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
984                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
985
986         _tbm_bufmgr_mutex_unlock();
987
988         return bo;
989
990 import_fail:
991         free(bo);
992         _tbm_bufmgr_mutex_unlock();
993         return NULL;
994 }
995
996 tbm_bo
997 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
998 {
999         tbm_bo bo;
1000         tbm_bo bo2 = NULL;
1001         void *bo_priv;
1002         tbm_backend_bo_data *bo_data;
1003         tbm_error_e error;
1004         int flags;
1005
1006         _tbm_bufmgr_mutex_lock();
1007         _tbm_set_last_result(TBM_ERROR_NONE);
1008
1009         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1010
1011         if (!bufmgr->use_hal_tbm) {
1012                 if (bufmgr->backend_module_data) {
1013                         if (!bufmgr->bufmgr_func->bufmgr_import_fd) {
1014                                 /* LCOV_EXCL_START */
1015                                 _tbm_bufmgr_mutex_unlock();
1016                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1017                                 return NULL;
1018                                 /* LCOV_EXCL_STOP */
1019                         }
1020                 } else {
1021                         if (!bufmgr->backend->bo_import_fd) {
1022                                 /* LCOV_EXCL_START */
1023                                 _tbm_bufmgr_mutex_unlock();
1024                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1025                                 return NULL;
1026                                 /* LCOV_EXCL_STOP */
1027                         }
1028                 }
1029         }
1030
1031         _tbm_util_check_bo_cnt(bufmgr);
1032
1033         bo = calloc(1, sizeof(struct _tbm_bo));
1034         if (!bo) {
1035                 /* LCOV_EXCL_START */
1036                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1037                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1038                 _tbm_bufmgr_mutex_unlock();
1039                 return NULL;
1040                 /* LCOV_EXCL_STOP */
1041         }
1042
1043         if (bufmgr->use_hal_tbm) {
1044                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_import_fd(bufmgr->hal_bufmgr, (hal_tbm_fd)fd, (hal_tbm_error *)&error);
1045                 /* LCOV_EXCL_START */
1046                 if (!bo_data) {
1047                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
1048                         _tbm_set_last_result(error);
1049                         goto import_fail;
1050                 }
1051                 /* LCOV_EXCL_STOP */
1052
1053                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1054                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1055                                 if (bo2->bo_data == bo_data) {
1056                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1057                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1058                                         bo2->ref_cnt++;
1059                                         free(bo);
1060                                         _tbm_bufmgr_mutex_unlock();
1061                                         return bo2;
1062                                 }
1063                         }
1064                 }
1065                 bo->bo_data = bo_data;
1066         } else if (bufmgr->backend_module_data) {
1067                 bo_data = bufmgr->bufmgr_func->bufmgr_import_fd(bufmgr->bufmgr_data, fd, &error);
1068                 if (!bo_data) {
1069                         /* LCOV_EXCL_START */
1070                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
1071                         _tbm_set_last_result(error);
1072                         goto import_fail;
1073                         /* LCOV_EXCL_STOP */
1074                 }
1075
1076                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1077                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1078                                 if (bo2->bo_data == bo_data) {
1079                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1080                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1081                                         bo2->ref_cnt++;
1082                                         free(bo);
1083                                         _tbm_bufmgr_mutex_unlock();
1084                                         return bo2;
1085                                 }
1086                         }
1087                 }
1088                 bo->bo_data = bo_data;
1089         } else {
1090                 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1091                 if (!bo_priv) {
1092                         /* LCOV_EXCL_START */
1093                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1094                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1095                         goto import_fail;
1096                         /* LCOV_EXCL_STOP */
1097                 }
1098
1099                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1100                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1101                                 if (bo2->priv == bo_priv) {
1102                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1103                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1104                                         bo2->ref_cnt++;
1105                                         free(bo);
1106                                         _tbm_bufmgr_mutex_unlock();
1107                                         return bo2;
1108                                 }
1109                         }
1110                 }
1111                 bo->priv = bo_priv;
1112         }
1113
1114         if (bufmgr->use_hal_tbm) {
1115                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1116                 if (error != TBM_ERROR_NONE) {
1117                         TBM_ERR("fail to get the bo flags(memory_types)");
1118                         _tbm_set_last_result(error);
1119                         flags = TBM_BO_DEFAULT;
1120                 }
1121         } else if (bufmgr->backend_module_data) {
1122                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
1123                 if (error != TBM_ERROR_NONE) {
1124                         TBM_ERR("fail to get the bo flags(memory_types)");
1125                         _tbm_set_last_result(error);
1126                         flags = TBM_BO_DEFAULT;
1127                 }
1128         } else {
1129                 if (bufmgr->backend->bo_get_flags)
1130                         flags = bufmgr->backend->bo_get_flags(bo);
1131                 else
1132                         flags = TBM_BO_DEFAULT;
1133         }
1134
1135         _tbm_bo_init(bufmgr, bo, flags);
1136
1137         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
1138                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1139
1140         _tbm_bufmgr_mutex_unlock();
1141
1142         return bo;
1143
1144 import_fail:
1145         free(bo);
1146         _tbm_bufmgr_mutex_unlock();
1147         return NULL;
1148 }
1149
1150 int
1151 tbm_bo_size(tbm_bo bo)
1152 {
1153         int size;
1154         tbm_error_e error;
1155
1156         _tbm_bufmgr_mutex_lock();
1157         _tbm_set_last_result(TBM_ERROR_NONE);
1158
1159         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1160
1161         if (bo->bufmgr->use_hal_tbm) {
1162                 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1163                 if (error != TBM_ERROR_NONE) {
1164                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
1165                         _tbm_set_last_result(TBM_ERROR_NONE);
1166                 }
1167         } else if (bo->bufmgr->backend_module_data) {
1168                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
1169                 if (error != TBM_ERROR_NONE) {
1170                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
1171                         _tbm_set_last_result(TBM_ERROR_NONE);
1172                 }
1173         } else
1174                 size = bo->bufmgr->backend->bo_size(bo);
1175
1176         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
1177
1178         _tbm_bufmgr_mutex_unlock();
1179
1180         return size;
1181 }
1182
1183 int
1184 tbm_bo_locked(tbm_bo bo)
1185 {
1186         _tbm_bufmgr_mutex_lock();
1187         _tbm_set_last_result(TBM_ERROR_NONE);
1188
1189         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1190
1191         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
1192                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1193                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1194                 _tbm_bufmgr_mutex_unlock();
1195                 return 0;
1196         }
1197
1198         if (bo->lock_cnt > 0) {
1199                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1200                 _tbm_bufmgr_mutex_unlock();
1201                 return 1;
1202         }
1203
1204         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1205         _tbm_bufmgr_mutex_unlock();
1206
1207         return 0;
1208 }
1209
1210 int
1211 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1212 {
1213         tbm_error_e error1, error2;
1214         int size1 = -1, size2 = -2;
1215         void *temp;
1216
1217         _tbm_bufmgr_mutex_lock();
1218         _tbm_set_last_result(TBM_ERROR_NONE);
1219
1220         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1221         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1222
1223         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1224
1225         if (bo1->bufmgr->use_hal_tbm) {
1226                 size1 = hal_tbm_bo_get_size((hal_tbm_bo *)bo1->bo_data, (hal_tbm_error *)&error1);
1227                 if (error1 != TBM_ERROR_NONE) {
1228                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1229                         _tbm_set_last_result(error1);
1230                         goto fail;
1231                 }
1232                 size2 = hal_tbm_bo_get_size((hal_tbm_bo *)bo2->bo_data, (hal_tbm_error *)&error2);
1233                 if (error2 != TBM_ERROR_NONE) {
1234                         TBM_ERR("fail to get the size of bo1.(%d)", error2);
1235                         _tbm_set_last_result(error2);
1236                         goto fail;
1237                 }
1238         } else if (bo1->bufmgr->backend_module_data) {
1239                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
1240                 if (error1 != TBM_ERROR_NONE) {
1241                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1242                         _tbm_set_last_result(error1);
1243                         goto fail;
1244                 }
1245                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
1246                 if (error2 != TBM_ERROR_NONE) {
1247                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
1248                         _tbm_set_last_result(error2);
1249                         goto fail;
1250                 }
1251         } else {
1252                 size1 = bo1->bufmgr->backend->bo_size(bo1);
1253                 size2 = bo2->bufmgr->backend->bo_size(bo2);
1254         }
1255
1256         if (size1 != size2) {
1257                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
1258                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1259                 goto fail;
1260         }
1261
1262         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1263
1264         temp = bo1->priv;
1265         bo1->priv = bo2->priv;
1266         bo2->priv = temp;
1267
1268         _tbm_bufmgr_mutex_unlock();
1269
1270         return 1;
1271
1272 fail:
1273         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1274         _tbm_bufmgr_mutex_unlock();
1275
1276         return 0;
1277 }
1278
1279 int
1280 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1281                      tbm_data_free data_free_func)
1282 {
1283         tbm_user_data *data;
1284
1285         _tbm_bufmgr_mutex_lock();
1286         _tbm_set_last_result(TBM_ERROR_NONE);
1287
1288         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1289
1290         /* check if the data according to the key exist if so, return false. */
1291         data = user_data_lookup(&bo->user_data_list, key);
1292         if (data) {
1293                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1294                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1295                 _tbm_bufmgr_mutex_unlock();
1296                 return 0;
1297         }
1298
1299         data = user_data_create(key, data_free_func);
1300         if (!data) {
1301                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1302                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1303                 _tbm_bufmgr_mutex_unlock();
1304                 return 0;
1305         }
1306
1307         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1308
1309         LIST_ADD(&data->item_link, &bo->user_data_list);
1310
1311         _tbm_bufmgr_mutex_unlock();
1312
1313         return 1;
1314 }
1315
1316 int
1317 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1318 {
1319         tbm_user_data *old_data;
1320
1321         _tbm_bufmgr_mutex_lock();
1322         _tbm_set_last_result(TBM_ERROR_NONE);
1323
1324         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1325
1326         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1327                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1328                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1329                 _tbm_bufmgr_mutex_unlock();
1330                 return 0;
1331         }
1332
1333         old_data = user_data_lookup(&bo->user_data_list, key);
1334         if (!old_data) {
1335                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1336                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1337                 _tbm_bufmgr_mutex_unlock();
1338                 return 0;
1339         }
1340
1341         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1342
1343         user_data_delete(old_data);
1344
1345         _tbm_bufmgr_mutex_unlock();
1346
1347         return 1;
1348 }
1349
1350 int
1351 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1352 {
1353         tbm_user_data *old_data;
1354
1355         _tbm_bufmgr_mutex_lock();
1356         _tbm_set_last_result(TBM_ERROR_NONE);
1357
1358         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1359
1360         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1361                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1362                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1363                 _tbm_bufmgr_mutex_unlock();
1364                 return 0;
1365         }
1366
1367         old_data = user_data_lookup(&bo->user_data_list, key);
1368         if (!old_data) {
1369                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1370                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1371                 _tbm_bufmgr_mutex_unlock();
1372                 return 0;
1373         }
1374
1375         if (old_data->data && old_data->free_func)
1376                 old_data->free_func(old_data->data);
1377         old_data->data = data;
1378
1379         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1380
1381         _tbm_bufmgr_mutex_unlock();
1382
1383         return 1;
1384 }
1385
1386 int
1387 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1388 {
1389         tbm_user_data *old_data;
1390
1391         _tbm_bufmgr_mutex_lock();
1392         _tbm_set_last_result(TBM_ERROR_NONE);
1393
1394         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1395
1396         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1397                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1398                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1399                 _tbm_bufmgr_mutex_unlock();
1400                 return 0;
1401         }
1402
1403         old_data = user_data_lookup(&bo->user_data_list, key);
1404         if (!old_data) {
1405                 *data = NULL;
1406                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1407                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1408                 _tbm_bufmgr_mutex_unlock();
1409                 return 0;
1410         }
1411
1412         *data = old_data->data;
1413
1414         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1415
1416         _tbm_bufmgr_mutex_unlock();
1417
1418         return 1;
1419 }
1420
1421 int
1422 tbm_bo_get_flags(tbm_bo bo)
1423 {
1424         int flags;
1425
1426         _tbm_bufmgr_mutex_lock();
1427
1428         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1429
1430         flags = bo->flags;
1431
1432         TBM_TRACE_BO("bo(%p)\n", bo);
1433
1434         _tbm_bufmgr_mutex_unlock();
1435
1436         return flags;
1437 }
1438
1439 /* LCOV_EXCL_START */
1440 /* internal function */
1441 int
1442 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1443 {
1444         _tbm_bufmgr_mutex_lock();
1445
1446         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1447
1448         bo->surface = surface;
1449
1450         _tbm_bufmgr_mutex_unlock();
1451
1452         return 1;
1453 }
1454
1455 void
1456 _tbm_bo_free(tbm_bo bo)
1457 {
1458         /* destory the user_data_list */
1459         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1460                 tbm_user_data *old_data = NULL, *tmp;
1461
1462                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1463                                 &bo->user_data_list, item_link) {
1464                         TBM_DBG("free user_data\n");
1465                         user_data_delete(old_data);
1466                 }
1467         }
1468
1469         while (bo->lock_cnt > 0) {
1470                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1471                 _bo_unlock(bo);
1472                 bo->lock_cnt--;
1473         }
1474
1475         /* call the bo_free */
1476         if (bo->bufmgr->use_hal_tbm) {
1477                 // call hal_tbm_bo_free when bo is created by tbm_bo_alloc api.
1478                 if (!bo->get_from_hal_surface) {
1479                         bo->get_from_hal_surface = 0;
1480
1481                         hal_tbm_bo_free(bo->bo_data);
1482                         bo->bo_data = NULL;
1483                 }
1484         } else if (bo->bufmgr->backend_module_data) {
1485                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1486                 bo->bo_data = NULL;
1487         } else {
1488                 bo->bufmgr->backend->bo_free(bo);
1489                 bo->priv = NULL;
1490         }
1491
1492         _tbm_bo_deinit(bo);
1493
1494         free(bo);
1495 }
1496 /* LCOV_EXCL_STOP */