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