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