tbm_bo: do not use error log parameter
[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_NONE) {
161                         TBM_WRN("fail to lock");
162                         _tbm_set_last_result(error);
163                         ret = 0;
164                 }
165         } else if (bo->bufmgr->backend_module_data) {
166                 if (bo->bufmgr->bo_func->bo_lock) {
167                         error = bo->bufmgr->bo_func->bo_lock(bo->bo_data, device, opt);
168                         if (error != TBM_ERROR_NONE) {
169                                 TBM_WRN("fail to lock");
170                                 _tbm_set_last_result(error);
171                                 ret = 0;
172                         }
173                 }
174         } else {
175                 if (bo->bufmgr->backend->bo_lock) {
176                         ret = bo->bufmgr->backend->bo_lock(bo, device, opt);
177                         if (!ret)
178                                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
179                 }
180         }
181
182         return ret;
183 }
184
185 static void
186 _bo_unlock(tbm_bo bo)
187 {
188         tbm_error_e error;
189
190         if (bo->bufmgr->use_hal_tbm) {
191                 error = (tbm_error_e)hal_tbm_bo_unlock((hal_tbm_bo *)bo->bo_data);
192                 if (error != TBM_ERROR_NONE) {
193                         TBM_WRN("fail to lock");
194                         _tbm_set_last_result(error);
195                 }
196         } else if (bo->bufmgr->backend_module_data) {
197                 if (bo->bufmgr->bo_func->bo_unlock) {
198                         error = bo->bufmgr->bo_func->bo_unlock(bo->bo_data);
199                         if (error != TBM_ERROR_NONE) {
200                                 TBM_WRN("fail to unlock");
201                                 _tbm_set_last_result(error);
202                         }
203                 }
204         } else {
205                 if (bo->bufmgr->backend->bo_unlock)
206                         bo->bufmgr->backend->bo_unlock(bo);
207         }
208 }
209
210 static int
211 _tbm_bo_lock(tbm_bo bo, int device, int opt)
212 {
213         int old, ret;
214
215         if (!bo)
216                 return 0;
217
218         /* do not try to lock the bo */
219         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
220                 return 1;
221
222         if (bo->lock_cnt < 0) {
223                 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
224                         bo, bo->lock_cnt);
225                 return 0;
226         }
227
228         old = bo->lock_cnt;
229
230         switch (bo->bufmgr->bo_lock_type) {
231         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
232                 if (bo->lock_cnt == 0) {
233                         _tbm_bufmgr_mutex_unlock();
234                         ret = _bo_lock(bo, device, opt);
235                         _tbm_bufmgr_mutex_lock();
236                         if (ret)
237                                 bo->lock_cnt++;
238                 } else
239                         ret = 1;
240                 break;
241         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
242                 _tbm_bufmgr_mutex_unlock();
243                 ret = _bo_lock(bo, device, opt);
244                 _tbm_bufmgr_mutex_lock();
245                 if (ret)
246                         bo->lock_cnt++;
247                 break;
248         default:
249                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
250                                 bo, bo->bufmgr->bo_lock_type);
251                 ret = 0;
252                 break;
253         }
254
255         TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
256
257         return ret;
258 }
259
260 static void
261 _tbm_bo_unlock(tbm_bo bo)
262 {
263         int old;
264
265         /* do not try to unlock the bo */
266         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
267                 return;
268
269         old = bo->lock_cnt;
270
271         switch (bo->bufmgr->bo_lock_type) {
272         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
273                 if (bo->lock_cnt > 0) {
274                         bo->lock_cnt--;
275                         if (bo->lock_cnt == 0)
276                                 _bo_unlock(bo);
277                 }
278                 break;
279         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
280                 if (bo->lock_cnt > 0) {
281                         bo->lock_cnt--;
282                         _bo_unlock(bo);
283                 }
284                 break;
285         default:
286                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
287                                 bo, bo->bufmgr->bo_lock_type);
288                 break;
289         }
290
291         if (bo->lock_cnt < 0)
292                 bo->lock_cnt = 0;
293
294         TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
295 }
296
297 static int
298 _tbm_bo_magic_check(tbm_bo bo)
299 {
300         if (bo->magic != TBM_BO_MAGIC)
301                 return 0;
302
303         return 1;
304 }
305
306 static int
307 _tbm_bo_is_valid(tbm_bo bo)
308 {
309         if (!bo) {
310                 TBM_ERR("error: bo is NULL.\n");
311                 return 0;
312         }
313
314         if (!_tbm_bo_magic_check(bo)) {
315                 TBM_ERR("error: No valid bo(%p).\n", bo);
316                 return 0;
317         }
318
319         return 1;
320 }
321
322 static void
323 _tbm_bo_init(tbm_bufmgr bufmgr, tbm_bo bo, int flags)
324 {
325         bo->bufmgr = bufmgr;
326         bo->flags = flags;
327         bo->magic = TBM_BO_MAGIC;
328         bo->ref_cnt = 1;
329
330         LIST_INITHEAD(&bo->user_data_list);
331
332         bufmgr->bo_cnt++;
333         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
334 }
335
336 static void
337 _tbm_bo_deinit(tbm_bo bo)
338 {
339         bo->magic = 0;
340
341         bo->bufmgr->bo_cnt--;
342         LIST_DEL(&bo->item_link);
343 }
344
345 tbm_bo
346 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
347 {
348         tbm_bo bo;
349         void *bo_priv;
350         tbm_backend_bo_data *bo_data;
351         tbm_error_e error;
352
353         _tbm_bufmgr_mutex_lock();
354         _tbm_set_last_result(TBM_ERROR_NONE);
355
356         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
357         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
358
359         bo = calloc(1, sizeof(struct _tbm_bo));
360         if (!bo) {
361                 /* LCOV_EXCL_START */
362                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
363                 _tbm_bufmgr_mutex_unlock();
364                 return NULL;
365                 /* LCOV_EXCL_STOP */
366         }
367
368         _tbm_util_check_bo_cnt(bufmgr);
369
370         if (bufmgr->use_hal_tbm) {
371                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo(bufmgr->hal_bufmgr, size, flags, (hal_tbm_error *)&error);
372                 /* LCOV_EXCL_START */
373                 if (!bo_data) {
374                         _tbm_set_last_result(error);
375                         goto alloc_fail;
376                 }
377                 /* LCOV_EXCL_STOP */
378                 bo->bo_data = bo_data;
379         } else if (bufmgr->backend_module_data) {
380                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo(bufmgr->bufmgr_data, (unsigned int)size, flags, &error);
381                 if (!bo_data) {
382                         /* LCOV_EXCL_START */
383                         _tbm_set_last_result(error);
384                         goto alloc_fail;
385                         /* LCOV_EXCL_STOP */
386                 }
387                 bo->bo_data = bo_data;
388         } else {
389                 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
390                 if (!bo_priv) {
391                         /* LCOV_EXCL_START */
392                         
393                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
394                         goto alloc_fail;
395                         /* LCOV_EXCL_STOP */
396                 }
397                 bo->priv = bo_priv;
398         }
399
400         _tbm_bo_init(bufmgr, bo, flags);
401
402         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
403                         _tbm_flag_to_str(bo->flags));
404
405         _tbm_bufmgr_mutex_unlock();
406
407         return bo;
408
409 alloc_fail:
410         TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, _tbm_flag_to_str(flags));
411         free(bo);
412         _tbm_bufmgr_mutex_unlock();
413         return NULL;
414 }
415
416 /* LCOV_EXCL_START */
417 tbm_bo
418 tbm_bo_alloc_with_format(tbm_bufmgr bufmgr, int format, int bo_idx, int width,
419                                                 int height, tbm_bo_memory_type flags, tbm_error_e *error)
420 {
421         tbm_bo bo;
422         tbm_backend_bo_data *bo_data;
423
424         _tbm_bufmgr_mutex_lock();
425         _tbm_set_last_result(TBM_ERROR_NONE);
426
427         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
428
429         bo = calloc(1, sizeof(struct _tbm_bo));
430         if (!bo) {
431                 TBM_ERR("error: fail to tbm_bo_alloc_with_format fmt(%s) idx(%d) w(%d) h(%d) mem_types(%s)\n",
432                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
433                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
434                 goto calloc_fail;
435         }
436
437         _tbm_util_check_bo_cnt(bufmgr);
438
439         /* LCOV_EXCL_START */
440         if (!bufmgr->use_hal_tbm) {
441                 if (!bufmgr->backend_module_data || !bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
442                         
443                         TBM_ERR("error: not supported tbm_bo_alloc_with_format\n");
444                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
445                         goto bo_alloc_fail;
446                 }
447         }
448         /* LCOV_EXCL_STOP */
449
450         if (bufmgr->use_hal_tbm) {
451                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo_with_format(bufmgr->hal_bufmgr,
452                                                                 format, bo_idx, width, height, (hal_tbm_bo_memory_type)flags, (hal_tbm_error *)error);
453                 if (!bo_data) {
454                         TBM_ERR("error: fail to tbm_bo_alloc_with_format\n");
455                         _tbm_set_last_result(*error);
456                         goto bo_alloc_fail;
457                 }
458         } else {
459                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format(bufmgr->bufmgr_data, format, bo_idx,
460                                                                                                                                 width, height, flags, error);
461                 if (!bo_data) {
462                         TBM_ERR("error: fail to tbm_bo_alloc_with_format fmt(%s) idx(%d) w(%d) h(%d) mem_types(%s)\n",
463                                         FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
464                         _tbm_set_last_result(*error);
465                         goto bo_alloc_fail;
466                 }
467         }
468
469         bo->bo_data = bo_data;
470         _tbm_bo_init(bufmgr, bo, flags);
471
472         _tbm_bufmgr_mutex_unlock();
473
474         return bo;
475
476 bo_alloc_fail:
477         free(bo);
478 calloc_fail:
479         _tbm_bufmgr_mutex_unlock();
480         return NULL;
481 }
482
483 tbm_bo
484 tbm_bo_alloc_with_tiled_format(tbm_bufmgr bufmgr, int width, int height, int bpp, int format,
485                                                         tbm_bo_memory_type flags, int bo_idx, tbm_error_e *error)
486 {
487         tbm_bo bo;
488         tbm_backend_bo_data *bo_data;
489
490         _tbm_bufmgr_mutex_lock();
491         _tbm_set_last_result(TBM_ERROR_NONE);
492
493         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
494
495         bo = calloc(1, sizeof(struct _tbm_bo));
496         if (!bo) {
497                 TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
498                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
499                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
500                 _tbm_bufmgr_mutex_unlock();
501                 return NULL;
502         }
503
504         _tbm_util_check_bo_cnt(bufmgr);
505
506         if (!bufmgr->use_hal_tbm) {
507                 if (!bufmgr->backend_module_data || !bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format) {
508                         TBM_ERR("error: not supported tbm_bo_alloc_with_tiled_format\n");
509                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
510                         free(bo);
511                         _tbm_bufmgr_mutex_unlock();
512                         return NULL;
513                 }
514         }
515
516         if (bufmgr->use_hal_tbm)
517                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_alloc_bo_with_tiled_format(bufmgr->hal_bufmgr,
518                                                                 width, height, bpp, format, (hal_tbm_bo_memory_type)flags, bo_idx, (hal_tbm_error *)error);
519         else
520                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format(bufmgr->bufmgr_data, width, height,
521                                                                                                                                         bpp, format, flags, bo_idx, error);
522         if (!bo_data) {
523                 TBM_ERR("error: fail to tbm_bo_alloc_with_tiled_format fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
524                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
525                 _tbm_set_last_result(*error);
526                 free(bo);
527                 _tbm_bufmgr_mutex_unlock();
528                 return NULL;
529         }
530
531         bo->bo_data = bo_data;
532         _tbm_bo_init(bufmgr, bo, flags);
533
534         _tbm_bufmgr_mutex_unlock();
535
536         return bo;
537 }
538
539 tbm_bo
540 tbm_bo_alloc_with_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, int bo_idx)
541 {
542         tbm_bo bo;
543         void *bo_priv;
544
545         _tbm_bufmgr_mutex_lock();
546         _tbm_set_last_result(TBM_ERROR_NONE);
547
548         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
549
550         bo = calloc(1, sizeof(struct _tbm_bo));
551         if (!bo) {
552                 TBM_ERR("error: fail to tbm_bo_alloc_with_surface fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
553                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
554                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
555                 _tbm_bufmgr_mutex_unlock();
556                 return NULL;
557         }
558
559         _tbm_util_check_bo_cnt(bufmgr);
560
561         if (!bufmgr->backend->surface_bo_alloc) {
562                 TBM_ERR("error: not supported tbm_bo_alloc_with_surface\n");
563                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
564                 free(bo);
565                 _tbm_bufmgr_mutex_unlock();
566                 return NULL;
567         }
568
569         bo_priv = bufmgr->backend->surface_bo_alloc(bo, width, height, format, flags, bo_idx);
570         if (!bo_priv) {
571                 TBM_ERR("error: fail to tbm_bo_alloc_with_surface fmt(%s) idx(%d) w(%d) h(%d) flags(%s)\n",
572                                 FOURCC_STR(format), bo_idx, width, height, _tbm_flag_to_str(flags));
573                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
574                 free(bo);
575                 _tbm_bufmgr_mutex_unlock();
576                 return NULL;
577         }
578
579         bo->priv = bo_priv;
580         _tbm_bo_init(bufmgr, bo, flags);
581
582         _tbm_bufmgr_mutex_unlock();
583
584         return bo;
585 }
586 /* LCOV_EXCL_STOP */
587
588 tbm_bo
589 tbm_bo_ref(tbm_bo bo)
590 {
591         _tbm_bufmgr_mutex_lock();
592         _tbm_set_last_result(TBM_ERROR_NONE);
593
594         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
595
596         bo->ref_cnt++;
597
598         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
599
600         _tbm_bufmgr_mutex_unlock();
601
602         return bo;
603 }
604
605 void
606 tbm_bo_unref(tbm_bo bo)
607 {
608         _tbm_bufmgr_mutex_lock();
609         _tbm_set_last_result(TBM_ERROR_NONE);
610
611         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
612
613         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
614
615         if (bo->ref_cnt <= 0) {
616                 _tbm_bufmgr_mutex_unlock();
617                 return;
618         }
619
620         bo->ref_cnt--;
621         if (bo->ref_cnt == 0)
622                 _tbm_bo_free(bo);
623
624         _tbm_bufmgr_mutex_unlock();
625 }
626
627 tbm_bo_handle
628 tbm_bo_map(tbm_bo bo, int device, int opt)
629 {
630         tbm_bo_handle bo_handle;
631         tbm_error_e error;
632
633         _tbm_bufmgr_mutex_lock();
634         _tbm_set_last_result(TBM_ERROR_NONE);
635
636         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
637
638         if (!_tbm_bo_lock(bo, device, opt)) {
639                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
640                 _tbm_bufmgr_mutex_unlock();
641                 return (tbm_bo_handle) NULL;
642         }
643
644         if (bo->bufmgr->use_hal_tbm) {
645                 hal_tbm_bo_handle hbo_handle;
646                 hbo_handle = hal_tbm_bo_map((hal_tbm_bo *)bo->bo_data, device, opt, (hal_tbm_error *)&error);
647                 if (hbo_handle.ptr == NULL) {
648                         /* LCOV_EXCL_START */
649                         _tbm_set_last_result(error);
650                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
651                         goto bo_map_fail;
652                         /* LCOV_EXCL_STOP */
653                 }
654                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
655         } else if (bo->bufmgr->backend_module_data) {
656                 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
657                 if (bo_handle.ptr == NULL) {
658                         /* LCOV_EXCL_START */
659                         _tbm_set_last_result(error);
660                         TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
661                         goto bo_map_fail;
662                         /* LCOV_EXCL_STOP */
663                 }
664         } else {
665                 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
666                 if (bo_handle.ptr == NULL) {
667                         /* LCOV_EXCL_START */
668                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
669                         TBM_ERR("error: fail to map bo:%p\n", bo);
670                         goto bo_map_fail;
671                         /* LCOV_EXCL_STOP */
672                 }
673         }
674
675         /* increase the map_count */
676         bo->map_cnt++;
677
678         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
679
680         _tbm_bufmgr_mutex_unlock();
681
682         return bo_handle;
683
684 bo_map_fail:
685         _tbm_bo_unlock(bo);
686         _tbm_bufmgr_mutex_unlock();
687         return (tbm_bo_handle) NULL;
688 }
689
690 int
691 tbm_bo_unmap(tbm_bo bo)
692 {
693         int ret = 1;
694         tbm_error_e error;
695
696         _tbm_bufmgr_mutex_lock();
697         _tbm_set_last_result(TBM_ERROR_NONE);
698
699         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
700         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
701
702         if (bo->bufmgr->use_hal_tbm) {
703                 error = (hal_tbm_error)hal_tbm_bo_unmap((hal_tbm_bo *)bo->bo_data);
704                 if (error != TBM_ERROR_NONE) {
705                         /* LCOV_EXCL_START */
706                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
707                         _tbm_set_last_result(error);
708                         ret = 0;
709                         goto done;
710                         /* LCOV_EXCL_STOP */
711                 }
712         } else if (bo->bufmgr->backend_module_data) {
713                 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
714                 if (error != TBM_ERROR_NONE) {
715                         /* LCOV_EXCL_START */
716                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
717                         _tbm_set_last_result(error);
718                         ret = 0;
719                         goto done;
720                         /* LCOV_EXCL_STOP */
721                 }
722         } else {
723                 ret = bo->bufmgr->backend->bo_unmap(bo);
724                 if (!ret) {
725                         /* LCOV_EXCL_START */
726                         TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
727                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
728                         goto done;
729                         /* LCOV_EXCL_STOP */
730                 }
731         }
732
733         /* decrease the map_count */
734         bo->map_cnt--;
735
736         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
737
738         _tbm_bo_unlock(bo);
739
740 done:
741         _tbm_bufmgr_mutex_unlock();
742
743         return ret;
744 }
745
746 tbm_bo_handle
747 tbm_bo_get_handle(tbm_bo bo, int device)
748 {
749         tbm_bo_handle bo_handle;
750         tbm_error_e error;
751
752         _tbm_bufmgr_mutex_lock();
753         _tbm_set_last_result(TBM_ERROR_NONE);
754
755         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
756
757         if (bo->bufmgr->use_hal_tbm) {
758                 hal_tbm_bo_handle hbo_handle;
759                 hbo_handle = hal_tbm_bo_get_handle((hal_tbm_bo *)bo->bo_data, device, (hal_tbm_error *)&error);
760                 if (hbo_handle.ptr == NULL) {
761                         /* LCOV_EXCL_START */
762                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
763                         _tbm_set_last_result(error);
764                         goto bo_handle_fail;
765                         /* LCOV_EXCL_STOP */
766                 }
767                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
768         } else if (bo->bufmgr->backend_module_data) {
769                 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
770                 if (bo_handle.ptr == NULL) {
771                         /* LCOV_EXCL_START */
772                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
773                         _tbm_set_last_result(error);
774                         goto bo_handle_fail;
775                         /* LCOV_EXCL_STOP */
776                 }
777         } else {
778                 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
779                 if (bo_handle.ptr == NULL) {
780                         /* LCOV_EXCL_START */
781                         TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
782                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
783                         goto bo_handle_fail;
784                         /* LCOV_EXCL_STOP */
785                 }
786         }
787
788         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
789
790         _tbm_bufmgr_mutex_unlock();
791
792         return bo_handle;
793
794 bo_handle_fail:
795         _tbm_bufmgr_mutex_unlock();
796         return (tbm_bo_handle) NULL;
797 }
798
799 tbm_key
800 tbm_bo_export(tbm_bo bo)
801 {
802         tbm_key ret;
803         tbm_error_e error;
804
805         _tbm_bufmgr_mutex_lock();
806         _tbm_set_last_result(TBM_ERROR_NONE);
807
808         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
809
810         if (bo->bufmgr->use_hal_tbm) {
811                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
812                 if (!ret) {
813                         /* LCOV_EXCL_START */
814                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
815                         _tbm_set_last_result(error);
816                         goto done;
817                         /* LCOV_EXCL_STOP */
818                 }
819         } else if (bo->bufmgr->backend_module_data) {
820                 if (!bo->bufmgr->bo_func->bo_export_key) {
821                         /* LCOV_EXCL_START */
822                         _tbm_bufmgr_mutex_unlock();
823                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
824                         return 0;
825                         /* LCOV_EXCL_STOP */
826                 }
827
828                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
829                 if (!ret) {
830                         /* LCOV_EXCL_START */
831                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
832                         _tbm_set_last_result(error);
833                         goto done;
834                         /* LCOV_EXCL_STOP */
835                 }
836         } else {
837                 if (!bo->bufmgr->backend->bo_export) {
838                         /* LCOV_EXCL_START */
839                         _tbm_bufmgr_mutex_unlock();
840                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
841                         return 0;
842                         /* LCOV_EXCL_STOP */
843                 }
844
845                 ret = bo->bufmgr->backend->bo_export(bo);
846                 if (!ret) {
847                         /* LCOV_EXCL_START */
848                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
849                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
850                         goto done;
851                         /* LCOV_EXCL_STOP */
852                 }
853         }
854
855         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
856
857 done:
858         _tbm_bufmgr_mutex_unlock();
859
860         return ret;
861 }
862
863 tbm_fd
864 tbm_bo_export_fd(tbm_bo bo)
865 {
866         tbm_fd ret;
867         tbm_error_e error;
868
869         _tbm_bufmgr_mutex_lock();
870         _tbm_set_last_result(TBM_ERROR_NONE);
871
872         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
873
874         if (bo->bufmgr->use_hal_tbm) {
875                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
876                 if (ret < 0) {
877                         /* LCOV_EXCL_START */
878                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
879                         _tbm_set_last_result(error);
880                         goto done;
881                         /* LCOV_EXCL_STOP */
882                 }
883         } else if (bo->bufmgr->backend_module_data) {
884                 if (!bo->bufmgr->bo_func->bo_export_fd) {
885                         /* LCOV_EXCL_START */
886                         _tbm_bufmgr_mutex_unlock();
887                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
888                         return -1;
889                         /* LCOV_EXCL_STOP */
890                 }
891
892                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
893                 if (ret < 0) {
894                         /* LCOV_EXCL_START */
895                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
896                         _tbm_set_last_result(error);
897                         goto done;
898                         /* LCOV_EXCL_STOP */
899                 }
900         } else {
901                 if (!bo->bufmgr->backend->bo_export_fd) {
902                         /* LCOV_EXCL_START */
903                         _tbm_bufmgr_mutex_unlock();
904                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
905                         return -1;
906                         /* LCOV_EXCL_STOP */
907                 }
908
909                 ret = bo->bufmgr->backend->bo_export_fd(bo);
910                 if (ret < 0) {
911                         /* LCOV_EXCL_START */
912                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
913                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
914                         goto done;
915                         /* LCOV_EXCL_STOP */
916                 }
917         }
918
919         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
920
921 done:
922         _tbm_bufmgr_mutex_unlock();
923
924         return ret;
925 }
926
927 tbm_bo
928 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
929 {
930         tbm_bo bo;
931         tbm_bo bo2 = NULL;
932         void *bo_priv;
933         tbm_error_e error;
934         tbm_backend_bo_data *bo_data;
935         int flags;
936
937         _tbm_bufmgr_mutex_lock();
938         _tbm_set_last_result(TBM_ERROR_NONE);
939
940         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
941
942         if (!bufmgr->use_hal_tbm) {
943                 if (bufmgr->backend_module_data) {
944                         if (!bufmgr->bufmgr_func->bufmgr_import_key) {
945                                 /* LCOV_EXCL_START */
946                                 _tbm_bufmgr_mutex_unlock();
947                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
948                                 return NULL;
949                                 /* LCOV_EXCL_STOP */
950                         }
951                 } else {
952                         if (!bufmgr->backend->bo_import) {
953                                 /* LCOV_EXCL_START */
954                                 _tbm_bufmgr_mutex_unlock();
955                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
956                                 return NULL;
957                                 /* LCOV_EXCL_STOP */
958                         }
959                 }
960         }
961
962         _tbm_util_check_bo_cnt(bufmgr);
963
964         bo = calloc(1, sizeof(struct _tbm_bo));
965         if (!bo) {
966                 /* LCOV_EXCL_START */
967                 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
968                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
969                 _tbm_bufmgr_mutex_unlock();
970                 return NULL;
971                 /* LCOV_EXCL_STOP */
972         }
973
974         if (bufmgr->use_hal_tbm) {
975                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_import_key(bufmgr->hal_bufmgr, key, (hal_tbm_error *)&error);
976                 /* LCOV_EXCL_START */
977                 if (!bo_data) {
978                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
979                         _tbm_set_last_result(error);
980                         goto import_fail;
981                 }
982                 /* LCOV_EXCL_STOP */
983                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
984                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
985                                 if (bo2->bo_data == bo_data) {
986                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
987                                                         bo2, bo2->ref_cnt, key,
988                                                         _tbm_flag_to_str(bo2->flags));
989                                         bo2->ref_cnt++;
990                                         free(bo);
991                                         _tbm_bufmgr_mutex_unlock();
992                                         return bo2;
993                                 }
994                         }
995                 }
996                 bo->bo_data = bo_data;
997         } else if (bufmgr->backend_module_data) {
998                 bo_data = bufmgr->bufmgr_func->bufmgr_import_key(bufmgr->bufmgr_data, key, &error);
999                 if (!bo_data) {
1000                         /* LCOV_EXCL_START */
1001                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
1002                         _tbm_set_last_result(error);
1003                         goto import_fail;
1004                         /* LCOV_EXCL_STOP */
1005                 }
1006
1007                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1008                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1009                                 if (bo2->bo_data == bo_data) {
1010                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1011                                                         bo2, bo2->ref_cnt, key,
1012                                                         _tbm_flag_to_str(bo2->flags));
1013                                         bo2->ref_cnt++;
1014                                         free(bo);
1015                                         _tbm_bufmgr_mutex_unlock();
1016                                         return bo2;
1017                                 }
1018                         }
1019                 }
1020                 bo->bo_data = bo_data;
1021         } else {
1022                 bo_priv = bufmgr->backend->bo_import(bo, key);
1023                 if (!bo_priv) {
1024                         /* LCOV_EXCL_START */
1025                         TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
1026                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1027                         goto import_fail;
1028                         /* LCOV_EXCL_STOP */
1029                 }
1030
1031                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1032                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1033                                 if (bo2->priv == bo_priv) {
1034                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1035                                                         bo2, bo2->ref_cnt, key,
1036                                                         _tbm_flag_to_str(bo2->flags));
1037                                         bo2->ref_cnt++;
1038                                         free(bo);
1039                                         _tbm_bufmgr_mutex_unlock();
1040                                         return bo2;
1041                                 }
1042                         }
1043                 }
1044                 bo->priv = bo_priv;
1045         }
1046
1047         if (bufmgr->use_hal_tbm) {
1048                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1049                 if (error != TBM_ERROR_NONE) {
1050                         TBM_ERR("fail to get the bo flags(memory_types)");
1051                         _tbm_set_last_result(error);
1052                         flags = TBM_BO_DEFAULT;
1053                 }
1054         } else if (bufmgr->backend_module_data) {
1055                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
1056                 if (error != TBM_ERROR_NONE) {
1057                         TBM_ERR("fail to get the bo flags(memory_types)");
1058                         _tbm_set_last_result(error);
1059                         flags = TBM_BO_DEFAULT;
1060                 }
1061         } else {
1062                 if (bufmgr->backend->bo_get_flags)
1063                         flags = bufmgr->backend->bo_get_flags(bo);
1064                 else
1065                         flags = TBM_BO_DEFAULT;
1066         }
1067
1068         _tbm_bo_init(bufmgr, bo, flags);
1069
1070         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
1071                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
1072
1073         _tbm_bufmgr_mutex_unlock();
1074
1075         return bo;
1076
1077 import_fail:
1078         free(bo);
1079         _tbm_bufmgr_mutex_unlock();
1080         return NULL;
1081 }
1082
1083 tbm_bo
1084 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
1085 {
1086         tbm_bo bo;
1087         tbm_bo bo2 = NULL;
1088         void *bo_priv;
1089         tbm_backend_bo_data *bo_data;
1090         tbm_error_e error;
1091         int flags;
1092
1093         _tbm_bufmgr_mutex_lock();
1094         _tbm_set_last_result(TBM_ERROR_NONE);
1095
1096         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
1097
1098         if (!bufmgr->use_hal_tbm) {
1099                 if (bufmgr->backend_module_data) {
1100                         if (!bufmgr->bufmgr_func->bufmgr_import_fd) {
1101                                 /* LCOV_EXCL_START */
1102                                 _tbm_bufmgr_mutex_unlock();
1103                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1104                                 return NULL;
1105                                 /* LCOV_EXCL_STOP */
1106                         }
1107                 } else {
1108                         if (!bufmgr->backend->bo_import_fd) {
1109                                 /* LCOV_EXCL_START */
1110                                 _tbm_bufmgr_mutex_unlock();
1111                                 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1112                                 return NULL;
1113                                 /* LCOV_EXCL_STOP */
1114                         }
1115                 }
1116         }
1117
1118         _tbm_util_check_bo_cnt(bufmgr);
1119
1120         bo = calloc(1, sizeof(struct _tbm_bo));
1121         if (!bo) {
1122                 /* LCOV_EXCL_START */
1123                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1124                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1125                 _tbm_bufmgr_mutex_unlock();
1126                 return NULL;
1127                 /* LCOV_EXCL_STOP */
1128         }
1129
1130         if (bufmgr->use_hal_tbm) {
1131                 bo_data = (tbm_backend_bo_data *)hal_tbm_bufmgr_import_fd(bufmgr->hal_bufmgr, (hal_tbm_fd)fd, (hal_tbm_error *)&error);
1132                 /* LCOV_EXCL_START */
1133                 if (!bo_data) {
1134                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
1135                         _tbm_set_last_result(error);
1136                         goto import_fail;
1137                 }
1138                 /* LCOV_EXCL_STOP */
1139
1140                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1141                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1142                                 if (bo2->bo_data == bo_data) {
1143                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1144                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1145                                         bo2->ref_cnt++;
1146                                         free(bo);
1147                                         _tbm_bufmgr_mutex_unlock();
1148                                         return bo2;
1149                                 }
1150                         }
1151                 }
1152                 bo->bo_data = bo_data;
1153         } else if (bufmgr->backend_module_data) {
1154                 bo_data = bufmgr->bufmgr_func->bufmgr_import_fd(bufmgr->bufmgr_data, fd, &error);
1155                 if (!bo_data) {
1156                         /* LCOV_EXCL_START */
1157                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
1158                         _tbm_set_last_result(error);
1159                         goto import_fail;
1160                         /* LCOV_EXCL_STOP */
1161                 }
1162
1163                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1164                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1165                                 if (bo2->bo_data == bo_data) {
1166                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1167                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1168                                         bo2->ref_cnt++;
1169                                         free(bo);
1170                                         _tbm_bufmgr_mutex_unlock();
1171                                         return bo2;
1172                                 }
1173                         }
1174                 }
1175                 bo->bo_data = bo_data;
1176         } else {
1177                 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1178                 if (!bo_priv) {
1179                         /* LCOV_EXCL_START */
1180                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1181                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1182                         goto import_fail;
1183                         /* LCOV_EXCL_STOP */
1184                 }
1185
1186                 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1187                         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1188                                 if (bo2->priv == bo_priv) {
1189                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1190                                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1191                                         bo2->ref_cnt++;
1192                                         free(bo);
1193                                         _tbm_bufmgr_mutex_unlock();
1194                                         return bo2;
1195                                 }
1196                         }
1197                 }
1198                 bo->priv = bo_priv;
1199         }
1200
1201         if (bufmgr->use_hal_tbm) {
1202                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1203                 if (error != TBM_ERROR_NONE) {
1204                         TBM_ERR("fail to get the bo flags(memory_types)");
1205                         _tbm_set_last_result(error);
1206                         flags = TBM_BO_DEFAULT;
1207                 }
1208         } else if (bufmgr->backend_module_data) {
1209                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
1210                 if (error != TBM_ERROR_NONE) {
1211                         TBM_ERR("fail to get the bo flags(memory_types)");
1212                         _tbm_set_last_result(error);
1213                         flags = TBM_BO_DEFAULT;
1214                 }
1215         } else {
1216                 if (bufmgr->backend->bo_get_flags)
1217                         flags = bufmgr->backend->bo_get_flags(bo);
1218                 else
1219                         flags = TBM_BO_DEFAULT;
1220         }
1221
1222         _tbm_bo_init(bufmgr, bo, flags);
1223
1224         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
1225                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1226
1227         _tbm_bufmgr_mutex_unlock();
1228
1229         return bo;
1230
1231 import_fail:
1232         free(bo);
1233         _tbm_bufmgr_mutex_unlock();
1234         return NULL;
1235 }
1236
1237 int
1238 tbm_bo_size(tbm_bo bo)
1239 {
1240         int size;
1241         tbm_error_e error;
1242
1243         _tbm_bufmgr_mutex_lock();
1244         _tbm_set_last_result(TBM_ERROR_NONE);
1245
1246         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1247
1248         if (bo->bufmgr->use_hal_tbm) {
1249                 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
1250                 if (error != TBM_ERROR_NONE) {
1251                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
1252                         _tbm_set_last_result(TBM_ERROR_NONE);
1253                 }
1254         } else if (bo->bufmgr->backend_module_data) {
1255                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
1256                 if (error != TBM_ERROR_NONE) {
1257                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
1258                         _tbm_set_last_result(TBM_ERROR_NONE);
1259                 }
1260         } else
1261                 size = bo->bufmgr->backend->bo_size(bo);
1262
1263         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
1264
1265         _tbm_bufmgr_mutex_unlock();
1266
1267         return size;
1268 }
1269
1270 int
1271 tbm_bo_locked(tbm_bo bo)
1272 {
1273         _tbm_bufmgr_mutex_lock();
1274         _tbm_set_last_result(TBM_ERROR_NONE);
1275
1276         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1277
1278         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
1279                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1280                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1281                 _tbm_bufmgr_mutex_unlock();
1282                 return 0;
1283         }
1284
1285         if (bo->lock_cnt > 0) {
1286                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1287                 _tbm_bufmgr_mutex_unlock();
1288                 return 1;
1289         }
1290
1291         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1292         _tbm_bufmgr_mutex_unlock();
1293
1294         return 0;
1295 }
1296
1297 int
1298 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1299 {
1300         tbm_error_e error1, error2;
1301         int size1 = -1, size2 = -2;
1302         void *temp;
1303
1304         _tbm_bufmgr_mutex_lock();
1305         _tbm_set_last_result(TBM_ERROR_NONE);
1306
1307         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1308         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1309
1310         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1311
1312         if (bo1->bufmgr->use_hal_tbm) {
1313                 size1 = hal_tbm_bo_get_size((hal_tbm_bo *)bo1->bo_data, (hal_tbm_error *)&error1);
1314                 if (error1 != TBM_ERROR_NONE) {
1315                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1316                         _tbm_set_last_result(error1);
1317                         goto fail;
1318                 }
1319                 size2 = hal_tbm_bo_get_size((hal_tbm_bo *)bo2->bo_data, (hal_tbm_error *)&error2);
1320                 if (error2 != TBM_ERROR_NONE) {
1321                         TBM_ERR("fail to get the size of bo1.(%d)", error2);
1322                         _tbm_set_last_result(error2);
1323                         goto fail;
1324                 }
1325         } else if (bo1->bufmgr->backend_module_data) {
1326                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
1327                 if (error1 != TBM_ERROR_NONE) {
1328                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1329                         _tbm_set_last_result(error1);
1330                         goto fail;
1331                 }
1332                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
1333                 if (error2 != TBM_ERROR_NONE) {
1334                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
1335                         _tbm_set_last_result(error2);
1336                         goto fail;
1337                 }
1338         } else {
1339                 size1 = bo1->bufmgr->backend->bo_size(bo1);
1340                 size2 = bo2->bufmgr->backend->bo_size(bo2);
1341         }
1342
1343         if (size1 != size2) {
1344                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
1345                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1346                 goto fail;
1347         }
1348
1349         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1350
1351         temp = bo1->priv;
1352         bo1->priv = bo2->priv;
1353         bo2->priv = temp;
1354
1355         _tbm_bufmgr_mutex_unlock();
1356
1357         return 1;
1358
1359 fail:
1360         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1361         _tbm_bufmgr_mutex_unlock();
1362
1363         return 0;
1364 }
1365
1366 int
1367 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1368                      tbm_data_free data_free_func)
1369 {
1370         tbm_user_data *data;
1371
1372         _tbm_bufmgr_mutex_lock();
1373         _tbm_set_last_result(TBM_ERROR_NONE);
1374
1375         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1376
1377         /* check if the data according to the key exist if so, return false. */
1378         data = user_data_lookup(&bo->user_data_list, key);
1379         if (data) {
1380                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1381                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1382                 _tbm_bufmgr_mutex_unlock();
1383                 return 0;
1384         }
1385
1386         data = user_data_create(key, data_free_func);
1387         if (!data) {
1388                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1389                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1390                 _tbm_bufmgr_mutex_unlock();
1391                 return 0;
1392         }
1393
1394         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1395
1396         LIST_ADD(&data->item_link, &bo->user_data_list);
1397
1398         _tbm_bufmgr_mutex_unlock();
1399
1400         return 1;
1401 }
1402
1403 int
1404 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1405 {
1406         tbm_user_data *old_data;
1407
1408         _tbm_bufmgr_mutex_lock();
1409         _tbm_set_last_result(TBM_ERROR_NONE);
1410
1411         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1412
1413         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1414                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1415                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1416                 _tbm_bufmgr_mutex_unlock();
1417                 return 0;
1418         }
1419
1420         old_data = user_data_lookup(&bo->user_data_list, key);
1421         if (!old_data) {
1422                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1423                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1424                 _tbm_bufmgr_mutex_unlock();
1425                 return 0;
1426         }
1427
1428         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1429
1430         user_data_delete(old_data);
1431
1432         _tbm_bufmgr_mutex_unlock();
1433
1434         return 1;
1435 }
1436
1437 int
1438 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1439 {
1440         tbm_user_data *old_data;
1441
1442         _tbm_bufmgr_mutex_lock();
1443         _tbm_set_last_result(TBM_ERROR_NONE);
1444
1445         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1446
1447         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1448                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1449                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1450                 _tbm_bufmgr_mutex_unlock();
1451                 return 0;
1452         }
1453
1454         old_data = user_data_lookup(&bo->user_data_list, key);
1455         if (!old_data) {
1456                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1457                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1458                 _tbm_bufmgr_mutex_unlock();
1459                 return 0;
1460         }
1461
1462         if (old_data->data && old_data->free_func)
1463                 old_data->free_func(old_data->data);
1464         old_data->data = data;
1465
1466         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1467
1468         _tbm_bufmgr_mutex_unlock();
1469
1470         return 1;
1471 }
1472
1473 int
1474 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1475 {
1476         tbm_user_data *old_data;
1477
1478         _tbm_bufmgr_mutex_lock();
1479         _tbm_set_last_result(TBM_ERROR_NONE);
1480
1481         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1482
1483         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1484                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1485                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1486                 _tbm_bufmgr_mutex_unlock();
1487                 return 0;
1488         }
1489
1490         old_data = user_data_lookup(&bo->user_data_list, key);
1491         if (!old_data) {
1492                 *data = NULL;
1493                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1494                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1495                 _tbm_bufmgr_mutex_unlock();
1496                 return 0;
1497         }
1498
1499         *data = old_data->data;
1500
1501         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1502
1503         _tbm_bufmgr_mutex_unlock();
1504
1505         return 1;
1506 }
1507
1508 int
1509 tbm_bo_get_flags(tbm_bo bo)
1510 {
1511         int flags;
1512
1513         _tbm_bufmgr_mutex_lock();
1514
1515         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1516
1517         flags = bo->flags;
1518
1519         TBM_TRACE_BO("bo(%p)\n", bo);
1520
1521         _tbm_bufmgr_mutex_unlock();
1522
1523         return flags;
1524 }
1525
1526 /* LCOV_EXCL_START */
1527 /* internal function */
1528 int
1529 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1530 {
1531         _tbm_bufmgr_mutex_lock();
1532
1533         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1534
1535         bo->surface = surface;
1536
1537         _tbm_bufmgr_mutex_unlock();
1538
1539         return 1;
1540 }
1541
1542 void
1543 _tbm_bo_free(tbm_bo bo)
1544 {
1545         /* destory the user_data_list */
1546         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1547                 tbm_user_data *old_data = NULL, *tmp;
1548
1549                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1550                                 &bo->user_data_list, item_link) {
1551                         TBM_DBG("free user_data\n");
1552                         user_data_delete(old_data);
1553                 }
1554         }
1555
1556         while (bo->lock_cnt > 0) {
1557                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1558                 _bo_unlock(bo);
1559                 bo->lock_cnt--;
1560         }
1561
1562         /* call the bo_free */
1563         if (bo->bufmgr->use_hal_tbm) {
1564                 hal_tbm_bo_free(bo->bo_data);
1565                 bo->bo_data = NULL;
1566         } else if (bo->bufmgr->backend_module_data) {
1567                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1568                 bo->bo_data = NULL;
1569         } else {
1570                 bo->bufmgr->backend->bo_free(bo);
1571                 bo->priv = NULL;
1572         }
1573
1574         _tbm_bo_deinit(bo);
1575
1576         free(bo);
1577 }
1578 /* LCOV_EXCL_STOP */