tbm_module: add tbm_module_bo_unmap and use it
[platform/core/uifw/libtbm.git] / src / tbm_bo.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33 #include "tbm_bufmgr.h"
34 #include "tbm_bufmgr_int.h"
35 #include "list.h"
36
37 /* check condition */
38 #define TBM_BO_RETURN_IF_FAIL(cond) {\
39         if (!(cond)) {\
40                 TBM_ERR("'%s' failed.\n", #cond);\
41                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
42                 _tbm_bufmgr_mutex_unlock();\
43                 return;\
44         } \
45 }
46
47 #define TBM_BO_RETURN_VAL_IF_FAIL(cond, val) {\
48         if (!(cond)) {\
49                 TBM_ERR("'%s' failed.\n", #cond);\
50                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
51                 _tbm_bufmgr_mutex_unlock();\
52                 return val;\
53         } \
54 }
55
56 char *
57 _tbm_flag_to_str(int f)
58 {
59         static char str[255];
60
61         if (f == TBM_BO_DEFAULT)
62                  snprintf(str, 255, "DEFAULT");
63         else {
64                 int c = 0;
65
66                 if (f & TBM_BO_SCANOUT)
67                         c += snprintf(&str[c], 255-c, "SCANOUT");
68
69                 if (f & TBM_BO_NONCACHABLE) {
70                         if (c >= 0 && c < 255)
71                                 c += snprintf(&str[c], 255-c, ", ");
72
73                         if (c >= 0 && c < 255)
74                                 c += snprintf(&str[c], 255-c, "NONCACHABLE,");
75                 }
76
77                 if (f & TBM_BO_WC) {
78                         if (c >= 0 && c < 255)
79                                 c += snprintf(&str[c], 255-c, ", ");
80
81                         if (c >= 0 && c < 255)
82                                 c += snprintf(&str[c], 255-c, "WC");
83                 }
84         }
85
86         return str;
87 }
88
89 /* 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         int ret = 1;
142         tbm_error_e error;
143
144         if (bo->bufmgr->use_hal_tbm) {
145                 error = (tbm_error_e)hal_tbm_bo_lock((hal_tbm_bo *)bo->bo_data, device, opt);
146                 if (error == TBM_ERROR_NOT_SUPPORTED) {
147                         _tbm_set_last_result(TBM_ERROR_NONE);
148                 } else {
149                         if (error != TBM_ERROR_NONE) {
150                                 TBM_WRN("fail to lock");
151                                 _tbm_set_last_result(error);
152                                 ret = 0;
153                         }
154                 }
155         } else if (bo->bufmgr->backend_module_data) {
156                 if (bo->bufmgr->bo_func->bo_lock) {
157                         error = bo->bufmgr->bo_func->bo_lock(bo->bo_data, device, opt);
158                         if (error != TBM_ERROR_NONE) {
159                                 TBM_WRN("fail to lock");
160                                 _tbm_set_last_result(error);
161                                 ret = 0;
162                         }
163                 }
164         } else {
165                 if (bo->bufmgr->backend->bo_lock) {
166                         ret = bo->bufmgr->backend->bo_lock(bo, device, opt);
167                         if (!ret)
168                                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
169                 }
170         }
171
172         return ret;
173 }
174
175 static void
176 _bo_unlock(tbm_bo bo)
177 {
178         tbm_error_e error;
179
180         if (bo->bufmgr->use_hal_tbm) {
181                 error = (tbm_error_e)hal_tbm_bo_unlock((hal_tbm_bo *)bo->bo_data);
182                 if (error == TBM_ERROR_NOT_SUPPORTED) {
183                         _tbm_set_last_result(TBM_ERROR_NONE);
184                 } else {
185                         if (error != TBM_ERROR_NONE) {
186                                 TBM_WRN("fail to lock");
187                                 _tbm_set_last_result(error);
188                         }
189                 }
190         } else if (bo->bufmgr->backend_module_data) {
191                 if (bo->bufmgr->bo_func->bo_unlock) {
192                         error = bo->bufmgr->bo_func->bo_unlock(bo->bo_data);
193                         if (error != TBM_ERROR_NONE) {
194                                 TBM_WRN("fail to unlock");
195                                 _tbm_set_last_result(error);
196                         }
197                 }
198         } else {
199                 if (bo->bufmgr->backend->bo_unlock)
200                         bo->bufmgr->backend->bo_unlock(bo);
201         }
202 }
203
204 static int
205 _tbm_bo_lock(tbm_bo bo, int device, int opt)
206 {
207         int old, ret;
208
209         if (!bo)
210                 return 0;
211
212         /* do not try to lock the bo */
213         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
214                 return 1;
215
216         if (bo->lock_cnt < 0) {
217                 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
218                         bo, bo->lock_cnt);
219                 return 0;
220         }
221
222         old = bo->lock_cnt;
223
224         switch (bo->bufmgr->bo_lock_type) {
225         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
226                 if (bo->lock_cnt == 0) {
227                         _tbm_bufmgr_mutex_unlock();
228                         ret = _bo_lock(bo, device, opt);
229                         _tbm_bufmgr_mutex_lock();
230                         if (ret)
231                                 bo->lock_cnt++;
232                 } else
233                         ret = 1;
234                 break;
235         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
236                 _tbm_bufmgr_mutex_unlock();
237                 ret = _bo_lock(bo, device, opt);
238                 _tbm_bufmgr_mutex_lock();
239                 if (ret)
240                         bo->lock_cnt++;
241                 break;
242         default:
243                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
244                                 bo, bo->bufmgr->bo_lock_type);
245                 ret = 0;
246                 break;
247         }
248
249         TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
250
251         return ret;
252 }
253
254 static void
255 _tbm_bo_unlock(tbm_bo bo)
256 {
257         int old;
258
259         /* do not try to unlock the bo */
260         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
261                 return;
262
263         old = bo->lock_cnt;
264
265         switch (bo->bufmgr->bo_lock_type) {
266         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
267                 if (bo->lock_cnt > 0) {
268                         bo->lock_cnt--;
269                         if (bo->lock_cnt == 0)
270                                 _bo_unlock(bo);
271                 }
272                 break;
273         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
274                 if (bo->lock_cnt > 0) {
275                         bo->lock_cnt--;
276                         _bo_unlock(bo);
277                 }
278                 break;
279         default:
280                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
281                                 bo, bo->bufmgr->bo_lock_type);
282                 break;
283         }
284
285         if (bo->lock_cnt < 0)
286                 bo->lock_cnt = 0;
287
288         TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
289 }
290
291 static int
292 _tbm_bo_magic_check(tbm_bo bo)
293 {
294         if (bo->magic != TBM_BO_MAGIC)
295                 return 0;
296
297         return 1;
298 }
299
300 static int
301 _tbm_bo_is_valid(tbm_bo bo)
302 {
303         if (!bo) {
304                 TBM_ERR("error: bo is NULL.\n");
305                 return 0;
306         }
307
308         if (!_tbm_bo_magic_check(bo)) {
309                 TBM_ERR("error: No valid bo(%p).\n", bo);
310                 return 0;
311         }
312
313         return 1;
314 }
315
316 static void
317 _tbm_bo_deinit(tbm_bo bo)
318 {
319         bo->magic = 0;
320
321         bo->bufmgr->bo_cnt--;
322         LIST_DEL(&bo->item_link);
323 }
324
325 tbm_bo
326 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
327 {
328         tbm_bo bo;
329         tbm_error_e error;
330
331         _tbm_bufmgr_mutex_lock();
332         _tbm_set_last_result(TBM_ERROR_NONE);
333
334         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
335         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
336
337         bo = tbm_bufmgr_internal_alloc_bo(bufmgr, size, flags, &error);
338         if (!bo) {
339                 /* LCOV_EXCL_START */
340                 TBM_ERR("tbm_bufmgr_internal_alloc_bo failed. error:%d", error);
341                 _tbm_set_last_result(error);
342                 _tbm_bufmgr_mutex_unlock();
343                 return NULL;
344                 /* LCOV_EXCL_STOP */
345         }
346
347         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
348                         _tbm_flag_to_str(bo->flags));
349
350         _tbm_bufmgr_mutex_unlock();
351
352         return bo;
353 }
354
355 tbm_bo
356 tbm_bo_ref(tbm_bo bo)
357 {
358         _tbm_bufmgr_mutex_lock();
359         _tbm_set_last_result(TBM_ERROR_NONE);
360
361         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
362
363         bo->ref_cnt++;
364
365         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
366
367         _tbm_bufmgr_mutex_unlock();
368
369         return bo;
370 }
371
372 void
373 tbm_bo_unref(tbm_bo bo)
374 {
375         _tbm_bufmgr_mutex_lock();
376         _tbm_set_last_result(TBM_ERROR_NONE);
377
378         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
379
380         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
381
382         if (bo->ref_cnt <= 0) {
383                 _tbm_bufmgr_mutex_unlock();
384                 return;
385         }
386
387         bo->ref_cnt--;
388         if (bo->ref_cnt == 0)
389                 _tbm_bo_free(bo);
390
391         _tbm_bufmgr_mutex_unlock();
392 }
393
394 tbm_bo_handle
395 tbm_bo_map(tbm_bo bo, int device, int opt)
396 {
397         tbm_bo_handle bo_handle;
398         tbm_error_e error;
399
400         _tbm_bufmgr_mutex_lock();
401         _tbm_set_last_result(TBM_ERROR_NONE);
402
403         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
404
405         if (!_tbm_bo_lock(bo, device, opt)) {
406                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
407                 _tbm_bufmgr_mutex_unlock();
408                 return (tbm_bo_handle) NULL;
409         }
410
411         bo_handle = tbm_module_bo_map(bo->bufmgr->module, bo, bo->bo_data, device, opt, &error);
412         if (bo_handle.ptr == NULL) {
413                 /* LCOV_EXCL_START */
414                 TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
415                 _tbm_set_last_result(error);
416                 _tbm_bo_unlock(bo);
417                 _tbm_bufmgr_mutex_unlock();
418                 return (tbm_bo_handle) NULL;
419                 /* LCOV_EXCL_STOP */
420         }
421
422         /* increase the map_count */
423         bo->map_cnt++;
424
425         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
426
427         _tbm_bufmgr_mutex_unlock();
428
429         return bo_handle;
430 }
431
432 int
433 tbm_bo_unmap(tbm_bo bo)
434 {
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), 0);
441         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
442
443         error = tbm_module_bo_unmap(bo->bufmgr->module, bo, bo->bo_data);
444         if (error != TBM_ERROR_NONE) {
445                 /* LCOV_EXCL_START */
446                 TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
447                 _tbm_set_last_result(error);
448                 _tbm_bufmgr_mutex_unlock();
449                 return 0;
450                 /* LCOV_EXCL_STOP */
451         }
452
453         /* decrease the map_count */
454         bo->map_cnt--;
455
456         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
457
458         _tbm_bo_unlock(bo);
459
460         _tbm_bufmgr_mutex_unlock();
461
462         return 1;
463 }
464
465 tbm_bo_handle
466 tbm_bo_get_handle(tbm_bo bo, int device)
467 {
468         tbm_bo_handle bo_handle;
469         tbm_error_e error;
470
471         _tbm_bufmgr_mutex_lock();
472         _tbm_set_last_result(TBM_ERROR_NONE);
473
474         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
475
476         bo_handle = tbm_module_bo_get_handle(bo->bufmgr->module, bo, bo->bo_data, device, &error);
477         if (bo_handle.ptr == NULL) {
478                 /* LCOV_EXCL_START */
479                 TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
480                 _tbm_set_last_result(error);
481                 _tbm_bufmgr_mutex_unlock();
482                 return (tbm_bo_handle)NULL;
483                 /* LCOV_EXCL_STOP */
484         }
485
486         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
487
488         _tbm_bufmgr_mutex_unlock();
489
490         return bo_handle;
491 }
492
493 tbm_key
494 tbm_bo_export(tbm_bo bo)
495 {
496         tbm_key ret;
497         tbm_error_e error;
498
499         _tbm_bufmgr_mutex_lock();
500         _tbm_set_last_result(TBM_ERROR_NONE);
501
502         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
503
504         if (bo->bufmgr->use_hal_tbm) {
505                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
506                 if (!ret) {
507                         /* LCOV_EXCL_START */
508                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
509                         _tbm_set_last_result(error);
510                         goto done;
511                         /* LCOV_EXCL_STOP */
512                 }
513         } else if (bo->bufmgr->backend_module_data) {
514                 if (!bo->bufmgr->bo_func->bo_export_key) {
515                         /* LCOV_EXCL_START */
516                         _tbm_bufmgr_mutex_unlock();
517                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
518                         return 0;
519                         /* LCOV_EXCL_STOP */
520                 }
521
522                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
523                 if (!ret) {
524                         /* LCOV_EXCL_START */
525                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
526                         _tbm_set_last_result(error);
527                         goto done;
528                         /* LCOV_EXCL_STOP */
529                 }
530         } else {
531                 if (!bo->bufmgr->backend->bo_export) {
532                         /* LCOV_EXCL_START */
533                         _tbm_bufmgr_mutex_unlock();
534                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
535                         return 0;
536                         /* LCOV_EXCL_STOP */
537                 }
538
539                 ret = bo->bufmgr->backend->bo_export(bo);
540                 if (!ret) {
541                         /* LCOV_EXCL_START */
542                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
543                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
544                         goto done;
545                         /* LCOV_EXCL_STOP */
546                 }
547         }
548
549         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
550
551 done:
552         _tbm_bufmgr_mutex_unlock();
553
554         return ret;
555 }
556
557 tbm_fd
558 tbm_bo_export_fd(tbm_bo bo)
559 {
560         tbm_fd ret;
561         tbm_error_e error;
562
563         _tbm_bufmgr_mutex_lock();
564         _tbm_set_last_result(TBM_ERROR_NONE);
565
566         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
567
568         if (bo->bufmgr->use_hal_tbm) {
569                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
570                 if (ret < 0) {
571                         /* LCOV_EXCL_START */
572                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
573                         _tbm_set_last_result(error);
574                         goto done;
575                         /* LCOV_EXCL_STOP */
576                 }
577         } else if (bo->bufmgr->backend_module_data) {
578                 if (!bo->bufmgr->bo_func->bo_export_fd) {
579                         /* LCOV_EXCL_START */
580                         _tbm_bufmgr_mutex_unlock();
581                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
582                         return -1;
583                         /* LCOV_EXCL_STOP */
584                 }
585
586                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
587                 if (ret < 0) {
588                         /* LCOV_EXCL_START */
589                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
590                         _tbm_set_last_result(error);
591                         goto done;
592                         /* LCOV_EXCL_STOP */
593                 }
594         } else {
595                 if (!bo->bufmgr->backend->bo_export_fd) {
596                         /* LCOV_EXCL_START */
597                         _tbm_bufmgr_mutex_unlock();
598                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
599                         return -1;
600                         /* LCOV_EXCL_STOP */
601                 }
602
603                 ret = bo->bufmgr->backend->bo_export_fd(bo);
604                 if (ret < 0) {
605                         /* LCOV_EXCL_START */
606                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
607                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
608                         goto done;
609                         /* LCOV_EXCL_STOP */
610                 }
611         }
612
613         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
614
615 done:
616         _tbm_bufmgr_mutex_unlock();
617
618         return ret;
619 }
620
621 tbm_bo
622 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
623 {
624         tbm_bo bo;
625         tbm_error_e error;
626
627         _tbm_bufmgr_mutex_lock();
628         _tbm_set_last_result(TBM_ERROR_NONE);
629
630         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
631
632         bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key, &error);
633         if (!bo) {
634                 /* LCOV_EXCL_START */
635                 TBM_ERR("tbm_bufmgr_internal_import_key failed. error:%d", error);
636                 _tbm_set_last_result(error);
637                 _tbm_bufmgr_mutex_unlock();
638                 return NULL;
639                 /* LCOV_EXCL_STOP */
640         }
641
642         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
643                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
644
645         _tbm_bufmgr_mutex_unlock();
646
647         return bo;
648 }
649
650 tbm_bo
651 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
652 {
653         tbm_bo bo;
654         tbm_error_e error;
655
656         _tbm_bufmgr_mutex_lock();
657         _tbm_set_last_result(TBM_ERROR_NONE);
658
659         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
660
661         bo = tbm_bufmgr_internal_import_bo_with_fd(bufmgr, fd, &error);
662         if (!bo) {
663                 /* LCOV_EXCL_START */
664                 TBM_ERR("tbm_bufmgr_internal_import_fd failed. error:%d", error);
665                 _tbm_set_last_result(error);
666                 _tbm_bufmgr_mutex_unlock();
667                 return NULL;
668                 /* LCOV_EXCL_STOP */
669         }
670
671         LIST_INITHEAD(&bo->user_data_list); // TODO: remove this. build-break when it is removed.
672
673         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
674                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
675
676         _tbm_bufmgr_mutex_unlock();
677
678         return bo;
679 }
680
681 int
682 tbm_bo_size(tbm_bo bo)
683 {
684         int size;
685         tbm_error_e error;
686
687         _tbm_bufmgr_mutex_lock();
688         _tbm_set_last_result(TBM_ERROR_NONE);
689
690         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
691
692         size = tbm_module_bo_get_size(bo->bufmgr->module, bo, bo->bo_data, &error);
693         _tbm_set_last_result(error);
694
695         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
696
697         _tbm_bufmgr_mutex_unlock();
698
699         return size;
700 }
701
702 int
703 tbm_bo_locked(tbm_bo bo)
704 {
705         _tbm_bufmgr_mutex_lock();
706         _tbm_set_last_result(TBM_ERROR_NONE);
707
708         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
709
710         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
711                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
712                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
713                 _tbm_bufmgr_mutex_unlock();
714                 return 0;
715         }
716
717         if (bo->lock_cnt > 0) {
718                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
719                 _tbm_bufmgr_mutex_unlock();
720                 return 1;
721         }
722
723         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
724         _tbm_bufmgr_mutex_unlock();
725
726         return 0;
727 }
728
729 int
730 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
731 {
732         tbm_error_e error1, error2;
733         int size1 = -1, size2 = -2;
734         void *temp;
735
736         _tbm_bufmgr_mutex_lock();
737         _tbm_set_last_result(TBM_ERROR_NONE);
738
739         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
740         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
741
742         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
743
744         size1 = tbm_module_bo_get_size(bo1->bufmgr->module, bo1, bo1->bo_data, &error1);
745         _tbm_set_last_result(error1);
746         size2 = tbm_module_bo_get_size(bo2->bufmgr->module, bo2, bo2->bo_data, &error2);
747         _tbm_set_last_result(error2);
748
749         if (size1 != size2) {
750                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
751                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
752                 goto fail;
753         }
754
755         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
756
757         temp = bo1->priv;
758         bo1->priv = bo2->priv;
759         bo2->priv = temp;
760
761         _tbm_bufmgr_mutex_unlock();
762
763         return 1;
764
765 fail:
766         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
767         _tbm_bufmgr_mutex_unlock();
768
769         return 0;
770 }
771
772 int
773 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
774                      tbm_data_free data_free_func)
775 {
776         tbm_user_data *data;
777
778         _tbm_bufmgr_mutex_lock();
779         _tbm_set_last_result(TBM_ERROR_NONE);
780
781         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
782
783         /* check if the data according to the key exist if so, return false. */
784         data = user_data_lookup(&bo->user_data_list, key);
785         if (data) {
786                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
787                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
788                 _tbm_bufmgr_mutex_unlock();
789                 return 0;
790         }
791
792         data = user_data_create(key, data_free_func);
793         if (!data) {
794                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
795                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
796                 _tbm_bufmgr_mutex_unlock();
797                 return 0;
798         }
799
800         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
801
802         LIST_ADD(&data->item_link, &bo->user_data_list);
803
804         _tbm_bufmgr_mutex_unlock();
805
806         return 1;
807 }
808
809 int
810 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
811 {
812         tbm_user_data *old_data;
813
814         _tbm_bufmgr_mutex_lock();
815         _tbm_set_last_result(TBM_ERROR_NONE);
816
817         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
818
819         if (LIST_IS_EMPTY(&bo->user_data_list)) {
820                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
821                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
822                 _tbm_bufmgr_mutex_unlock();
823                 return 0;
824         }
825
826         old_data = user_data_lookup(&bo->user_data_list, key);
827         if (!old_data) {
828                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
829                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
830                 _tbm_bufmgr_mutex_unlock();
831                 return 0;
832         }
833
834         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
835
836         user_data_delete(old_data);
837
838         _tbm_bufmgr_mutex_unlock();
839
840         return 1;
841 }
842
843 int
844 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
845 {
846         tbm_user_data *old_data;
847
848         _tbm_bufmgr_mutex_lock();
849         _tbm_set_last_result(TBM_ERROR_NONE);
850
851         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
852
853         if (LIST_IS_EMPTY(&bo->user_data_list)) {
854                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
855                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
856                 _tbm_bufmgr_mutex_unlock();
857                 return 0;
858         }
859
860         old_data = user_data_lookup(&bo->user_data_list, key);
861         if (!old_data) {
862                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
863                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
864                 _tbm_bufmgr_mutex_unlock();
865                 return 0;
866         }
867
868         if (old_data->data && old_data->free_func)
869                 old_data->free_func(old_data->data);
870         old_data->data = data;
871
872         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
873
874         _tbm_bufmgr_mutex_unlock();
875
876         return 1;
877 }
878
879 int
880 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
881 {
882         tbm_user_data *old_data;
883
884         _tbm_bufmgr_mutex_lock();
885         _tbm_set_last_result(TBM_ERROR_NONE);
886
887         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
888
889         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
890                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
891                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
892                 _tbm_bufmgr_mutex_unlock();
893                 return 0;
894         }
895
896         old_data = user_data_lookup(&bo->user_data_list, key);
897         if (!old_data) {
898                 *data = NULL;
899                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
900                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
901                 _tbm_bufmgr_mutex_unlock();
902                 return 0;
903         }
904
905         *data = old_data->data;
906
907         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
908
909         _tbm_bufmgr_mutex_unlock();
910
911         return 1;
912 }
913
914 int
915 tbm_bo_get_flags(tbm_bo bo)
916 {
917         int flags;
918
919         _tbm_bufmgr_mutex_lock();
920
921         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
922
923         flags = bo->flags;
924
925         TBM_TRACE_BO("bo(%p)\n", bo);
926
927         _tbm_bufmgr_mutex_unlock();
928
929         return flags;
930 }
931
932 /* LCOV_EXCL_START */
933 /* internal function */
934 int
935 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
936 {
937         _tbm_bufmgr_mutex_lock();
938
939         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
940
941         bo->surface = surface;
942
943         _tbm_bufmgr_mutex_unlock();
944
945         return 1;
946 }
947
948 void
949 _tbm_bo_free(tbm_bo bo)
950 {
951         /* destory the user_data_list */
952         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
953                 tbm_user_data *old_data = NULL, *tmp;
954
955                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
956                                 &bo->user_data_list, item_link) {
957                         TBM_DBG("free user_data\n");
958                         user_data_delete(old_data);
959                 }
960         }
961
962         while (bo->lock_cnt > 0) {
963                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
964                 _bo_unlock(bo);
965                 bo->lock_cnt--;
966         }
967
968         tbm_module_bo_free(bo->bufmgr->module, bo, bo->bo_data, bo->get_from_hal_surface);
969
970         _tbm_bo_deinit(bo);
971
972         free(bo);
973 }
974 /* LCOV_EXCL_STOP */