c97ac1d97e16973f74944692e3596bbae76843ba
[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 /* LCOV_EXCL_STOP */
90
91 tbm_user_data *
92 user_data_lookup(struct list_head *user_data_list, unsigned long key)
93 {
94         tbm_user_data *old_data = NULL;
95
96         if (LIST_IS_EMPTY(user_data_list))
97                 return NULL;
98
99         LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
100                 if (old_data->key == key)
101                         return old_data;
102         }
103
104         return NULL;
105 }
106
107 tbm_user_data *
108 user_data_create(unsigned long key, tbm_data_free data_free_func)
109 {
110         tbm_user_data *user_data;
111
112         user_data = calloc(1, sizeof(tbm_user_data));
113         if (!user_data) {
114                 /* LCOV_EXCL_START */
115                 TBM_ERR("fail to allocate an user_date\n");
116                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
117                 return NULL;
118                 /* LCOV_EXCL_STOP */
119         }
120
121         user_data->key = key;
122         user_data->free_func = data_free_func;
123
124         return user_data;
125 }
126
127 void
128 user_data_delete(tbm_user_data *user_data)
129 {
130         if (user_data->data && user_data->free_func)
131                 user_data->free_func(user_data->data);
132
133         LIST_DEL(&user_data->item_link);
134
135         free(user_data);
136 }
137
138 static int
139 _bo_lock(tbm_bo bo, int device, int opt)
140 {
141         tbm_error_e error;
142         int ret;
143
144         error = tbm_module_bo_lock(bo->bufmgr->module, bo, bo->bo_data, device, opt);
145         _tbm_set_last_result(error);
146         switch(error) {
147                 case TBM_ERROR_NONE:
148                         ret = 1;
149                         break;
150                 case TBM_ERROR_NOT_SUPPORTED:
151                         ret = 1;
152                         _tbm_set_last_result(TBM_ERROR_NONE);
153                         break;
154                 default:
155                         ret = 0;
156                         TBM_WRN("fail to lock. error:%d", error);
157                         break;
158         }
159
160         return ret;
161 }
162
163 static void
164 _bo_unlock(tbm_bo bo)
165 {
166         tbm_error_e error;
167
168         error = tbm_module_bo_unlock(bo->bufmgr->module, bo, bo->bo_data);
169         _tbm_set_last_result(error);
170         switch(error) {
171                 case TBM_ERROR_NONE:
172                         break;
173                 case TBM_ERROR_NOT_SUPPORTED:
174                         _tbm_set_last_result(TBM_ERROR_NONE);
175                         break;
176                 default:
177                         TBM_WRN("fail to lock. error:%d", error);
178                         break;
179         }
180 }
181
182 static int
183 _tbm_bo_lock(tbm_bo bo, int device, int opt)
184 {
185         int old, ret;
186
187         if (!bo)
188                 return 0;
189
190         /* do not try to lock the bo */
191         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
192                 return 1;
193
194         if (bo->lock_cnt < 0) {
195                 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
196                         bo, bo->lock_cnt);
197                 return 0;
198         }
199
200         old = bo->lock_cnt;
201
202         switch (bo->bufmgr->bo_lock_type) {
203         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
204                 if (bo->lock_cnt == 0) {
205                         _tbm_bufmgr_mutex_unlock();
206                         ret = _bo_lock(bo, device, opt);
207                         _tbm_bufmgr_mutex_lock();
208                         if (ret)
209                                 bo->lock_cnt++;
210                 } else
211                         ret = 1;
212                 break;
213         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
214                 _tbm_bufmgr_mutex_unlock();
215                 ret = _bo_lock(bo, device, opt);
216                 _tbm_bufmgr_mutex_lock();
217                 if (ret)
218                         bo->lock_cnt++;
219                 break;
220         default:
221                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
222                                 bo, bo->bufmgr->bo_lock_type);
223                 ret = 0;
224                 break;
225         }
226
227         TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
228
229         return ret;
230 }
231
232 static void
233 _tbm_bo_unlock(tbm_bo bo)
234 {
235         int old;
236
237         /* do not try to unlock the bo */
238         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
239                 return;
240
241         old = bo->lock_cnt;
242
243         switch (bo->bufmgr->bo_lock_type) {
244         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
245                 if (bo->lock_cnt > 0) {
246                         bo->lock_cnt--;
247                         if (bo->lock_cnt == 0)
248                                 _bo_unlock(bo);
249                 }
250                 break;
251         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
252                 if (bo->lock_cnt > 0) {
253                         bo->lock_cnt--;
254                         _bo_unlock(bo);
255                 }
256                 break;
257         default:
258                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
259                                 bo, bo->bufmgr->bo_lock_type);
260                 break;
261         }
262
263         if (bo->lock_cnt < 0)
264                 bo->lock_cnt = 0;
265
266         TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
267 }
268
269 static int
270 _tbm_bo_magic_check(tbm_bo bo)
271 {
272         if (bo->magic != TBM_BO_MAGIC)
273                 return 0;
274
275         return 1;
276 }
277
278 static int
279 _tbm_bo_is_valid(tbm_bo bo)
280 {
281         if (!bo) {
282                 TBM_ERR("error: bo is NULL.\n");
283                 return 0;
284         }
285
286         if (!_tbm_bo_magic_check(bo)) {
287                 TBM_ERR("error: No valid bo(%p).\n", bo);
288                 return 0;
289         }
290
291         return 1;
292 }
293
294 static void
295 _tbm_bo_deinit(tbm_bo bo)
296 {
297         bo->magic = 0;
298
299         bo->bufmgr->bo_cnt--;
300         LIST_DEL(&bo->item_link);
301 }
302
303 tbm_bo
304 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
305 {
306         tbm_bo bo;
307         tbm_error_e error;
308
309         _tbm_bufmgr_mutex_lock();
310         _tbm_set_last_result(TBM_ERROR_NONE);
311
312         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
313         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
314
315         bo = tbm_bufmgr_internal_alloc_bo(bufmgr, size, flags, &error);
316         if (!bo) {
317                 /* LCOV_EXCL_START */
318                 TBM_ERR("tbm_bufmgr_internal_alloc_bo failed. error:%d", error);
319                 _tbm_set_last_result(error);
320                 _tbm_bufmgr_mutex_unlock();
321                 return NULL;
322                 /* LCOV_EXCL_STOP */
323         }
324
325         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
326                         _tbm_flag_to_str(bo->flags));
327
328         _tbm_bufmgr_mutex_unlock();
329
330         return bo;
331 }
332
333 tbm_bo
334 tbm_bo_ref(tbm_bo bo)
335 {
336         _tbm_bufmgr_mutex_lock();
337         _tbm_set_last_result(TBM_ERROR_NONE);
338
339         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
340
341         bo->ref_cnt++;
342
343         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
344
345         _tbm_bufmgr_mutex_unlock();
346
347         return bo;
348 }
349
350 void
351 tbm_bo_unref(tbm_bo bo)
352 {
353         _tbm_bufmgr_mutex_lock();
354         _tbm_set_last_result(TBM_ERROR_NONE);
355
356         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
357
358         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
359
360         if (bo->ref_cnt <= 0) {
361                 _tbm_bufmgr_mutex_unlock();
362                 return;
363         }
364
365         bo->ref_cnt--;
366         if (bo->ref_cnt == 0)
367                 _tbm_bo_free(bo);
368
369         _tbm_bufmgr_mutex_unlock();
370 }
371
372 tbm_bo_handle
373 tbm_bo_map(tbm_bo bo, int device, int opt)
374 {
375         tbm_bo_handle bo_handle;
376         tbm_error_e error;
377
378         _tbm_bufmgr_mutex_lock();
379         _tbm_set_last_result(TBM_ERROR_NONE);
380
381         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
382
383         if (!_tbm_bo_lock(bo, device, opt)) {
384                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
385                 _tbm_bufmgr_mutex_unlock();
386                 return (tbm_bo_handle) NULL;
387         }
388
389         bo_handle = tbm_module_bo_map(bo->bufmgr->module, bo, bo->bo_data, device, opt, &error);
390         if (bo_handle.ptr == NULL) {
391                 /* LCOV_EXCL_START */
392                 TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
393                 _tbm_set_last_result(error);
394                 _tbm_bo_unlock(bo);
395                 _tbm_bufmgr_mutex_unlock();
396                 return (tbm_bo_handle) NULL;
397                 /* LCOV_EXCL_STOP */
398         }
399
400         /* increase the map_count */
401         bo->map_cnt++;
402
403         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
404
405         _tbm_bufmgr_mutex_unlock();
406
407         return bo_handle;
408 }
409
410 int
411 tbm_bo_unmap(tbm_bo bo)
412 {
413         tbm_error_e error;
414
415         _tbm_bufmgr_mutex_lock();
416         _tbm_set_last_result(TBM_ERROR_NONE);
417
418         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
419         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
420
421         error = tbm_module_bo_unmap(bo->bufmgr->module, bo, bo->bo_data);
422         if (error != TBM_ERROR_NONE) {
423                 /* LCOV_EXCL_START */
424                 TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
425                 _tbm_set_last_result(error);
426                 _tbm_bufmgr_mutex_unlock();
427                 return 0;
428                 /* LCOV_EXCL_STOP */
429         }
430
431         /* decrease the map_count */
432         bo->map_cnt--;
433
434         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
435
436         _tbm_bo_unlock(bo);
437
438         _tbm_bufmgr_mutex_unlock();
439
440         return 1;
441 }
442
443 tbm_bo_handle
444 tbm_bo_get_handle(tbm_bo bo, int device)
445 {
446         tbm_bo_handle bo_handle;
447         tbm_error_e error;
448
449         _tbm_bufmgr_mutex_lock();
450         _tbm_set_last_result(TBM_ERROR_NONE);
451
452         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
453
454         bo_handle = tbm_module_bo_get_handle(bo->bufmgr->module, bo, bo->bo_data, device, &error);
455         if (bo_handle.ptr == NULL) {
456                 /* LCOV_EXCL_START */
457                 TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
458                 _tbm_set_last_result(error);
459                 _tbm_bufmgr_mutex_unlock();
460                 return (tbm_bo_handle)NULL;
461                 /* LCOV_EXCL_STOP */
462         }
463
464         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
465
466         _tbm_bufmgr_mutex_unlock();
467
468         return bo_handle;
469 }
470
471 tbm_key
472 tbm_bo_export(tbm_bo bo)
473 {
474         tbm_key ret;
475         tbm_error_e error;
476
477         _tbm_bufmgr_mutex_lock();
478         _tbm_set_last_result(TBM_ERROR_NONE);
479
480         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
481
482         if (bo->bufmgr->use_hal_tbm) {
483                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
484                 if (!ret) {
485                         /* LCOV_EXCL_START */
486                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
487                         _tbm_set_last_result(error);
488                         goto done;
489                         /* LCOV_EXCL_STOP */
490                 }
491         } else if (bo->bufmgr->backend_module_data) {
492                 if (!bo->bufmgr->bo_func->bo_export_key) {
493                         /* LCOV_EXCL_START */
494                         _tbm_bufmgr_mutex_unlock();
495                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
496                         return 0;
497                         /* LCOV_EXCL_STOP */
498                 }
499
500                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
501                 if (!ret) {
502                         /* LCOV_EXCL_START */
503                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
504                         _tbm_set_last_result(error);
505                         goto done;
506                         /* LCOV_EXCL_STOP */
507                 }
508         } else {
509                 if (!bo->bufmgr->backend->bo_export) {
510                         /* LCOV_EXCL_START */
511                         _tbm_bufmgr_mutex_unlock();
512                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
513                         return 0;
514                         /* LCOV_EXCL_STOP */
515                 }
516
517                 ret = bo->bufmgr->backend->bo_export(bo);
518                 if (!ret) {
519                         /* LCOV_EXCL_START */
520                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
521                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
522                         goto done;
523                         /* LCOV_EXCL_STOP */
524                 }
525         }
526
527         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
528
529 done:
530         _tbm_bufmgr_mutex_unlock();
531
532         return ret;
533 }
534
535 tbm_fd
536 tbm_bo_export_fd(tbm_bo bo)
537 {
538         tbm_fd ret;
539         tbm_error_e error;
540
541         _tbm_bufmgr_mutex_lock();
542         _tbm_set_last_result(TBM_ERROR_NONE);
543
544         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
545
546         if (bo->bufmgr->use_hal_tbm) {
547                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
548                 if (ret < 0) {
549                         /* LCOV_EXCL_START */
550                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
551                         _tbm_set_last_result(error);
552                         goto done;
553                         /* LCOV_EXCL_STOP */
554                 }
555         } else if (bo->bufmgr->backend_module_data) {
556                 if (!bo->bufmgr->bo_func->bo_export_fd) {
557                         /* LCOV_EXCL_START */
558                         _tbm_bufmgr_mutex_unlock();
559                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
560                         return -1;
561                         /* LCOV_EXCL_STOP */
562                 }
563
564                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
565                 if (ret < 0) {
566                         /* LCOV_EXCL_START */
567                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
568                         _tbm_set_last_result(error);
569                         goto done;
570                         /* LCOV_EXCL_STOP */
571                 }
572         } else {
573                 if (!bo->bufmgr->backend->bo_export_fd) {
574                         /* LCOV_EXCL_START */
575                         _tbm_bufmgr_mutex_unlock();
576                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
577                         return -1;
578                         /* LCOV_EXCL_STOP */
579                 }
580
581                 ret = bo->bufmgr->backend->bo_export_fd(bo);
582                 if (ret < 0) {
583                         /* LCOV_EXCL_START */
584                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
585                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
586                         goto done;
587                         /* LCOV_EXCL_STOP */
588                 }
589         }
590
591         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
592
593 done:
594         _tbm_bufmgr_mutex_unlock();
595
596         return ret;
597 }
598
599 tbm_bo
600 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
601 {
602         tbm_bo bo;
603         tbm_error_e error;
604
605         _tbm_bufmgr_mutex_lock();
606         _tbm_set_last_result(TBM_ERROR_NONE);
607
608         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
609
610         bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key, &error);
611         if (!bo) {
612                 /* LCOV_EXCL_START */
613                 TBM_ERR("tbm_bufmgr_internal_import_key failed. error:%d", error);
614                 _tbm_set_last_result(error);
615                 _tbm_bufmgr_mutex_unlock();
616                 return NULL;
617                 /* LCOV_EXCL_STOP */
618         }
619
620         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
621                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
622
623         _tbm_bufmgr_mutex_unlock();
624
625         return bo;
626 }
627
628 tbm_bo
629 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
630 {
631         tbm_bo bo;
632         tbm_error_e error;
633
634         _tbm_bufmgr_mutex_lock();
635         _tbm_set_last_result(TBM_ERROR_NONE);
636
637         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
638
639         bo = tbm_bufmgr_internal_import_bo_with_fd(bufmgr, fd, &error);
640         if (!bo) {
641                 /* LCOV_EXCL_START */
642                 TBM_ERR("tbm_bufmgr_internal_import_fd failed. error:%d", error);
643                 _tbm_set_last_result(error);
644                 _tbm_bufmgr_mutex_unlock();
645                 return NULL;
646                 /* LCOV_EXCL_STOP */
647         }
648
649         LIST_INITHEAD(&bo->user_data_list); // TODO: remove this. build-break when it is removed.
650
651         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
652                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
653
654         _tbm_bufmgr_mutex_unlock();
655
656         return bo;
657 }
658
659 int
660 tbm_bo_size(tbm_bo bo)
661 {
662         int size;
663         tbm_error_e error;
664
665         _tbm_bufmgr_mutex_lock();
666         _tbm_set_last_result(TBM_ERROR_NONE);
667
668         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
669
670         size = tbm_module_bo_get_size(bo->bufmgr->module, bo, bo->bo_data, &error);
671         _tbm_set_last_result(error);
672
673         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
674
675         _tbm_bufmgr_mutex_unlock();
676
677         return size;
678 }
679
680 int
681 tbm_bo_locked(tbm_bo bo)
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), 0);
687
688         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
689                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
690                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
691                 _tbm_bufmgr_mutex_unlock();
692                 return 0;
693         }
694
695         if (bo->lock_cnt > 0) {
696                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
697                 _tbm_bufmgr_mutex_unlock();
698                 return 1;
699         }
700
701         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
702         _tbm_bufmgr_mutex_unlock();
703
704         return 0;
705 }
706
707 int
708 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
709 {
710         tbm_error_e error1, error2;
711         int size1 = -1, size2 = -2;
712         void *temp;
713
714         _tbm_bufmgr_mutex_lock();
715         _tbm_set_last_result(TBM_ERROR_NONE);
716
717         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
718         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
719
720         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
721
722         size1 = tbm_module_bo_get_size(bo1->bufmgr->module, bo1, bo1->bo_data, &error1);
723         _tbm_set_last_result(error1);
724         size2 = tbm_module_bo_get_size(bo2->bufmgr->module, bo2, bo2->bo_data, &error2);
725         _tbm_set_last_result(error2);
726
727         if (size1 != size2) {
728                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
729                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
730                 goto fail;
731         }
732
733         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
734
735         temp = bo1->priv;
736         bo1->priv = bo2->priv;
737         bo2->priv = temp;
738
739         _tbm_bufmgr_mutex_unlock();
740
741         return 1;
742
743 fail:
744         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
745         _tbm_bufmgr_mutex_unlock();
746
747         return 0;
748 }
749
750 int
751 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
752                      tbm_data_free data_free_func)
753 {
754         tbm_user_data *data;
755
756         _tbm_bufmgr_mutex_lock();
757         _tbm_set_last_result(TBM_ERROR_NONE);
758
759         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
760
761         /* check if the data according to the key exist if so, return false. */
762         data = user_data_lookup(&bo->user_data_list, key);
763         if (data) {
764                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
765                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
766                 _tbm_bufmgr_mutex_unlock();
767                 return 0;
768         }
769
770         data = user_data_create(key, data_free_func);
771         if (!data) {
772                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
773                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
774                 _tbm_bufmgr_mutex_unlock();
775                 return 0;
776         }
777
778         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
779
780         LIST_ADD(&data->item_link, &bo->user_data_list);
781
782         _tbm_bufmgr_mutex_unlock();
783
784         return 1;
785 }
786
787 int
788 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
789 {
790         tbm_user_data *old_data;
791
792         _tbm_bufmgr_mutex_lock();
793         _tbm_set_last_result(TBM_ERROR_NONE);
794
795         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
796
797         if (LIST_IS_EMPTY(&bo->user_data_list)) {
798                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
799                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
800                 _tbm_bufmgr_mutex_unlock();
801                 return 0;
802         }
803
804         old_data = user_data_lookup(&bo->user_data_list, key);
805         if (!old_data) {
806                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
807                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
808                 _tbm_bufmgr_mutex_unlock();
809                 return 0;
810         }
811
812         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
813
814         user_data_delete(old_data);
815
816         _tbm_bufmgr_mutex_unlock();
817
818         return 1;
819 }
820
821 int
822 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
823 {
824         tbm_user_data *old_data;
825
826         _tbm_bufmgr_mutex_lock();
827         _tbm_set_last_result(TBM_ERROR_NONE);
828
829         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
830
831         if (LIST_IS_EMPTY(&bo->user_data_list)) {
832                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
833                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
834                 _tbm_bufmgr_mutex_unlock();
835                 return 0;
836         }
837
838         old_data = user_data_lookup(&bo->user_data_list, key);
839         if (!old_data) {
840                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
841                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
842                 _tbm_bufmgr_mutex_unlock();
843                 return 0;
844         }
845
846         if (old_data->data && old_data->free_func)
847                 old_data->free_func(old_data->data);
848         old_data->data = data;
849
850         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
851
852         _tbm_bufmgr_mutex_unlock();
853
854         return 1;
855 }
856
857 int
858 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
859 {
860         tbm_user_data *old_data;
861
862         _tbm_bufmgr_mutex_lock();
863         _tbm_set_last_result(TBM_ERROR_NONE);
864
865         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
866
867         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
868                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
869                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
870                 _tbm_bufmgr_mutex_unlock();
871                 return 0;
872         }
873
874         old_data = user_data_lookup(&bo->user_data_list, key);
875         if (!old_data) {
876                 *data = NULL;
877                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
878                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
879                 _tbm_bufmgr_mutex_unlock();
880                 return 0;
881         }
882
883         *data = old_data->data;
884
885         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
886
887         _tbm_bufmgr_mutex_unlock();
888
889         return 1;
890 }
891
892 int
893 tbm_bo_get_flags(tbm_bo bo)
894 {
895         int flags;
896
897         _tbm_bufmgr_mutex_lock();
898
899         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
900
901         flags = bo->flags;
902
903         TBM_TRACE_BO("bo(%p)\n", bo);
904
905         _tbm_bufmgr_mutex_unlock();
906
907         return flags;
908 }
909
910 /* LCOV_EXCL_START */
911 /* internal function */
912 int
913 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
914 {
915         _tbm_bufmgr_mutex_lock();
916
917         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
918
919         bo->surface = surface;
920
921         _tbm_bufmgr_mutex_unlock();
922
923         return 1;
924 }
925
926 void
927 _tbm_bo_free(tbm_bo bo)
928 {
929         /* destory the user_data_list */
930         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
931                 tbm_user_data *old_data = NULL, *tmp;
932
933                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
934                                 &bo->user_data_list, item_link) {
935                         TBM_DBG("free user_data\n");
936                         user_data_delete(old_data);
937                 }
938         }
939
940         while (bo->lock_cnt > 0) {
941                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
942                 _bo_unlock(bo);
943                 bo->lock_cnt--;
944         }
945
946         tbm_module_bo_free(bo->bufmgr->module, bo, bo->bo_data, bo->get_from_hal_surface);
947
948         _tbm_bo_deinit(bo);
949
950         free(bo);
951 }
952 /* LCOV_EXCL_STOP */