tbm_bufmgr: add tbm_bufmgr_internal_import_bo_with_key and use it
[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 /* check condition */
38 #define TBM_BO_RETURN_IF_FAIL(cond) {\
39         if (!(cond)) {\
40                 TBM_ERR("'%s' failed.\n", #cond);\
41                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
42                 _tbm_bufmgr_mutex_unlock();\
43                 return;\
44         } \
45 }
46
47 #define TBM_BO_RETURN_VAL_IF_FAIL(cond, val) {\
48         if (!(cond)) {\
49                 TBM_ERR("'%s' failed.\n", #cond);\
50                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
51                 _tbm_bufmgr_mutex_unlock();\
52                 return val;\
53         } \
54 }
55
56 char *
57 _tbm_flag_to_str(int f)
58 {
59         static char str[255];
60
61         if (f == TBM_BO_DEFAULT)
62                  snprintf(str, 255, "DEFAULT");
63         else {
64                 int c = 0;
65
66                 if (f & TBM_BO_SCANOUT)
67                         c += snprintf(&str[c], 255-c, "SCANOUT");
68
69                 if (f & TBM_BO_NONCACHABLE) {
70                         if (c >= 0 && c < 255)
71                                 c += snprintf(&str[c], 255-c, ", ");
72
73                         if (c >= 0 && c < 255)
74                                 c += snprintf(&str[c], 255-c, "NONCACHABLE,");
75                 }
76
77                 if (f & TBM_BO_WC) {
78                         if (c >= 0 && c < 255)
79                                 c += snprintf(&str[c], 255-c, ", ");
80
81                         if (c >= 0 && c < 255)
82                                 c += snprintf(&str[c], 255-c, "WC");
83                 }
84         }
85
86         return str;
87 }
88
89 static void
90 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
91 {
92         static int last_chk_bo_cnt = 0;
93
94         if ((bufmgr->bo_cnt >= 500) && ((bufmgr->bo_cnt % 20) == 0) &&
95                 (bufmgr->bo_cnt > last_chk_bo_cnt)) {
96                 TBM_DBG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
97                 tbm_bufmgr_debug_show(bufmgr);
98                 last_chk_bo_cnt = bufmgr->bo_cnt;
99         }
100 }
101 /* LCOV_EXCL_STOP */
102
103 tbm_user_data *
104 user_data_lookup(struct list_head *user_data_list, unsigned long key)
105 {
106         tbm_user_data *old_data = NULL;
107
108         if (LIST_IS_EMPTY(user_data_list))
109                 return NULL;
110
111         LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
112                 if (old_data->key == key)
113                         return old_data;
114         }
115
116         return NULL;
117 }
118
119 tbm_user_data *
120 user_data_create(unsigned long key, tbm_data_free data_free_func)
121 {
122         tbm_user_data *user_data;
123
124         user_data = calloc(1, sizeof(tbm_user_data));
125         if (!user_data) {
126                 /* LCOV_EXCL_START */
127                 TBM_ERR("fail to allocate an user_date\n");
128                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
129                 return NULL;
130                 /* LCOV_EXCL_STOP */
131         }
132
133         user_data->key = key;
134         user_data->free_func = data_free_func;
135
136         return user_data;
137 }
138
139 void
140 user_data_delete(tbm_user_data *user_data)
141 {
142         if (user_data->data && user_data->free_func)
143                 user_data->free_func(user_data->data);
144
145         LIST_DEL(&user_data->item_link);
146
147         free(user_data);
148 }
149
150 static int
151 _bo_lock(tbm_bo bo, int device, int opt)
152 {
153         int ret = 1;
154         tbm_error_e error;
155
156         if (bo->bufmgr->use_hal_tbm) {
157                 error = (tbm_error_e)hal_tbm_bo_lock((hal_tbm_bo *)bo->bo_data, device, opt);
158                 if (error == TBM_ERROR_NOT_SUPPORTED) {
159                         _tbm_set_last_result(TBM_ERROR_NONE);
160                 } else {
161                         if (error != TBM_ERROR_NONE) {
162                                 TBM_WRN("fail to lock");
163                                 _tbm_set_last_result(error);
164                                 ret = 0;
165                         }
166                 }
167         } else if (bo->bufmgr->backend_module_data) {
168                 if (bo->bufmgr->bo_func->bo_lock) {
169                         error = bo->bufmgr->bo_func->bo_lock(bo->bo_data, device, opt);
170                         if (error != TBM_ERROR_NONE) {
171                                 TBM_WRN("fail to lock");
172                                 _tbm_set_last_result(error);
173                                 ret = 0;
174                         }
175                 }
176         } else {
177                 if (bo->bufmgr->backend->bo_lock) {
178                         ret = bo->bufmgr->backend->bo_lock(bo, device, opt);
179                         if (!ret)
180                                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
181                 }
182         }
183
184         return ret;
185 }
186
187 static void
188 _bo_unlock(tbm_bo bo)
189 {
190         tbm_error_e error;
191
192         if (bo->bufmgr->use_hal_tbm) {
193                 error = (tbm_error_e)hal_tbm_bo_unlock((hal_tbm_bo *)bo->bo_data);
194                 if (error == TBM_ERROR_NOT_SUPPORTED) {
195                         _tbm_set_last_result(TBM_ERROR_NONE);
196                 } else {
197                         if (error != TBM_ERROR_NONE) {
198                                 TBM_WRN("fail to lock");
199                                 _tbm_set_last_result(error);
200                         }
201                 }
202         } else if (bo->bufmgr->backend_module_data) {
203                 if (bo->bufmgr->bo_func->bo_unlock) {
204                         error = bo->bufmgr->bo_func->bo_unlock(bo->bo_data);
205                         if (error != TBM_ERROR_NONE) {
206                                 TBM_WRN("fail to unlock");
207                                 _tbm_set_last_result(error);
208                         }
209                 }
210         } else {
211                 if (bo->bufmgr->backend->bo_unlock)
212                         bo->bufmgr->backend->bo_unlock(bo);
213         }
214 }
215
216 static int
217 _tbm_bo_lock(tbm_bo bo, int device, int opt)
218 {
219         int old, ret;
220
221         if (!bo)
222                 return 0;
223
224         /* do not try to lock the bo */
225         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
226                 return 1;
227
228         if (bo->lock_cnt < 0) {
229                 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
230                         bo, bo->lock_cnt);
231                 return 0;
232         }
233
234         old = bo->lock_cnt;
235
236         switch (bo->bufmgr->bo_lock_type) {
237         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
238                 if (bo->lock_cnt == 0) {
239                         _tbm_bufmgr_mutex_unlock();
240                         ret = _bo_lock(bo, device, opt);
241                         _tbm_bufmgr_mutex_lock();
242                         if (ret)
243                                 bo->lock_cnt++;
244                 } else
245                         ret = 1;
246                 break;
247         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
248                 _tbm_bufmgr_mutex_unlock();
249                 ret = _bo_lock(bo, device, opt);
250                 _tbm_bufmgr_mutex_lock();
251                 if (ret)
252                         bo->lock_cnt++;
253                 break;
254         default:
255                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
256                                 bo, bo->bufmgr->bo_lock_type);
257                 ret = 0;
258                 break;
259         }
260
261         TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
262
263         return ret;
264 }
265
266 static void
267 _tbm_bo_unlock(tbm_bo bo)
268 {
269         int old;
270
271         /* do not try to unlock the bo */
272         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
273                 return;
274
275         old = bo->lock_cnt;
276
277         switch (bo->bufmgr->bo_lock_type) {
278         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
279                 if (bo->lock_cnt > 0) {
280                         bo->lock_cnt--;
281                         if (bo->lock_cnt == 0)
282                                 _bo_unlock(bo);
283                 }
284                 break;
285         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
286                 if (bo->lock_cnt > 0) {
287                         bo->lock_cnt--;
288                         _bo_unlock(bo);
289                 }
290                 break;
291         default:
292                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
293                                 bo, bo->bufmgr->bo_lock_type);
294                 break;
295         }
296
297         if (bo->lock_cnt < 0)
298                 bo->lock_cnt = 0;
299
300         TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
301 }
302
303 static int
304 _tbm_bo_magic_check(tbm_bo bo)
305 {
306         if (bo->magic != TBM_BO_MAGIC)
307                 return 0;
308
309         return 1;
310 }
311
312 static int
313 _tbm_bo_is_valid(tbm_bo bo)
314 {
315         if (!bo) {
316                 TBM_ERR("error: bo is NULL.\n");
317                 return 0;
318         }
319
320         if (!_tbm_bo_magic_check(bo)) {
321                 TBM_ERR("error: No valid bo(%p).\n", bo);
322                 return 0;
323         }
324
325         return 1;
326 }
327
328 static void
329 _tbm_bo_init(tbm_bufmgr bufmgr, tbm_bo bo, int flags)
330 {
331         bo->bufmgr = bufmgr;
332         bo->flags = flags;
333         bo->magic = TBM_BO_MAGIC;
334         bo->ref_cnt = 1;
335
336         LIST_INITHEAD(&bo->user_data_list);
337
338         bufmgr->bo_cnt++;
339         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
340 }
341
342 static void
343 _tbm_bo_deinit(tbm_bo bo)
344 {
345         bo->magic = 0;
346
347         bo->bufmgr->bo_cnt--;
348         LIST_DEL(&bo->item_link);
349 }
350
351 tbm_bo
352 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
353 {
354         tbm_bo bo;
355         tbm_error_e error;
356
357         _tbm_bufmgr_mutex_lock();
358         _tbm_set_last_result(TBM_ERROR_NONE);
359
360         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
361         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
362
363         bo = tbm_bufmgr_internal_alloc_bo(bufmgr, size, flags, &error);
364         if (!bo) {
365                 /* LCOV_EXCL_START */
366                 TBM_ERR("tbm_bufmgr_internal_alloc_bo failed. error:%d", error);
367                 _tbm_set_last_result(error);
368                 _tbm_bufmgr_mutex_unlock();
369                 return NULL;
370                 /* LCOV_EXCL_STOP */
371         }
372
373         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
374                         _tbm_flag_to_str(bo->flags));
375
376         _tbm_bufmgr_mutex_unlock();
377
378         return bo;
379 }
380
381 tbm_bo
382 tbm_bo_ref(tbm_bo bo)
383 {
384         _tbm_bufmgr_mutex_lock();
385         _tbm_set_last_result(TBM_ERROR_NONE);
386
387         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
388
389         bo->ref_cnt++;
390
391         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
392
393         _tbm_bufmgr_mutex_unlock();
394
395         return bo;
396 }
397
398 void
399 tbm_bo_unref(tbm_bo bo)
400 {
401         _tbm_bufmgr_mutex_lock();
402         _tbm_set_last_result(TBM_ERROR_NONE);
403
404         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
405
406         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
407
408         if (bo->ref_cnt <= 0) {
409                 _tbm_bufmgr_mutex_unlock();
410                 return;
411         }
412
413         bo->ref_cnt--;
414         if (bo->ref_cnt == 0)
415                 _tbm_bo_free(bo);
416
417         _tbm_bufmgr_mutex_unlock();
418 }
419
420 tbm_bo_handle
421 tbm_bo_map(tbm_bo bo, int device, int opt)
422 {
423         tbm_bo_handle bo_handle;
424         tbm_error_e error;
425
426         _tbm_bufmgr_mutex_lock();
427         _tbm_set_last_result(TBM_ERROR_NONE);
428
429         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
430
431         if (!_tbm_bo_lock(bo, device, opt)) {
432                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
433                 _tbm_bufmgr_mutex_unlock();
434                 return (tbm_bo_handle) NULL;
435         }
436
437         if (bo->bufmgr->use_hal_tbm) {
438                 hal_tbm_bo_handle hbo_handle;
439                 hbo_handle = hal_tbm_bo_map((hal_tbm_bo *)bo->bo_data, device, opt, (hal_tbm_error *)&error);
440                 if (hbo_handle.ptr == NULL) {
441                         /* LCOV_EXCL_START */
442                         _tbm_set_last_result(error);
443                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
444                         goto bo_map_fail;
445                         /* LCOV_EXCL_STOP */
446                 }
447                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
448         } else if (bo->bufmgr->backend_module_data) {
449                 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
450                 if (bo_handle.ptr == NULL) {
451                         /* LCOV_EXCL_START */
452                         _tbm_set_last_result(error);
453                         TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
454                         goto bo_map_fail;
455                         /* LCOV_EXCL_STOP */
456                 }
457         } else {
458                 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
459                 if (bo_handle.ptr == NULL) {
460                         /* LCOV_EXCL_START */
461                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
462                         TBM_ERR("error: fail to map bo:%p\n", bo);
463                         goto bo_map_fail;
464                         /* LCOV_EXCL_STOP */
465                 }
466         }
467
468         /* increase the map_count */
469         bo->map_cnt++;
470
471         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
472
473         _tbm_bufmgr_mutex_unlock();
474
475         return bo_handle;
476
477 bo_map_fail:
478         _tbm_bo_unlock(bo);
479         _tbm_bufmgr_mutex_unlock();
480         return (tbm_bo_handle) NULL;
481 }
482
483 int
484 tbm_bo_unmap(tbm_bo bo)
485 {
486         int ret = 1;
487         tbm_error_e error;
488
489         _tbm_bufmgr_mutex_lock();
490         _tbm_set_last_result(TBM_ERROR_NONE);
491
492         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
493         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
494
495         if (bo->bufmgr->use_hal_tbm) {
496                 error = (hal_tbm_error)hal_tbm_bo_unmap((hal_tbm_bo *)bo->bo_data);
497                 if (error != TBM_ERROR_NONE) {
498                         /* LCOV_EXCL_START */
499                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
500                         _tbm_set_last_result(error);
501                         ret = 0;
502                         goto done;
503                         /* LCOV_EXCL_STOP */
504                 }
505         } else if (bo->bufmgr->backend_module_data) {
506                 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
507                 if (error != TBM_ERROR_NONE) {
508                         /* LCOV_EXCL_START */
509                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
510                         _tbm_set_last_result(error);
511                         ret = 0;
512                         goto done;
513                         /* LCOV_EXCL_STOP */
514                 }
515         } else {
516                 ret = bo->bufmgr->backend->bo_unmap(bo);
517                 if (!ret) {
518                         /* LCOV_EXCL_START */
519                         TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
520                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
521                         goto done;
522                         /* LCOV_EXCL_STOP */
523                 }
524         }
525
526         /* decrease the map_count */
527         bo->map_cnt--;
528
529         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
530
531         _tbm_bo_unlock(bo);
532
533 done:
534         _tbm_bufmgr_mutex_unlock();
535
536         return ret;
537 }
538
539 tbm_bo_handle
540 tbm_bo_get_handle(tbm_bo bo, int device)
541 {
542         tbm_bo_handle bo_handle;
543         tbm_error_e error;
544
545         _tbm_bufmgr_mutex_lock();
546         _tbm_set_last_result(TBM_ERROR_NONE);
547
548         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
549
550         if (bo->bufmgr->use_hal_tbm) {
551                 hal_tbm_bo_handle hbo_handle;
552                 hbo_handle = hal_tbm_bo_get_handle((hal_tbm_bo *)bo->bo_data, device, (hal_tbm_error *)&error);
553                 if (hbo_handle.ptr == NULL) {
554                         /* LCOV_EXCL_START */
555                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
556                         _tbm_set_last_result(error);
557                         goto bo_handle_fail;
558                         /* LCOV_EXCL_STOP */
559                 }
560                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
561         } else if (bo->bufmgr->backend_module_data) {
562                 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
563                 if (bo_handle.ptr == NULL) {
564                         /* LCOV_EXCL_START */
565                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
566                         _tbm_set_last_result(error);
567                         goto bo_handle_fail;
568                         /* LCOV_EXCL_STOP */
569                 }
570         } else {
571                 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
572                 if (bo_handle.ptr == NULL) {
573                         /* LCOV_EXCL_START */
574                         TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
575                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
576                         goto bo_handle_fail;
577                         /* LCOV_EXCL_STOP */
578                 }
579         }
580
581         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
582
583         _tbm_bufmgr_mutex_unlock();
584
585         return bo_handle;
586
587 bo_handle_fail:
588         _tbm_bufmgr_mutex_unlock();
589         return (tbm_bo_handle) NULL;
590 }
591
592 tbm_key
593 tbm_bo_export(tbm_bo bo)
594 {
595         tbm_key ret;
596         tbm_error_e error;
597
598         _tbm_bufmgr_mutex_lock();
599         _tbm_set_last_result(TBM_ERROR_NONE);
600
601         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
602
603         if (bo->bufmgr->use_hal_tbm) {
604                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
605                 if (!ret) {
606                         /* LCOV_EXCL_START */
607                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
608                         _tbm_set_last_result(error);
609                         goto done;
610                         /* LCOV_EXCL_STOP */
611                 }
612         } else if (bo->bufmgr->backend_module_data) {
613                 if (!bo->bufmgr->bo_func->bo_export_key) {
614                         /* LCOV_EXCL_START */
615                         _tbm_bufmgr_mutex_unlock();
616                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
617                         return 0;
618                         /* LCOV_EXCL_STOP */
619                 }
620
621                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
622                 if (!ret) {
623                         /* LCOV_EXCL_START */
624                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
625                         _tbm_set_last_result(error);
626                         goto done;
627                         /* LCOV_EXCL_STOP */
628                 }
629         } else {
630                 if (!bo->bufmgr->backend->bo_export) {
631                         /* LCOV_EXCL_START */
632                         _tbm_bufmgr_mutex_unlock();
633                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
634                         return 0;
635                         /* LCOV_EXCL_STOP */
636                 }
637
638                 ret = bo->bufmgr->backend->bo_export(bo);
639                 if (!ret) {
640                         /* LCOV_EXCL_START */
641                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
642                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
643                         goto done;
644                         /* LCOV_EXCL_STOP */
645                 }
646         }
647
648         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
649
650 done:
651         _tbm_bufmgr_mutex_unlock();
652
653         return ret;
654 }
655
656 tbm_fd
657 tbm_bo_export_fd(tbm_bo bo)
658 {
659         tbm_fd ret;
660         tbm_error_e error;
661
662         _tbm_bufmgr_mutex_lock();
663         _tbm_set_last_result(TBM_ERROR_NONE);
664
665         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
666
667         if (bo->bufmgr->use_hal_tbm) {
668                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
669                 if (ret < 0) {
670                         /* LCOV_EXCL_START */
671                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
672                         _tbm_set_last_result(error);
673                         goto done;
674                         /* LCOV_EXCL_STOP */
675                 }
676         } else if (bo->bufmgr->backend_module_data) {
677                 if (!bo->bufmgr->bo_func->bo_export_fd) {
678                         /* LCOV_EXCL_START */
679                         _tbm_bufmgr_mutex_unlock();
680                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
681                         return -1;
682                         /* LCOV_EXCL_STOP */
683                 }
684
685                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
686                 if (ret < 0) {
687                         /* LCOV_EXCL_START */
688                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
689                         _tbm_set_last_result(error);
690                         goto done;
691                         /* LCOV_EXCL_STOP */
692                 }
693         } else {
694                 if (!bo->bufmgr->backend->bo_export_fd) {
695                         /* LCOV_EXCL_START */
696                         _tbm_bufmgr_mutex_unlock();
697                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
698                         return -1;
699                         /* LCOV_EXCL_STOP */
700                 }
701
702                 ret = bo->bufmgr->backend->bo_export_fd(bo);
703                 if (ret < 0) {
704                         /* LCOV_EXCL_START */
705                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
706                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
707                         goto done;
708                         /* LCOV_EXCL_STOP */
709                 }
710         }
711
712         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
713
714 done:
715         _tbm_bufmgr_mutex_unlock();
716
717         return ret;
718 }
719
720 tbm_bo
721 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
722 {
723         tbm_bo bo;
724         tbm_error_e error;
725
726         _tbm_bufmgr_mutex_lock();
727         _tbm_set_last_result(TBM_ERROR_NONE);
728
729         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
730
731         bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key, &error);
732         if (!bo) {
733                 /* LCOV_EXCL_START */
734                 TBM_ERR("tbm_bufmgr_internal_import_key failed. error:%d", error);
735                 _tbm_set_last_result(error);
736                 _tbm_bufmgr_mutex_unlock();
737                 return NULL;
738                 /* LCOV_EXCL_STOP */
739         }
740
741         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
742                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
743
744         _tbm_bufmgr_mutex_unlock();
745
746         return bo;
747 }
748
749 tbm_bo
750 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
751 {
752         tbm_bo bo, bo2 = NULL;
753         tbm_error_e error;
754         int flags;
755
756         _tbm_bufmgr_mutex_lock();
757         _tbm_set_last_result(TBM_ERROR_NONE);
758
759         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
760
761         _tbm_util_check_bo_cnt(bufmgr);
762
763         bo = calloc(1, sizeof(struct _tbm_bo));
764         if (!bo) {
765                 /* LCOV_EXCL_START */
766                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
767                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
768                 _tbm_bufmgr_mutex_unlock();
769                 return NULL;
770                 /* LCOV_EXCL_STOP */
771         }
772
773         bo->bo_data = tbm_module_bufmgr_bo_import_fd(bufmgr->module, bo, fd, &error);
774         if (!bo->bo_data) {
775                 /* LCOV_EXCL_START */
776                 TBM_ERR("tbm_module_bufmgr_bo_import_fd failed. tbm_fd:%d", fd);
777                 _tbm_set_last_result(error);
778                 _tbm_bufmgr_mutex_unlock();
779                 return NULL;
780                 /* LCOV_EXCL_STOP */
781         }
782
783         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
784         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
785         if (bo2) {
786                 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list",
787                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
788                 bo2->ref_cnt++;
789                 free(bo);
790                 _tbm_bufmgr_mutex_unlock();
791                 return bo2;
792         }
793
794         if (bufmgr->use_hal_tbm) {
795                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
796                 if (error != TBM_ERROR_NONE) {
797                         TBM_ERR("fail to get the bo flags(memory_types)");
798                         _tbm_set_last_result(error);
799                         flags = TBM_BO_DEFAULT;
800                 }
801         } else if (bufmgr->backend_module_data) {
802                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
803                 if (error != TBM_ERROR_NONE) {
804                         TBM_ERR("fail to get the bo flags(memory_types)");
805                         _tbm_set_last_result(error);
806                         flags = TBM_BO_DEFAULT;
807                 }
808         } else {
809                 if (bufmgr->backend->bo_get_flags)
810                         flags = bufmgr->backend->bo_get_flags(bo);
811                 else
812                         flags = TBM_BO_DEFAULT;
813         }
814
815         _tbm_bo_init(bufmgr, bo, flags);
816
817         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
818                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
819
820         _tbm_bufmgr_mutex_unlock();
821
822         return bo;
823 }
824
825 int
826 tbm_bo_size(tbm_bo bo)
827 {
828         int size;
829         tbm_error_e error;
830
831         _tbm_bufmgr_mutex_lock();
832         _tbm_set_last_result(TBM_ERROR_NONE);
833
834         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
835
836         if (bo->bufmgr->use_hal_tbm) {
837                 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
838                 if (error != TBM_ERROR_NONE) {
839                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
840                         _tbm_set_last_result(TBM_ERROR_NONE);
841                 }
842         } else if (bo->bufmgr->backend_module_data) {
843                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
844                 if (error != TBM_ERROR_NONE) {
845                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
846                         _tbm_set_last_result(TBM_ERROR_NONE);
847                 }
848         } else
849                 size = bo->bufmgr->backend->bo_size(bo);
850
851         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
852
853         _tbm_bufmgr_mutex_unlock();
854
855         return size;
856 }
857
858 int
859 tbm_bo_locked(tbm_bo bo)
860 {
861         _tbm_bufmgr_mutex_lock();
862         _tbm_set_last_result(TBM_ERROR_NONE);
863
864         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
865
866         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
867                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
868                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
869                 _tbm_bufmgr_mutex_unlock();
870                 return 0;
871         }
872
873         if (bo->lock_cnt > 0) {
874                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
875                 _tbm_bufmgr_mutex_unlock();
876                 return 1;
877         }
878
879         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
880         _tbm_bufmgr_mutex_unlock();
881
882         return 0;
883 }
884
885 int
886 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
887 {
888         tbm_error_e error1, error2;
889         int size1 = -1, size2 = -2;
890         void *temp;
891
892         _tbm_bufmgr_mutex_lock();
893         _tbm_set_last_result(TBM_ERROR_NONE);
894
895         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
896         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
897
898         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
899
900         if (bo1->bufmgr->use_hal_tbm) {
901                 size1 = hal_tbm_bo_get_size((hal_tbm_bo *)bo1->bo_data, (hal_tbm_error *)&error1);
902                 if (error1 != TBM_ERROR_NONE) {
903                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
904                         _tbm_set_last_result(error1);
905                         goto fail;
906                 }
907                 size2 = hal_tbm_bo_get_size((hal_tbm_bo *)bo2->bo_data, (hal_tbm_error *)&error2);
908                 if (error2 != TBM_ERROR_NONE) {
909                         TBM_ERR("fail to get the size of bo1.(%d)", error2);
910                         _tbm_set_last_result(error2);
911                         goto fail;
912                 }
913         } else if (bo1->bufmgr->backend_module_data) {
914                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
915                 if (error1 != TBM_ERROR_NONE) {
916                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
917                         _tbm_set_last_result(error1);
918                         goto fail;
919                 }
920                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
921                 if (error2 != TBM_ERROR_NONE) {
922                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
923                         _tbm_set_last_result(error2);
924                         goto fail;
925                 }
926         } else {
927                 size1 = bo1->bufmgr->backend->bo_size(bo1);
928                 size2 = bo2->bufmgr->backend->bo_size(bo2);
929         }
930
931         if (size1 != size2) {
932                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
933                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
934                 goto fail;
935         }
936
937         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
938
939         temp = bo1->priv;
940         bo1->priv = bo2->priv;
941         bo2->priv = temp;
942
943         _tbm_bufmgr_mutex_unlock();
944
945         return 1;
946
947 fail:
948         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
949         _tbm_bufmgr_mutex_unlock();
950
951         return 0;
952 }
953
954 int
955 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
956                      tbm_data_free data_free_func)
957 {
958         tbm_user_data *data;
959
960         _tbm_bufmgr_mutex_lock();
961         _tbm_set_last_result(TBM_ERROR_NONE);
962
963         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
964
965         /* check if the data according to the key exist if so, return false. */
966         data = user_data_lookup(&bo->user_data_list, key);
967         if (data) {
968                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
969                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
970                 _tbm_bufmgr_mutex_unlock();
971                 return 0;
972         }
973
974         data = user_data_create(key, data_free_func);
975         if (!data) {
976                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
977                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
978                 _tbm_bufmgr_mutex_unlock();
979                 return 0;
980         }
981
982         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
983
984         LIST_ADD(&data->item_link, &bo->user_data_list);
985
986         _tbm_bufmgr_mutex_unlock();
987
988         return 1;
989 }
990
991 int
992 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
993 {
994         tbm_user_data *old_data;
995
996         _tbm_bufmgr_mutex_lock();
997         _tbm_set_last_result(TBM_ERROR_NONE);
998
999         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1000
1001         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1002                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1003                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1004                 _tbm_bufmgr_mutex_unlock();
1005                 return 0;
1006         }
1007
1008         old_data = user_data_lookup(&bo->user_data_list, key);
1009         if (!old_data) {
1010                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1011                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1012                 _tbm_bufmgr_mutex_unlock();
1013                 return 0;
1014         }
1015
1016         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1017
1018         user_data_delete(old_data);
1019
1020         _tbm_bufmgr_mutex_unlock();
1021
1022         return 1;
1023 }
1024
1025 int
1026 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1027 {
1028         tbm_user_data *old_data;
1029
1030         _tbm_bufmgr_mutex_lock();
1031         _tbm_set_last_result(TBM_ERROR_NONE);
1032
1033         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1034
1035         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1036                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1037                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1038                 _tbm_bufmgr_mutex_unlock();
1039                 return 0;
1040         }
1041
1042         old_data = user_data_lookup(&bo->user_data_list, key);
1043         if (!old_data) {
1044                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1045                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1046                 _tbm_bufmgr_mutex_unlock();
1047                 return 0;
1048         }
1049
1050         if (old_data->data && old_data->free_func)
1051                 old_data->free_func(old_data->data);
1052         old_data->data = data;
1053
1054         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1055
1056         _tbm_bufmgr_mutex_unlock();
1057
1058         return 1;
1059 }
1060
1061 int
1062 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1063 {
1064         tbm_user_data *old_data;
1065
1066         _tbm_bufmgr_mutex_lock();
1067         _tbm_set_last_result(TBM_ERROR_NONE);
1068
1069         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1070
1071         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1072                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1073                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1074                 _tbm_bufmgr_mutex_unlock();
1075                 return 0;
1076         }
1077
1078         old_data = user_data_lookup(&bo->user_data_list, key);
1079         if (!old_data) {
1080                 *data = NULL;
1081                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1082                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1083                 _tbm_bufmgr_mutex_unlock();
1084                 return 0;
1085         }
1086
1087         *data = old_data->data;
1088
1089         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1090
1091         _tbm_bufmgr_mutex_unlock();
1092
1093         return 1;
1094 }
1095
1096 int
1097 tbm_bo_get_flags(tbm_bo bo)
1098 {
1099         int flags;
1100
1101         _tbm_bufmgr_mutex_lock();
1102
1103         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1104
1105         flags = bo->flags;
1106
1107         TBM_TRACE_BO("bo(%p)\n", bo);
1108
1109         _tbm_bufmgr_mutex_unlock();
1110
1111         return flags;
1112 }
1113
1114 /* LCOV_EXCL_START */
1115 /* internal function */
1116 int
1117 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1118 {
1119         _tbm_bufmgr_mutex_lock();
1120
1121         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1122
1123         bo->surface = surface;
1124
1125         _tbm_bufmgr_mutex_unlock();
1126
1127         return 1;
1128 }
1129
1130 void
1131 _tbm_bo_free(tbm_bo bo)
1132 {
1133         /* destory the user_data_list */
1134         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1135                 tbm_user_data *old_data = NULL, *tmp;
1136
1137                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1138                                 &bo->user_data_list, item_link) {
1139                         TBM_DBG("free user_data\n");
1140                         user_data_delete(old_data);
1141                 }
1142         }
1143
1144         while (bo->lock_cnt > 0) {
1145                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1146                 _bo_unlock(bo);
1147                 bo->lock_cnt--;
1148         }
1149
1150         /* call the bo_free */
1151         if (bo->bufmgr->use_hal_tbm) {
1152                 // call hal_tbm_bo_free when bo is created by tbm_bo_alloc api.
1153                 if (!bo->get_from_hal_surface) {
1154                         bo->get_from_hal_surface = 0;
1155
1156                         hal_tbm_bo_free(bo->bo_data);
1157                         bo->bo_data = NULL;
1158                 }
1159         } else if (bo->bufmgr->backend_module_data) {
1160                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1161                 bo->bo_data = NULL;
1162         } else {
1163                 bo->bufmgr->backend->bo_free(bo);
1164                 bo->priv = NULL;
1165         }
1166
1167         _tbm_bo_deinit(bo);
1168
1169         free(bo);
1170 }
1171 /* LCOV_EXCL_STOP */