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