error: add tbm_error.h
[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 static pthread_mutex_t tbm_bo_lock = PTHREAD_MUTEX_INITIALIZER;
38 static void _tbm_bo_mutex_unlock(void);
39
40 /* check condition */
41 #define TBM_BO_RETURN_IF_FAIL(cond) {\
42         if (!(cond)) {\
43                 TBM_ERR("'%s' failed.\n", #cond);\
44                 _tbm_bo_mutex_unlock();\
45                 return;\
46         } \
47 }
48
49 #define TBM_BO_RETURN_VAL_IF_FAIL(cond, val) {\
50         if (!(cond)) {\
51                 TBM_ERR("'%s' failed.\n", #cond);\
52                 _tbm_bo_mutex_unlock();\
53                 return val;\
54         } \
55 }
56
57 /* LCOV_EXCL_START */
58 static bool
59 _tbm_bo_mutex_init(void)
60 {
61         static bool tbm_bo_mutex_init = false;
62
63         if (tbm_bo_mutex_init)
64                 return true;
65
66         if (pthread_mutex_init(&tbm_bo_lock, NULL)) {
67                 TBM_ERR("fail: Cannot pthread_mutex_init for tbm_bo_lock.\n");
68                 return false;
69         }
70
71         tbm_bo_mutex_init = true;
72
73         return true;
74 }
75
76 static void
77 _tbm_bo_mutex_lock(void)
78 {
79         if (!_tbm_bo_mutex_init()) {
80                 TBM_ERR("fail: _tbm_bo_mutex_init()\n");
81                 return;
82         }
83
84         pthread_mutex_lock(&tbm_bo_lock);
85 }
86
87 static void
88 _tbm_bo_mutex_unlock(void)
89 {
90         pthread_mutex_unlock(&tbm_bo_lock);
91 }
92
93 static char *
94 _tbm_flag_to_str(int f)
95 {
96         static char str[255];
97
98         if (f == TBM_BO_DEFAULT)
99                  snprintf(str, 255, "DEFAULT");
100         else {
101                 int c = 0;
102
103                 if (f & TBM_BO_SCANOUT)
104                         c += snprintf(&str[c], 255-c, "SCANOUT");
105
106                 if (f & TBM_BO_NONCACHABLE) {
107                         if (c >= 0 && c < 255)
108                                 c += snprintf(&str[c], 255-c, ", ");
109
110                         if (c >= 0 && c < 255)
111                                 c += snprintf(&str[c], 255-c, "NONCACHABLE,");
112                 }
113
114                 if (f & TBM_BO_WC) {
115                         if (c >= 0 && c < 255)
116                                 c += snprintf(&str[c], 255-c, ", ");
117
118                         if (c >= 0 && c < 255)
119                                 c += snprintf(&str[c], 255-c, "WC");
120                 }
121         }
122
123         return str;
124 }
125
126 static void
127 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
128 {
129         static int last_chk_bo_cnt = 0;
130
131         if ((bufmgr->bo_cnt >= 500) && ((bufmgr->bo_cnt % 20) == 0) &&
132                 (bufmgr->bo_cnt > last_chk_bo_cnt)) {
133                 TBM_DBG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
134                 tbm_bufmgr_debug_show(bufmgr);
135                 last_chk_bo_cnt = bufmgr->bo_cnt;
136         }
137 }
138 /* LCOV_EXCL_STOP */
139
140 tbm_user_data
141 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
142 {
143         tbm_user_data *old_data = NULL;
144
145         if (LIST_IS_EMPTY(user_data_list))
146                 return NULL;
147
148         LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
149                 if (old_data->key == key)
150                         return old_data;
151         }
152
153         return NULL;
154 }
155
156 tbm_user_data
157 *user_data_create(unsigned long key, tbm_data_free data_free_func)
158 {
159         tbm_user_data *user_data;
160
161         user_data = calloc(1, sizeof(tbm_user_data));
162         if (!user_data) {
163                 /* LCOV_EXCL_START */
164                 TBM_ERR("fail to allocate an user_date\n");
165                 return NULL;
166                 /* LCOV_EXCL_STOP */
167         }
168
169         user_data->key = key;
170         user_data->free_func = data_free_func;
171
172         return user_data;
173 }
174
175 void
176 user_data_delete(tbm_user_data *user_data)
177 {
178         if (user_data->data && user_data->free_func)
179                 user_data->free_func(user_data->data);
180
181         LIST_DEL(&user_data->item_link);
182
183         free(user_data);
184 }
185
186 static int
187 _bo_lock(tbm_bo bo, int device, int opt)
188 {
189         int ret = 1;
190         tbm_error_e error;
191
192         if (bo->bufmgr->backend_module_data) {
193                 if (bo->bufmgr->bo_func->bo_lock) {
194                         error = bo->bufmgr->bo_func->bo_lock(bo->bo_data, device, opt);
195                         if (error != TBM_ERROR_NONE) {
196                                 TBM_WRN("fail to lock");
197                                 ret = 0;
198                         }
199                 }
200         } else {
201                 if (bo->bufmgr->backend->bo_lock)
202                         ret = bo->bufmgr->backend->bo_lock(bo, device, opt);
203         }
204
205         return ret;
206 }
207
208 static void
209 _bo_unlock(tbm_bo bo)
210 {
211         tbm_error_e error;
212
213         if (bo->bufmgr->backend_module_data) {
214                 if (bo->bufmgr->bo_func->bo_unlock) {
215                         error = bo->bufmgr->bo_func->bo_unlock(bo->bo_data);
216                         if (error != TBM_ERROR_NONE)
217                                 TBM_WRN("fail to unlock");
218                 }
219         } else {
220                 if (bo->bufmgr->backend->bo_unlock)
221                         bo->bufmgr->backend->bo_unlock(bo);
222         }
223 }
224
225 static int
226 _tbm_bo_lock(tbm_bo bo, int device, int opt)
227 {
228         int old, ret;
229
230         if (!bo)
231                 return 0;
232
233         /* do not try to lock the bo */
234         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
235                 return 1;
236
237         if (bo->lock_cnt < 0) {
238                 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
239                         bo, bo->lock_cnt);
240                 return 0;
241         }
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                         _tbm_bo_mutex_unlock();
249                         ret = _bo_lock(bo, device, opt);
250                         _tbm_bo_mutex_lock();
251                         if (ret)
252                                 bo->lock_cnt++;
253                 } else
254                         ret = 1;
255                 break;
256         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
257                 _tbm_bo_mutex_unlock();
258                 ret = _bo_lock(bo, device, opt);
259                 _tbm_bo_mutex_lock();
260                 if (ret)
261                         bo->lock_cnt++;
262                 break;
263         default:
264                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
265                                 bo, bo->bufmgr->bo_lock_type);
266                 ret = 0;
267                 break;
268         }
269
270         TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
271
272         return ret;
273 }
274
275 static void
276 _tbm_bo_unlock(tbm_bo bo)
277 {
278         int old;
279
280         /* do not try to unlock the bo */
281         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
282                 return;
283
284         old = bo->lock_cnt;
285
286         switch (bo->bufmgr->bo_lock_type) {
287         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
288                 if (bo->lock_cnt > 0) {
289                         bo->lock_cnt--;
290                         if (bo->lock_cnt == 0)
291                                 _bo_unlock(bo);
292                 }
293                 break;
294         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
295                 if (bo->lock_cnt > 0) {
296                         bo->lock_cnt--;
297                         _bo_unlock(bo);
298                 }
299                 break;
300         default:
301                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
302                                 bo, bo->bufmgr->bo_lock_type);
303                 break;
304         }
305
306         if (bo->lock_cnt < 0)
307                 bo->lock_cnt = 0;
308
309         TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
310 }
311
312 static int
313 _tbm_bo_is_valid(tbm_bo bo)
314 {
315         tbm_bufmgr bufmgr = NULL;
316         tbm_bo old_data = NULL;
317
318         if (bo == NULL) {
319                 TBM_ERR("error: bo is NULL.\n");
320                 return 0;
321         }
322
323         bufmgr = tbm_bufmgr_get();
324         if (bufmgr == NULL) {
325                 TBM_ERR("error: bufmgr is NULL.\n");
326                 return 0;
327         }
328
329         if (LIST_IS_EMPTY(&bufmgr->bo_list)) {
330                 TBM_ERR("error: bo->bo->bufmgr->bo_list is EMPTY.\n");
331                 return 0;
332         }
333
334         LIST_FOR_EACH_ENTRY(old_data, &bufmgr->bo_list, item_link) {
335                 if (old_data == bo)
336                         return 1;
337         }
338
339         TBM_ERR("error: No valid bo(%p).\n", bo);
340
341         return 0;
342 }
343
344 tbm_bo
345 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
346 {
347         tbm_bo bo;
348         void *bo_priv;
349         tbm_backend_bo_data *bo_data;
350         tbm_error_e error;
351
352         _tbm_bo_mutex_lock();
353
354         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
355         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
356
357         bo = calloc(1, sizeof(struct _tbm_bo));
358         if (!bo) {
359                 /* LCOV_EXCL_START */
360                 TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n",
361                                 size, _tbm_flag_to_str(flags));
362                 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
363                 _tbm_bo_mutex_unlock();
364                 return NULL;
365                 /* LCOV_EXCL_STOP */
366         }
367
368         _tbm_util_check_bo_cnt(bufmgr);
369
370         bo->bufmgr = bufmgr;
371
372         if (bufmgr->backend_module_data) {
373                 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo(bufmgr->bufmgr_data, (unsigned int)size, flags, &error);
374                 if (!bo_data) {
375                         /* LCOV_EXCL_START */
376                         TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n",
377                                         size, _tbm_flag_to_str(flags));
378                         _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
379                         free(bo);
380                         _tbm_bo_mutex_unlock();
381                         return NULL;
382                         /* LCOV_EXCL_STOP */
383                 }
384                 bo->bo_data = bo_data;
385         } else {
386                 bo_priv = bo->bufmgr->backend->bo_alloc(bo, size, flags);
387                 if (!bo_priv) {
388                         /* LCOV_EXCL_START */
389                         TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n",
390                                         size, _tbm_flag_to_str(flags));
391                         _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
392                         free(bo);
393                         _tbm_bo_mutex_unlock();
394                         return NULL;
395                         /* LCOV_EXCL_STOP */
396                 }
397                 bo->priv = bo_priv;
398         }
399
400         bo->bufmgr->bo_cnt++;
401         bo->ref_cnt = 1;
402         bo->flags = flags;
403
404         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
405                         _tbm_flag_to_str(bo->flags));
406
407         LIST_INITHEAD(&bo->user_data_list);
408
409         LIST_ADD(&bo->item_link, &bo->bufmgr->bo_list);
410
411         _tbm_bo_mutex_unlock();
412
413         return bo;
414 }
415
416 tbm_bo
417 tbm_bo_ref(tbm_bo bo)
418 {
419         _tbm_bo_mutex_lock();
420
421         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
422
423         bo->ref_cnt++;
424
425         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
426
427         _tbm_bo_mutex_unlock();
428
429         return bo;
430 }
431
432 void
433 tbm_bo_unref(tbm_bo bo)
434 {
435         _tbm_bo_mutex_lock();
436
437         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
438
439         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
440
441         if (bo->ref_cnt <= 0) {
442                 _tbm_bo_mutex_unlock();
443                 return;
444         }
445
446         bo->ref_cnt--;
447         if (bo->ref_cnt == 0)
448                 _tbm_bo_free(bo);
449
450         _tbm_bo_mutex_unlock();
451 }
452
453 tbm_bo_handle
454 tbm_bo_map(tbm_bo bo, int device, int opt)
455 {
456         tbm_bo_handle bo_handle;
457         tbm_error_e error;
458
459         _tbm_bo_mutex_lock();
460
461         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
462
463         if (!_tbm_bo_lock(bo, device, opt)) {
464                 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
465                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
466                 _tbm_bo_mutex_unlock();
467                 return (tbm_bo_handle) NULL;
468         }
469
470         if (bo->bufmgr->backend_module_data) {
471                 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
472                 if (bo_handle.ptr == NULL) {
473                         /* LCOV_EXCL_START */
474                         _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
475                         TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
476                         _tbm_bo_unlock(bo);
477                         _tbm_bo_mutex_unlock();
478                         return (tbm_bo_handle) NULL;
479                         /* LCOV_EXCL_STOP */
480                 }
481         } else {
482                 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
483                 if (bo_handle.ptr == NULL) {
484                         /* LCOV_EXCL_START */
485                         _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
486                         TBM_ERR("error: fail to map bo:%p\n", bo);
487                         _tbm_bo_unlock(bo);
488                         _tbm_bo_mutex_unlock();
489                         return (tbm_bo_handle) NULL;
490                         /* LCOV_EXCL_STOP */
491                 }
492         }
493
494         /* increase the map_count */
495         bo->map_cnt++;
496
497         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
498
499         _tbm_bo_mutex_unlock();
500
501         return bo_handle;
502 }
503
504 int
505 tbm_bo_unmap(tbm_bo bo)
506 {
507         int ret = 1;
508         tbm_error_e error;
509
510         _tbm_bo_mutex_lock();
511
512         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
513         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
514
515         if (bo->bufmgr->backend_module_data) {
516                 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
517                 if (error != TBM_ERROR_NONE) {
518                         /* LCOV_EXCL_START */
519                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
520                         _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
521                         ret = 0;
522                         _tbm_bo_mutex_unlock();
523                         return ret;
524                         /* LCOV_EXCL_STOP */
525                 }
526         } else {
527                 ret = bo->bufmgr->backend->bo_unmap(bo);
528                 if (!ret) {
529                         /* LCOV_EXCL_START */
530                         TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
531                         _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
532                         _tbm_bo_mutex_unlock();
533                         return ret;
534                         /* LCOV_EXCL_STOP */
535                 }
536         }
537
538         /* decrease the map_count */
539         bo->map_cnt--;
540
541         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
542
543         _tbm_bo_unlock(bo);
544
545         _tbm_bo_mutex_unlock();
546
547         return ret;
548 }
549
550 tbm_bo_handle
551 tbm_bo_get_handle(tbm_bo bo, int device)
552 {
553         tbm_bo_handle bo_handle;
554         tbm_error_e error;
555
556         _tbm_bo_mutex_lock();
557
558         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
559
560         if (bo->bufmgr->backend_module_data) {
561                 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
562                 if (bo_handle.ptr == NULL) {
563                         /* LCOV_EXCL_START */
564                         _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
565                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
566                         _tbm_bo_mutex_unlock();
567                         return (tbm_bo_handle) NULL;
568                         /* LCOV_EXCL_STOP */
569                 }
570         } else {
571                 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
572                 if (bo_handle.ptr == NULL) {
573                         /* LCOV_EXCL_START */
574                         _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
575                         TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
576                         _tbm_bo_mutex_unlock();
577                         return (tbm_bo_handle) NULL;
578                         /* LCOV_EXCL_STOP */
579                 }
580         }
581
582         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
583
584         _tbm_bo_mutex_unlock();
585
586         return bo_handle;
587 }
588
589 tbm_key
590 tbm_bo_export(tbm_bo bo)
591 {
592         tbm_key ret;
593         tbm_error_e error;
594
595         _tbm_bo_mutex_lock();
596
597         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
598
599         if (bo->bufmgr->backend_module_data) {
600                 if (!bo->bufmgr->bo_func->bo_export_key) {
601                         /* LCOV_EXCL_START */
602                         _tbm_bo_mutex_unlock();
603                         return 0;
604                         /* LCOV_EXCL_STOP */
605                 }
606
607                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
608                 if (!ret) {
609                         /* LCOV_EXCL_START */
610                         _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
611                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
612                         _tbm_bo_mutex_unlock();
613                         return ret;
614                         /* LCOV_EXCL_STOP */
615                 }
616         } else {
617                 if (!bo->bufmgr->backend->bo_export) {
618                         /* LCOV_EXCL_START */
619                         _tbm_bo_mutex_unlock();
620                         return 0;
621                         /* LCOV_EXCL_STOP */
622                 }
623
624                 ret = bo->bufmgr->backend->bo_export(bo);
625                 if (!ret) {
626                         /* LCOV_EXCL_START */
627                         _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
628                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
629                         _tbm_bo_mutex_unlock();
630                         return ret;
631                         /* LCOV_EXCL_STOP */
632                 }
633         }
634
635         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
636
637         _tbm_bo_mutex_unlock();
638
639         return ret;
640 }
641
642 tbm_fd
643 tbm_bo_export_fd(tbm_bo bo)
644 {
645         tbm_fd ret;
646         tbm_error_e error;
647
648         _tbm_bo_mutex_lock();
649
650         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
651
652         if (bo->bufmgr->backend_module_data) {
653                 if (!bo->bufmgr->bo_func->bo_export_fd) {
654                         /* LCOV_EXCL_START */
655                         _tbm_bo_mutex_unlock();
656                         return -1;
657                         /* LCOV_EXCL_STOP */
658                 }
659
660                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
661                 if (ret < 0) {
662                         /* LCOV_EXCL_START */
663                         _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
664                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
665                         _tbm_bo_mutex_unlock();
666                         return ret;
667                         /* LCOV_EXCL_STOP */
668                 }
669         } else {
670                 if (!bo->bufmgr->backend->bo_export_fd) {
671                         /* LCOV_EXCL_START */
672                         _tbm_bo_mutex_unlock();
673                         return -1;
674                         /* LCOV_EXCL_STOP */
675                 }
676
677                 ret = bo->bufmgr->backend->bo_export_fd(bo);
678                 if (ret < 0) {
679                         /* LCOV_EXCL_START */
680                         _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
681                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
682                         _tbm_bo_mutex_unlock();
683                         return ret;
684                         /* LCOV_EXCL_STOP */
685                 }
686         }
687
688         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
689
690         _tbm_bo_mutex_unlock();
691
692         return ret;
693 }
694
695 tbm_bo
696 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
697 {
698         tbm_bo bo;
699         tbm_bo bo2 = NULL;
700         void *bo_priv;
701         tbm_error_e error;
702         tbm_backend_bo_data *bo_data;
703
704         _tbm_bo_mutex_lock();
705
706         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
707
708         if (bufmgr->backend_module_data) {
709                 if (!bufmgr->bufmgr_func->bufmgr_import_key) {
710                         /* LCOV_EXCL_START */
711                         _tbm_bo_mutex_unlock();
712                         return NULL;
713                         /* LCOV_EXCL_STOP */
714                 }
715         } else {
716                 if (!bufmgr->backend->bo_import) {
717                         /* LCOV_EXCL_START */
718                         _tbm_bo_mutex_unlock();
719                         return NULL;
720                         /* LCOV_EXCL_STOP */
721                 }
722         }
723
724         _tbm_util_check_bo_cnt(bufmgr);
725
726         bo = calloc(1, sizeof(struct _tbm_bo));
727         if (!bo) {
728                 /* LCOV_EXCL_START */
729                 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
730                 _tbm_bo_mutex_unlock();
731                 return NULL;
732                 /* LCOV_EXCL_STOP */
733         }
734
735         bo->bufmgr = bufmgr;
736
737         if (bo->bufmgr->backend_module_data) {
738                 bo_data = bo->bufmgr->bufmgr_func->bufmgr_import_key(bufmgr->bufmgr_data, key, &error);
739                 if (!bo_data) {
740                         /* LCOV_EXCL_START */
741                         TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
742                         _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
743                         free(bo);
744                         _tbm_bo_mutex_unlock();
745                         return NULL;
746                         /* LCOV_EXCL_STOP */
747                 }
748
749                 if (!LIST_IS_EMPTY(&bo->bufmgr->bo_list)) {
750                         LIST_FOR_EACH_ENTRY(bo2, &bo->bufmgr->bo_list, item_link) {
751                                 if (bo2->bo_data == bo_data) {
752                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
753                                                         bo2, bo2->ref_cnt, key,
754                                                         _tbm_flag_to_str(bo2->flags));
755                                         bo2->ref_cnt++;
756                                         free(bo);
757                                         _tbm_bo_mutex_unlock();
758                                         return bo2;
759                                 }
760                         }
761                 }
762                 bo->bo_data = bo_data;
763         } else {
764                 bo_priv = bo->bufmgr->backend->bo_import(bo, key);
765                 if (!bo_priv) {
766                         /* LCOV_EXCL_START */
767                         TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
768                         _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
769                         free(bo);
770                         _tbm_bo_mutex_unlock();
771                         return NULL;
772                         /* LCOV_EXCL_STOP */
773                 }
774
775                 if (!LIST_IS_EMPTY(&bo->bufmgr->bo_list)) {
776                         LIST_FOR_EACH_ENTRY(bo2, &bo->bufmgr->bo_list, item_link) {
777                                 if (bo2->priv == bo_priv) {
778                                         TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
779                                                         bo2, bo2->ref_cnt, key,
780                                                         _tbm_flag_to_str(bo2->flags));
781                                         bo2->ref_cnt++;
782                                         free(bo);
783                                         _tbm_bo_mutex_unlock();
784                                         return bo2;
785                                 }
786                         }
787                 }
788                 bo->priv = bo_priv;
789         }
790
791         bo->bufmgr->bo_cnt++;
792         bo->ref_cnt = 1;
793
794         if (bo->bufmgr->backend_module_data) {
795                 bo->flags = bo->bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
796                 if (error != TBM_ERROR_NONE) {
797                         TBM_ERR("fail to get the bo flags(memory_types)");
798                         bo->flags = TBM_BO_DEFAULT;
799                 }
800         } else {
801                 if (bo->bufmgr->backend->bo_get_flags)
802                         bo->flags = bo->bufmgr->backend->bo_get_flags(bo);
803                 else
804                         bo->flags = TBM_BO_DEFAULT;
805         }
806
807         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
808                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
809
810         LIST_INITHEAD(&bo->user_data_list);
811
812         LIST_ADD(&bo->item_link, &bo->bufmgr->bo_list);
813
814         _tbm_bo_mutex_unlock();
815
816         return bo;
817 }
818
819 tbm_bo
820 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
821 {
822         tbm_bo bo;
823         tbm_bo bo2 = NULL;
824         void *bo_priv;
825         tbm_backend_bo_data *bo_data;
826         tbm_error_e error;
827
828         _tbm_bo_mutex_lock();
829
830         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
831
832         if (bufmgr->backend_module_data) {
833                 if (!bufmgr->bufmgr_func->bufmgr_import_fd) {
834                         /* LCOV_EXCL_START */
835                         _tbm_bo_mutex_unlock();
836                         return NULL;
837                         /* LCOV_EXCL_STOP */
838                 }
839         } else {
840                 if (!bufmgr->backend->bo_import_fd) {
841                         /* LCOV_EXCL_START */
842                         _tbm_bo_mutex_unlock();
843                         return NULL;
844                         /* LCOV_EXCL_STOP */
845                 }
846         }
847
848         _tbm_util_check_bo_cnt(bufmgr);
849
850         bo = calloc(1, sizeof(struct _tbm_bo));
851         if (!bo) {
852                 /* LCOV_EXCL_START */
853                 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
854                 _tbm_bo_mutex_unlock();
855                 return NULL;
856                 /* LCOV_EXCL_STOP */
857         }
858
859         bo->bufmgr = bufmgr;
860
861         if (bo->bufmgr->backend_module_data) {
862                 bo_data = bo->bufmgr->bufmgr_func->bufmgr_import_fd(bufmgr->bufmgr_data, fd, &error);
863                 if (!bo_data) {
864                         /* LCOV_EXCL_START */
865                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
866                         _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
867                         free(bo);
868                         _tbm_bo_mutex_unlock();
869                         return NULL;
870                         /* LCOV_EXCL_STOP */
871                 }
872
873                 if (!LIST_IS_EMPTY(&bo->bufmgr->bo_list)) {
874                         LIST_FOR_EACH_ENTRY(bo2, &bo->bufmgr->bo_list, item_link) {
875                                 if (bo2->bo_data == bo_data) {
876                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
877                                                         bo2, bo2->ref_cnt, fd,
878                                                         _tbm_flag_to_str(bo2->flags));
879                                         bo2->ref_cnt++;
880                                         free(bo);
881                                         _tbm_bo_mutex_unlock();
882                                         return bo2;
883                                 }
884                         }
885                 }
886                 bo->bo_data = bo_data;
887         } else {
888                 bo_priv = bo->bufmgr->backend->bo_import_fd(bo, fd);
889                 if (!bo_priv) {
890                         /* LCOV_EXCL_START */
891                         TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
892                         _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
893                         free(bo);
894                         _tbm_bo_mutex_unlock();
895                         return NULL;
896                         /* LCOV_EXCL_STOP */
897                 }
898
899                 if (!LIST_IS_EMPTY(&bo->bufmgr->bo_list)) {
900                         LIST_FOR_EACH_ENTRY(bo2, &bo->bufmgr->bo_list, item_link) {
901                                 if (bo2->priv == bo_priv) {
902                                         TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
903                                                         bo2, bo2->ref_cnt, fd,
904                                                         _tbm_flag_to_str(bo2->flags));
905                                         bo2->ref_cnt++;
906                                         free(bo);
907                                         _tbm_bo_mutex_unlock();
908                                         return bo2;
909                                 }
910                         }
911                 }
912                 bo->priv = bo_priv;
913         }
914
915         bo->bufmgr->bo_cnt++;
916         bo->ref_cnt = 1;
917
918         if (bo->bufmgr->backend_module_data) {
919                 bo->flags = bo->bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
920                 if (error != TBM_ERROR_NONE) {
921                         TBM_ERR("fail to get the bo flags(memory_types)");
922                         bo->flags = TBM_BO_DEFAULT;
923                 }
924         } else {
925                 if (bo->bufmgr->backend->bo_get_flags)
926                         bo->flags = bo->bufmgr->backend->bo_get_flags(bo);
927                 else
928                         bo->flags = TBM_BO_DEFAULT;
929         }
930
931         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
932                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
933
934         LIST_INITHEAD(&bo->user_data_list);
935
936         LIST_ADD(&bo->item_link, &bo->bufmgr->bo_list);
937
938         _tbm_bo_mutex_unlock();
939
940         return bo;
941 }
942
943 int
944 tbm_bo_size(tbm_bo bo)
945 {
946         int size;
947         tbm_error_e error;
948
949         _tbm_bo_mutex_lock();
950
951         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
952
953         if (bo->bufmgr->backend_module_data) {
954                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
955                 if (error != TBM_ERROR_NONE)
956                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
957         } else
958                 size = bo->bufmgr->backend->bo_size(bo);
959
960         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
961
962         _tbm_bo_mutex_unlock();
963
964         return size;
965 }
966
967 int
968 tbm_bo_locked(tbm_bo bo)
969 {
970         _tbm_bo_mutex_lock();
971
972         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
973
974         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
975                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
976                 _tbm_bo_mutex_unlock();
977                 return 0;
978         }
979
980         if (bo->lock_cnt > 0) {
981                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
982                 _tbm_bo_mutex_unlock();
983                 return 1;
984         }
985
986         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
987         _tbm_bo_mutex_unlock();
988
989         return 0;
990 }
991
992 int
993 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
994 {
995         tbm_error_e error1, error2;
996         int size1 = -1, size2 = -2;
997         void *temp;
998
999         _tbm_bo_mutex_lock();
1000
1001         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1002         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1003
1004         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1005
1006         if (bo1->bufmgr->backend_module_data) {
1007                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
1008                 if (error1 != TBM_ERROR_NONE) {
1009                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
1010                         goto fail;
1011                 }
1012                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
1013                 if (error2 != TBM_ERROR_NONE) {
1014                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
1015                         goto fail;
1016                 }
1017         } else {
1018                 size1 = bo1->bufmgr->backend->bo_size(bo1);
1019                 size2 = bo2->bufmgr->backend->bo_size(bo2);
1020         }
1021
1022         if (size1 != size2) {
1023                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
1024                 goto fail;
1025         }
1026
1027         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1028
1029         temp = bo1->priv;
1030         bo1->priv = bo2->priv;
1031         bo2->priv = temp;
1032
1033         _tbm_bo_mutex_unlock();
1034
1035         return 1;
1036
1037 fail:
1038         _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1039         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1040         _tbm_bo_mutex_unlock();
1041
1042         return 0;
1043 }
1044
1045 int
1046 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1047                      tbm_data_free data_free_func)
1048 {
1049         tbm_user_data *data;
1050
1051         _tbm_bo_mutex_lock();
1052
1053         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1054
1055         /* check if the data according to the key exist if so, return false. */
1056         data = user_data_lookup(&bo->user_data_list, key);
1057         if (data) {
1058                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1059                 _tbm_bo_mutex_unlock();
1060                 return 0;
1061         }
1062
1063         data = user_data_create(key, data_free_func);
1064         if (!data) {
1065                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1066                 _tbm_bo_mutex_unlock();
1067                 return 0;
1068         }
1069
1070         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1071
1072         LIST_ADD(&data->item_link, &bo->user_data_list);
1073
1074         _tbm_bo_mutex_unlock();
1075
1076         return 1;
1077 }
1078
1079 int
1080 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1081 {
1082         tbm_user_data *old_data;
1083
1084         _tbm_bo_mutex_lock();
1085
1086         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1087
1088         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1089                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1090                 _tbm_bo_mutex_unlock();
1091                 return 0;
1092         }
1093
1094         old_data = user_data_lookup(&bo->user_data_list, key);
1095         if (!old_data) {
1096                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1097                 _tbm_bo_mutex_unlock();
1098                 return 0;
1099         }
1100
1101         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1102
1103         user_data_delete(old_data);
1104
1105         _tbm_bo_mutex_unlock();
1106
1107         return 1;
1108 }
1109
1110 int
1111 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1112 {
1113         tbm_user_data *old_data;
1114
1115         _tbm_bo_mutex_lock();
1116
1117         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1118
1119         if (LIST_IS_EMPTY(&bo->user_data_list)) {
1120                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1121                 _tbm_bo_mutex_unlock();
1122                 return 0;
1123         }
1124
1125         old_data = user_data_lookup(&bo->user_data_list, key);
1126         if (!old_data) {
1127                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1128                 _tbm_bo_mutex_unlock();
1129                 return 0;
1130         }
1131
1132         if (old_data->data && old_data->free_func)
1133                 old_data->free_func(old_data->data);
1134         old_data->data = data;
1135
1136         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1137
1138         _tbm_bo_mutex_unlock();
1139
1140         return 1;
1141 }
1142
1143 int
1144 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1145 {
1146         tbm_user_data *old_data;
1147
1148         _tbm_bo_mutex_lock();
1149
1150         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1151
1152         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1153                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1154                 _tbm_bo_mutex_unlock();
1155                 return 0;
1156         }
1157
1158         old_data = user_data_lookup(&bo->user_data_list, key);
1159         if (!old_data) {
1160                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1161                 *data = NULL;
1162                 _tbm_bo_mutex_unlock();
1163                 return 0;
1164         }
1165
1166         *data = old_data->data;
1167
1168         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1169
1170         _tbm_bo_mutex_unlock();
1171
1172         return 1;
1173 }
1174
1175 int
1176 tbm_bo_get_flags(tbm_bo bo)
1177 {
1178         int flags;
1179
1180         _tbm_bo_mutex_lock();
1181
1182         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1183
1184         flags = bo->flags;
1185
1186         TBM_TRACE_BO("bo(%p)\n", bo);
1187
1188         _tbm_bo_mutex_unlock();
1189
1190         return flags;
1191 }
1192
1193 /* LCOV_EXCL_START */
1194 /* internal function */
1195 int
1196 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1197 {
1198         _tbm_bo_mutex_lock();
1199
1200         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1201
1202         bo->surface = surface;
1203
1204         _tbm_bo_mutex_unlock();
1205
1206         return 1;
1207 }
1208
1209 void
1210 _tbm_bo_free(tbm_bo bo)
1211 {
1212         /* destory the user_data_list */
1213         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1214                 tbm_user_data *old_data = NULL, *tmp;
1215
1216                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1217                                 &bo->user_data_list, item_link) {
1218                         TBM_DBG("free user_data\n");
1219                         user_data_delete(old_data);
1220                 }
1221         }
1222
1223         while (bo->lock_cnt > 0) {
1224                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1225                 _bo_unlock(bo);
1226                 bo->lock_cnt--;
1227         }
1228
1229         /* call the bo_free */
1230         if (bo->bufmgr->backend_module_data) {
1231                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1232                 bo->bo_data = NULL;
1233         } else {
1234                 bo->bufmgr->backend->bo_free(bo);
1235                 bo->priv = NULL;
1236         }
1237
1238         bo->bufmgr->bo_cnt--;
1239
1240         LIST_DEL(&bo->item_link);
1241         free(bo);
1242 }
1243 /* LCOV_EXCL_STOP */