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