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