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