tbm_bufmgr: add tbm_bufmgr_internal_alloc_bo 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, bo2 = NULL;
724         tbm_error_e error;
725         int flags;
726
727         _tbm_bufmgr_mutex_lock();
728         _tbm_set_last_result(TBM_ERROR_NONE);
729
730         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
731
732         _tbm_util_check_bo_cnt(bufmgr);
733
734         bo = calloc(1, sizeof(struct _tbm_bo));
735         if (!bo) {
736                 /* LCOV_EXCL_START */
737                 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
738                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
739                 _tbm_bufmgr_mutex_unlock();
740                 return NULL;
741                 /* LCOV_EXCL_STOP */
742         }
743
744         bo->bo_data = tbm_module_bufmgr_bo_import_key(bufmgr->module, bo, key, &error);
745         if (!bo->bo_data) {
746                 /* LCOV_EXCL_START */
747                 TBM_ERR("tbm_module_bufmgr_bo_import_key failed. tbm_key:%d", key);
748                 _tbm_set_last_result(error);
749                 _tbm_bufmgr_mutex_unlock();
750                 return NULL;
751                 /* LCOV_EXCL_STOP */
752         }
753
754         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
755         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
756         if (bo2) {
757                 TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list",
758                                         bo2, bo2->ref_cnt, key, _tbm_flag_to_str(bo2->flags));
759                 bo2->ref_cnt++;
760                 free(bo);
761                 _tbm_bufmgr_mutex_unlock();
762                 return bo2;
763         }
764
765         if (bufmgr->use_hal_tbm) {
766                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
767                 if (error != TBM_ERROR_NONE) {
768                         TBM_ERR("fail to get the bo flags(memory_types)");
769                         _tbm_set_last_result(error);
770                         flags = TBM_BO_DEFAULT;
771                 }
772         } else if (bufmgr->backend_module_data) {
773                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
774                 if (error != TBM_ERROR_NONE) {
775                         TBM_ERR("fail to get the bo flags(memory_types)");
776                         _tbm_set_last_result(error);
777                         flags = TBM_BO_DEFAULT;
778                 }
779         } else {
780                 if (bufmgr->backend->bo_get_flags)
781                         flags = bufmgr->backend->bo_get_flags(bo);
782                 else
783                         flags = TBM_BO_DEFAULT;
784         }
785
786         _tbm_bo_init(bufmgr, bo, flags);
787
788         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
789                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
790
791         _tbm_bufmgr_mutex_unlock();
792
793         return bo;
794 }
795
796 tbm_bo
797 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
798 {
799         tbm_bo bo, bo2 = NULL;
800         tbm_error_e error;
801         int flags;
802
803         _tbm_bufmgr_mutex_lock();
804         _tbm_set_last_result(TBM_ERROR_NONE);
805
806         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
807
808         _tbm_util_check_bo_cnt(bufmgr);
809
810         bo = calloc(1, sizeof(struct _tbm_bo));
811         if (!bo) {
812                 /* LCOV_EXCL_START */
813                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
814                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
815                 _tbm_bufmgr_mutex_unlock();
816                 return NULL;
817                 /* LCOV_EXCL_STOP */
818         }
819
820         bo->bo_data = tbm_module_bufmgr_bo_import_fd(bufmgr->module, bo, fd, &error);
821         if (!bo->bo_data) {
822                 /* LCOV_EXCL_START */
823                 TBM_ERR("tbm_module_bufmgr_bo_import_fd failed. tbm_fd:%d", fd);
824                 _tbm_set_last_result(error);
825                 _tbm_bufmgr_mutex_unlock();
826                 return NULL;
827                 /* LCOV_EXCL_STOP */
828         }
829
830         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
831         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
832         if (bo2) {
833                 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list",
834                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
835                 bo2->ref_cnt++;
836                 free(bo);
837                 _tbm_bufmgr_mutex_unlock();
838                 return bo2;
839         }
840
841         if (bufmgr->use_hal_tbm) {
842                 flags = (tbm_bo_memory_type)hal_tbm_bo_get_memory_types((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
843                 if (error != TBM_ERROR_NONE) {
844                         TBM_ERR("fail to get the bo flags(memory_types)");
845                         _tbm_set_last_result(error);
846                         flags = TBM_BO_DEFAULT;
847                 }
848         } else if (bufmgr->backend_module_data) {
849                 flags = bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
850                 if (error != TBM_ERROR_NONE) {
851                         TBM_ERR("fail to get the bo flags(memory_types)");
852                         _tbm_set_last_result(error);
853                         flags = TBM_BO_DEFAULT;
854                 }
855         } else {
856                 if (bufmgr->backend->bo_get_flags)
857                         flags = bufmgr->backend->bo_get_flags(bo);
858                 else
859                         flags = TBM_BO_DEFAULT;
860         }
861
862         _tbm_bo_init(bufmgr, bo, flags);
863
864         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
865                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
866
867         _tbm_bufmgr_mutex_unlock();
868
869         return bo;
870 }
871
872 int
873 tbm_bo_size(tbm_bo bo)
874 {
875         int size;
876         tbm_error_e error;
877
878         _tbm_bufmgr_mutex_lock();
879         _tbm_set_last_result(TBM_ERROR_NONE);
880
881         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
882
883         if (bo->bufmgr->use_hal_tbm) {
884                 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
885                 if (error != TBM_ERROR_NONE) {
886                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
887                         _tbm_set_last_result(TBM_ERROR_NONE);
888                 }
889         } else if (bo->bufmgr->backend_module_data) {
890                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
891                 if (error != TBM_ERROR_NONE) {
892                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
893                         _tbm_set_last_result(TBM_ERROR_NONE);
894                 }
895         } else
896                 size = bo->bufmgr->backend->bo_size(bo);
897
898         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
899
900         _tbm_bufmgr_mutex_unlock();
901
902         return size;
903 }
904
905 int
906 tbm_bo_locked(tbm_bo bo)
907 {
908         _tbm_bufmgr_mutex_lock();
909         _tbm_set_last_result(TBM_ERROR_NONE);
910
911         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
912
913         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
914                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
915                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
916                 _tbm_bufmgr_mutex_unlock();
917                 return 0;
918         }
919
920         if (bo->lock_cnt > 0) {
921                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
922                 _tbm_bufmgr_mutex_unlock();
923                 return 1;
924         }
925
926         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
927         _tbm_bufmgr_mutex_unlock();
928
929         return 0;
930 }
931
932 int
933 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
934 {
935         tbm_error_e error1, error2;
936         int size1 = -1, size2 = -2;
937         void *temp;
938
939         _tbm_bufmgr_mutex_lock();
940         _tbm_set_last_result(TBM_ERROR_NONE);
941
942         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
943         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
944
945         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
946
947         if (bo1->bufmgr->use_hal_tbm) {
948                 size1 = hal_tbm_bo_get_size((hal_tbm_bo *)bo1->bo_data, (hal_tbm_error *)&error1);
949                 if (error1 != TBM_ERROR_NONE) {
950                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
951                         _tbm_set_last_result(error1);
952                         goto fail;
953                 }
954                 size2 = hal_tbm_bo_get_size((hal_tbm_bo *)bo2->bo_data, (hal_tbm_error *)&error2);
955                 if (error2 != TBM_ERROR_NONE) {
956                         TBM_ERR("fail to get the size of bo1.(%d)", error2);
957                         _tbm_set_last_result(error2);
958                         goto fail;
959                 }
960         } else if (bo1->bufmgr->backend_module_data) {
961                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
962                 if (error1 != TBM_ERROR_NONE) {
963                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
964                         _tbm_set_last_result(error1);
965                         goto fail;
966                 }
967                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
968                 if (error2 != TBM_ERROR_NONE) {
969                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
970                         _tbm_set_last_result(error2);
971                         goto fail;
972                 }
973         } else {
974                 size1 = bo1->bufmgr->backend->bo_size(bo1);
975                 size2 = bo2->bufmgr->backend->bo_size(bo2);
976         }
977
978         if (size1 != size2) {
979                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
980                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
981                 goto fail;
982         }
983
984         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
985
986         temp = bo1->priv;
987         bo1->priv = bo2->priv;
988         bo2->priv = temp;
989
990         _tbm_bufmgr_mutex_unlock();
991
992         return 1;
993
994 fail:
995         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
996         _tbm_bufmgr_mutex_unlock();
997
998         return 0;
999 }
1000
1001 int
1002 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1003                      tbm_data_free data_free_func)
1004 {
1005         tbm_user_data *data;
1006
1007         _tbm_bufmgr_mutex_lock();
1008         _tbm_set_last_result(TBM_ERROR_NONE);
1009
1010         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1011
1012         /* check if the data according to the key exist if so, return false. */
1013         data = user_data_lookup(&bo->user_data_list, key);
1014         if (data) {
1015                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1016                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1017                 _tbm_bufmgr_mutex_unlock();
1018                 return 0;
1019         }
1020
1021         data = user_data_create(key, data_free_func);
1022         if (!data) {
1023                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1024                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1025                 _tbm_bufmgr_mutex_unlock();
1026                 return 0;
1027         }
1028
1029         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1030
1031         LIST_ADD(&data->item_link, &bo->user_data_list);
1032
1033         _tbm_bufmgr_mutex_unlock();
1034
1035         return 1;
1036 }
1037
1038 int
1039 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1040 {
1041         tbm_user_data *old_data;
1042
1043         _tbm_bufmgr_mutex_lock();
1044         _tbm_set_last_result(TBM_ERROR_NONE);
1045
1046         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1047
1048         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1049                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1050                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1051                 _tbm_bufmgr_mutex_unlock();
1052                 return 0;
1053         }
1054
1055         old_data = user_data_lookup(&bo->user_data_list, key);
1056         if (!old_data) {
1057                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1058                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1059                 _tbm_bufmgr_mutex_unlock();
1060                 return 0;
1061         }
1062
1063         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1064
1065         user_data_delete(old_data);
1066
1067         _tbm_bufmgr_mutex_unlock();
1068
1069         return 1;
1070 }
1071
1072 int
1073 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1074 {
1075         tbm_user_data *old_data;
1076
1077         _tbm_bufmgr_mutex_lock();
1078         _tbm_set_last_result(TBM_ERROR_NONE);
1079
1080         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1081
1082         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1083                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1084                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1085                 _tbm_bufmgr_mutex_unlock();
1086                 return 0;
1087         }
1088
1089         old_data = user_data_lookup(&bo->user_data_list, key);
1090         if (!old_data) {
1091                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1092                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1093                 _tbm_bufmgr_mutex_unlock();
1094                 return 0;
1095         }
1096
1097         if (old_data->data && old_data->free_func)
1098                 old_data->free_func(old_data->data);
1099         old_data->data = data;
1100
1101         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1102
1103         _tbm_bufmgr_mutex_unlock();
1104
1105         return 1;
1106 }
1107
1108 int
1109 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1110 {
1111         tbm_user_data *old_data;
1112
1113         _tbm_bufmgr_mutex_lock();
1114         _tbm_set_last_result(TBM_ERROR_NONE);
1115
1116         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1117
1118         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1119                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1120                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1121                 _tbm_bufmgr_mutex_unlock();
1122                 return 0;
1123         }
1124
1125         old_data = user_data_lookup(&bo->user_data_list, key);
1126         if (!old_data) {
1127                 *data = NULL;
1128                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1129                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1130                 _tbm_bufmgr_mutex_unlock();
1131                 return 0;
1132         }
1133
1134         *data = old_data->data;
1135
1136         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1137
1138         _tbm_bufmgr_mutex_unlock();
1139
1140         return 1;
1141 }
1142
1143 int
1144 tbm_bo_get_flags(tbm_bo bo)
1145 {
1146         int flags;
1147
1148         _tbm_bufmgr_mutex_lock();
1149
1150         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1151
1152         flags = bo->flags;
1153
1154         TBM_TRACE_BO("bo(%p)\n", bo);
1155
1156         _tbm_bufmgr_mutex_unlock();
1157
1158         return flags;
1159 }
1160
1161 /* LCOV_EXCL_START */
1162 /* internal function */
1163 int
1164 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1165 {
1166         _tbm_bufmgr_mutex_lock();
1167
1168         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1169
1170         bo->surface = surface;
1171
1172         _tbm_bufmgr_mutex_unlock();
1173
1174         return 1;
1175 }
1176
1177 void
1178 _tbm_bo_free(tbm_bo bo)
1179 {
1180         /* destory the user_data_list */
1181         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1182                 tbm_user_data *old_data = NULL, *tmp;
1183
1184                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1185                                 &bo->user_data_list, item_link) {
1186                         TBM_DBG("free user_data\n");
1187                         user_data_delete(old_data);
1188                 }
1189         }
1190
1191         while (bo->lock_cnt > 0) {
1192                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1193                 _bo_unlock(bo);
1194                 bo->lock_cnt--;
1195         }
1196
1197         /* call the bo_free */
1198         if (bo->bufmgr->use_hal_tbm) {
1199                 // call hal_tbm_bo_free when bo is created by tbm_bo_alloc api.
1200                 if (!bo->get_from_hal_surface) {
1201                         bo->get_from_hal_surface = 0;
1202
1203                         hal_tbm_bo_free(bo->bo_data);
1204                         bo->bo_data = NULL;
1205                 }
1206         } else if (bo->bufmgr->backend_module_data) {
1207                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1208                 bo->bo_data = NULL;
1209         } else {
1210                 bo->bufmgr->backend->bo_free(bo);
1211                 bo->priv = NULL;
1212         }
1213
1214         _tbm_bo_deinit(bo);
1215
1216         free(bo);
1217 }
1218 /* LCOV_EXCL_STOP */