tbm_module: change the tbm_module_bo_xxx signature
[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_bo_data_lock(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_bo_data_unlock(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_bo_data_map(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_bo_data_unmap(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_bo_data_get_handle(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         ret = tbm_bo_data_export_key(bo->bo_data, &error);
483         if (!ret) {
484                 /* LCOV_EXCL_START */
485                 TBM_ERR("tbm_moule_bo_export_key failed. bo:%p tbm_key:%d error:%d", bo, ret, error);
486                 _tbm_set_last_result(error);
487                 _tbm_bufmgr_mutex_unlock();
488                 return ret;
489                 /* LCOV_EXCL_STOP */
490         }
491
492         TBM_TRACE_BO("bo:%p tbm_key:%u", bo, ret);
493
494         _tbm_bufmgr_mutex_unlock();
495
496         return ret;
497 }
498
499 tbm_fd
500 tbm_bo_export_fd(tbm_bo bo)
501 {
502         tbm_fd fd;
503         tbm_error_e error;
504
505         _tbm_bufmgr_mutex_lock();
506         _tbm_set_last_result(TBM_ERROR_NONE);
507
508         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
509
510         fd = tbm_bo_data_export_fd(bo->bo_data, &error);
511         if (fd < 0) {
512                 /* LCOV_EXCL_START */
513                 TBM_ERR("tbm_bo_data_export_fd filed. bo:%p tbm_fd:%d error:%d", bo, fd, error);
514                 _tbm_set_last_result(error);
515                 _tbm_bufmgr_mutex_unlock();
516                 return fd;
517                 /* LCOV_EXCL_STOP */
518         }
519
520         TBM_TRACE_BO("bo:%p tbm_fd:%d", bo, fd);
521
522         _tbm_bufmgr_mutex_unlock();
523
524         return fd;
525 }
526
527 tbm_bo
528 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
529 {
530         tbm_bo bo;
531         tbm_error_e error;
532
533         _tbm_bufmgr_mutex_lock();
534         _tbm_set_last_result(TBM_ERROR_NONE);
535
536         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
537
538         bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key, &error);
539         if (!bo) {
540                 /* LCOV_EXCL_START */
541                 TBM_ERR("tbm_bufmgr_internal_import_key failed. error:%d", error);
542                 _tbm_set_last_result(error);
543                 _tbm_bufmgr_mutex_unlock();
544                 return NULL;
545                 /* LCOV_EXCL_STOP */
546         }
547
548         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
549                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
550
551         _tbm_bufmgr_mutex_unlock();
552
553         return bo;
554 }
555
556 tbm_bo
557 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
558 {
559         tbm_bo bo;
560         tbm_error_e error;
561
562         _tbm_bufmgr_mutex_lock();
563         _tbm_set_last_result(TBM_ERROR_NONE);
564
565         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
566
567         bo = tbm_bufmgr_internal_import_bo_with_fd(bufmgr, fd, &error);
568         if (!bo) {
569                 /* LCOV_EXCL_START */
570                 TBM_ERR("tbm_bufmgr_internal_import_fd failed. error:%d", error);
571                 _tbm_set_last_result(error);
572                 _tbm_bufmgr_mutex_unlock();
573                 return NULL;
574                 /* LCOV_EXCL_STOP */
575         }
576
577         LIST_INITHEAD(&bo->user_data_list); // TODO: remove this. build-break when it is removed.
578
579         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
580                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
581
582         _tbm_bufmgr_mutex_unlock();
583
584         return bo;
585 }
586
587 int
588 tbm_bo_size(tbm_bo bo)
589 {
590         int size;
591         tbm_error_e error;
592
593         _tbm_bufmgr_mutex_lock();
594         _tbm_set_last_result(TBM_ERROR_NONE);
595
596         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
597
598         size = tbm_bo_data_get_size(bo->bo_data, &error);
599         _tbm_set_last_result(error);
600
601         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
602
603         _tbm_bufmgr_mutex_unlock();
604
605         return size;
606 }
607
608 int
609 tbm_bo_locked(tbm_bo bo)
610 {
611         _tbm_bufmgr_mutex_lock();
612         _tbm_set_last_result(TBM_ERROR_NONE);
613
614         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
615
616         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
617                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
618                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
619                 _tbm_bufmgr_mutex_unlock();
620                 return 0;
621         }
622
623         if (bo->lock_cnt > 0) {
624                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
625                 _tbm_bufmgr_mutex_unlock();
626                 return 1;
627         }
628
629         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
630         _tbm_bufmgr_mutex_unlock();
631
632         return 0;
633 }
634
635 int
636 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
637 {
638         tbm_error_e error1, error2;
639         int size1 = -1, size2 = -2;
640         void *temp;
641
642         _tbm_bufmgr_mutex_lock();
643         _tbm_set_last_result(TBM_ERROR_NONE);
644
645         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
646         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
647
648         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
649
650         size1 = tbm_bo_data_get_size(bo1->bo_data, &error1);
651         _tbm_set_last_result(error1);
652         size2 = tbm_bo_data_get_size(bo2->bo_data, &error2);
653         _tbm_set_last_result(error2);
654
655         if (size1 != size2) {
656                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
657                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
658                 goto fail;
659         }
660
661         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
662
663         temp = bo1->priv;
664         bo1->priv = bo2->priv;
665         bo2->priv = temp;
666
667         _tbm_bufmgr_mutex_unlock();
668
669         return 1;
670
671 fail:
672         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
673         _tbm_bufmgr_mutex_unlock();
674
675         return 0;
676 }
677
678 int
679 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
680                      tbm_data_free data_free_func)
681 {
682         tbm_user_data *data;
683
684         _tbm_bufmgr_mutex_lock();
685         _tbm_set_last_result(TBM_ERROR_NONE);
686
687         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
688
689         /* check if the data according to the key exist if so, return false. */
690         data = user_data_lookup(&bo->user_data_list, key);
691         if (data) {
692                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
693                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
694                 _tbm_bufmgr_mutex_unlock();
695                 return 0;
696         }
697
698         data = user_data_create(key, data_free_func);
699         if (!data) {
700                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
701                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
702                 _tbm_bufmgr_mutex_unlock();
703                 return 0;
704         }
705
706         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
707
708         LIST_ADD(&data->item_link, &bo->user_data_list);
709
710         _tbm_bufmgr_mutex_unlock();
711
712         return 1;
713 }
714
715 int
716 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
717 {
718         tbm_user_data *old_data;
719
720         _tbm_bufmgr_mutex_lock();
721         _tbm_set_last_result(TBM_ERROR_NONE);
722
723         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
724
725         if (LIST_IS_EMPTY(&bo->user_data_list)) {
726                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
727                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
728                 _tbm_bufmgr_mutex_unlock();
729                 return 0;
730         }
731
732         old_data = user_data_lookup(&bo->user_data_list, key);
733         if (!old_data) {
734                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
735                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
736                 _tbm_bufmgr_mutex_unlock();
737                 return 0;
738         }
739
740         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
741
742         user_data_delete(old_data);
743
744         _tbm_bufmgr_mutex_unlock();
745
746         return 1;
747 }
748
749 int
750 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
751 {
752         tbm_user_data *old_data;
753
754         _tbm_bufmgr_mutex_lock();
755         _tbm_set_last_result(TBM_ERROR_NONE);
756
757         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
758
759         if (LIST_IS_EMPTY(&bo->user_data_list)) {
760                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
761                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
762                 _tbm_bufmgr_mutex_unlock();
763                 return 0;
764         }
765
766         old_data = user_data_lookup(&bo->user_data_list, key);
767         if (!old_data) {
768                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
769                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
770                 _tbm_bufmgr_mutex_unlock();
771                 return 0;
772         }
773
774         if (old_data->data && old_data->free_func)
775                 old_data->free_func(old_data->data);
776         old_data->data = data;
777
778         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
779
780         _tbm_bufmgr_mutex_unlock();
781
782         return 1;
783 }
784
785 int
786 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
787 {
788         tbm_user_data *old_data;
789
790         _tbm_bufmgr_mutex_lock();
791         _tbm_set_last_result(TBM_ERROR_NONE);
792
793         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
794
795         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
796                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
797                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
798                 _tbm_bufmgr_mutex_unlock();
799                 return 0;
800         }
801
802         old_data = user_data_lookup(&bo->user_data_list, key);
803         if (!old_data) {
804                 *data = NULL;
805                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
806                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
807                 _tbm_bufmgr_mutex_unlock();
808                 return 0;
809         }
810
811         *data = old_data->data;
812
813         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
814
815         _tbm_bufmgr_mutex_unlock();
816
817         return 1;
818 }
819
820 int
821 tbm_bo_get_flags(tbm_bo bo)
822 {
823         int flags;
824
825         _tbm_bufmgr_mutex_lock();
826
827         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
828
829         flags = bo->flags;
830
831         TBM_TRACE_BO("bo(%p)\n", bo);
832
833         _tbm_bufmgr_mutex_unlock();
834
835         return flags;
836 }
837
838 /* LCOV_EXCL_START */
839 /* internal function */
840 int
841 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
842 {
843         _tbm_bufmgr_mutex_lock();
844
845         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
846
847         bo->surface = surface;
848
849         _tbm_bufmgr_mutex_unlock();
850
851         return 1;
852 }
853
854 void
855 _tbm_bo_free(tbm_bo bo)
856 {
857         /* destory the user_data_list */
858         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
859                 tbm_user_data *old_data = NULL, *tmp;
860
861                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
862                                 &bo->user_data_list, item_link) {
863                         TBM_DBG("free user_data\n");
864                         user_data_delete(old_data);
865                 }
866         }
867
868         while (bo->lock_cnt > 0) {
869                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
870                 _bo_unlock(bo);
871                 bo->lock_cnt--;
872         }
873
874         tbm_bo_data_free(bo->bo_data, bo->get_from_surface_data);
875
876         _tbm_bo_deinit(bo);
877
878         free(bo);
879 }
880 /* LCOV_EXCL_STOP */