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