tbm_module: add tbm_module_bo_get_bo_handle 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         if (bo->bufmgr->use_hal_tbm) {
412                 hal_tbm_bo_handle hbo_handle;
413                 hbo_handle = hal_tbm_bo_map((hal_tbm_bo *)bo->bo_data, device, opt, (hal_tbm_error *)&error);
414                 if (hbo_handle.ptr == NULL) {
415                         /* LCOV_EXCL_START */
416                         _tbm_set_last_result(error);
417                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
418                         goto bo_map_fail;
419                         /* LCOV_EXCL_STOP */
420                 }
421                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
422         } else if (bo->bufmgr->backend_module_data) {
423                 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
424                 if (bo_handle.ptr == NULL) {
425                         /* LCOV_EXCL_START */
426                         _tbm_set_last_result(error);
427                         TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
428                         goto bo_map_fail;
429                         /* LCOV_EXCL_STOP */
430                 }
431         } else {
432                 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
433                 if (bo_handle.ptr == NULL) {
434                         /* LCOV_EXCL_START */
435                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
436                         TBM_ERR("error: fail to map bo:%p\n", bo);
437                         goto bo_map_fail;
438                         /* LCOV_EXCL_STOP */
439                 }
440         }
441
442         /* increase the map_count */
443         bo->map_cnt++;
444
445         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
446
447         _tbm_bufmgr_mutex_unlock();
448
449         return bo_handle;
450
451 bo_map_fail:
452         _tbm_bo_unlock(bo);
453         _tbm_bufmgr_mutex_unlock();
454         return (tbm_bo_handle) NULL;
455 }
456
457 int
458 tbm_bo_unmap(tbm_bo bo)
459 {
460         int ret = 1;
461         tbm_error_e error;
462
463         _tbm_bufmgr_mutex_lock();
464         _tbm_set_last_result(TBM_ERROR_NONE);
465
466         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
467         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
468
469         if (bo->bufmgr->use_hal_tbm) {
470                 error = (hal_tbm_error)hal_tbm_bo_unmap((hal_tbm_bo *)bo->bo_data);
471                 if (error != TBM_ERROR_NONE) {
472                         /* LCOV_EXCL_START */
473                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
474                         _tbm_set_last_result(error);
475                         ret = 0;
476                         goto done;
477                         /* LCOV_EXCL_STOP */
478                 }
479         } else if (bo->bufmgr->backend_module_data) {
480                 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
481                 if (error != TBM_ERROR_NONE) {
482                         /* LCOV_EXCL_START */
483                         TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
484                         _tbm_set_last_result(error);
485                         ret = 0;
486                         goto done;
487                         /* LCOV_EXCL_STOP */
488                 }
489         } else {
490                 ret = bo->bufmgr->backend->bo_unmap(bo);
491                 if (!ret) {
492                         /* LCOV_EXCL_START */
493                         TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
494                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
495                         goto done;
496                         /* LCOV_EXCL_STOP */
497                 }
498         }
499
500         /* decrease the map_count */
501         bo->map_cnt--;
502
503         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
504
505         _tbm_bo_unlock(bo);
506
507 done:
508         _tbm_bufmgr_mutex_unlock();
509
510         return ret;
511 }
512
513 tbm_bo_handle
514 tbm_bo_get_handle(tbm_bo bo, int device)
515 {
516         tbm_bo_handle bo_handle;
517         tbm_error_e error;
518
519         _tbm_bufmgr_mutex_lock();
520         _tbm_set_last_result(TBM_ERROR_NONE);
521
522         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
523
524         bo_handle = tbm_module_bo_get_handle(bo->bufmgr->module, bo, bo->bo_data, device, &error);
525         if (bo_handle.ptr == NULL) {
526                 /* LCOV_EXCL_START */
527                 TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
528                 _tbm_set_last_result(error);
529                 _tbm_bufmgr_mutex_unlock();
530                 return (tbm_bo_handle)NULL;
531                 /* LCOV_EXCL_STOP */
532         }
533
534         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
535
536         _tbm_bufmgr_mutex_unlock();
537
538         return bo_handle;
539 }
540
541 tbm_key
542 tbm_bo_export(tbm_bo bo)
543 {
544         tbm_key ret;
545         tbm_error_e error;
546
547         _tbm_bufmgr_mutex_lock();
548         _tbm_set_last_result(TBM_ERROR_NONE);
549
550         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
551
552         if (bo->bufmgr->use_hal_tbm) {
553                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
554                 if (!ret) {
555                         /* LCOV_EXCL_START */
556                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
557                         _tbm_set_last_result(error);
558                         goto done;
559                         /* LCOV_EXCL_STOP */
560                 }
561         } else if (bo->bufmgr->backend_module_data) {
562                 if (!bo->bufmgr->bo_func->bo_export_key) {
563                         /* LCOV_EXCL_START */
564                         _tbm_bufmgr_mutex_unlock();
565                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
566                         return 0;
567                         /* LCOV_EXCL_STOP */
568                 }
569
570                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
571                 if (!ret) {
572                         /* LCOV_EXCL_START */
573                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
574                         _tbm_set_last_result(error);
575                         goto done;
576                         /* LCOV_EXCL_STOP */
577                 }
578         } else {
579                 if (!bo->bufmgr->backend->bo_export) {
580                         /* LCOV_EXCL_START */
581                         _tbm_bufmgr_mutex_unlock();
582                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
583                         return 0;
584                         /* LCOV_EXCL_STOP */
585                 }
586
587                 ret = bo->bufmgr->backend->bo_export(bo);
588                 if (!ret) {
589                         /* LCOV_EXCL_START */
590                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
591                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
592                         goto done;
593                         /* LCOV_EXCL_STOP */
594                 }
595         }
596
597         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
598
599 done:
600         _tbm_bufmgr_mutex_unlock();
601
602         return ret;
603 }
604
605 tbm_fd
606 tbm_bo_export_fd(tbm_bo bo)
607 {
608         tbm_fd ret;
609         tbm_error_e error;
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), -1);
615
616         if (bo->bufmgr->use_hal_tbm) {
617                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
618                 if (ret < 0) {
619                         /* LCOV_EXCL_START */
620                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
621                         _tbm_set_last_result(error);
622                         goto done;
623                         /* LCOV_EXCL_STOP */
624                 }
625         } else if (bo->bufmgr->backend_module_data) {
626                 if (!bo->bufmgr->bo_func->bo_export_fd) {
627                         /* LCOV_EXCL_START */
628                         _tbm_bufmgr_mutex_unlock();
629                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
630                         return -1;
631                         /* LCOV_EXCL_STOP */
632                 }
633
634                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
635                 if (ret < 0) {
636                         /* LCOV_EXCL_START */
637                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
638                         _tbm_set_last_result(error);
639                         goto done;
640                         /* LCOV_EXCL_STOP */
641                 }
642         } else {
643                 if (!bo->bufmgr->backend->bo_export_fd) {
644                         /* LCOV_EXCL_START */
645                         _tbm_bufmgr_mutex_unlock();
646                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
647                         return -1;
648                         /* LCOV_EXCL_STOP */
649                 }
650
651                 ret = bo->bufmgr->backend->bo_export_fd(bo);
652                 if (ret < 0) {
653                         /* LCOV_EXCL_START */
654                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
655                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
656                         goto done;
657                         /* LCOV_EXCL_STOP */
658                 }
659         }
660
661         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
662
663 done:
664         _tbm_bufmgr_mutex_unlock();
665
666         return ret;
667 }
668
669 tbm_bo
670 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
671 {
672         tbm_bo bo;
673         tbm_error_e error;
674
675         _tbm_bufmgr_mutex_lock();
676         _tbm_set_last_result(TBM_ERROR_NONE);
677
678         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
679
680         bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key, &error);
681         if (!bo) {
682                 /* LCOV_EXCL_START */
683                 TBM_ERR("tbm_bufmgr_internal_import_key failed. error:%d", error);
684                 _tbm_set_last_result(error);
685                 _tbm_bufmgr_mutex_unlock();
686                 return NULL;
687                 /* LCOV_EXCL_STOP */
688         }
689
690         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
691                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
692
693         _tbm_bufmgr_mutex_unlock();
694
695         return bo;
696 }
697
698 tbm_bo
699 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
700 {
701         tbm_bo bo;
702         tbm_error_e error;
703
704         _tbm_bufmgr_mutex_lock();
705         _tbm_set_last_result(TBM_ERROR_NONE);
706
707         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
708
709         bo = tbm_bufmgr_internal_import_bo_with_fd(bufmgr, fd, &error);
710         if (!bo) {
711                 /* LCOV_EXCL_START */
712                 TBM_ERR("tbm_bufmgr_internal_import_fd failed. error:%d", error);
713                 _tbm_set_last_result(error);
714                 _tbm_bufmgr_mutex_unlock();
715                 return NULL;
716                 /* LCOV_EXCL_STOP */
717         }
718
719         LIST_INITHEAD(&bo->user_data_list); // TODO: remove this. build-break when it is removed.
720
721         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
722                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
723
724         _tbm_bufmgr_mutex_unlock();
725
726         return bo;
727 }
728
729 int
730 tbm_bo_size(tbm_bo bo)
731 {
732         int size;
733         tbm_error_e error;
734
735         _tbm_bufmgr_mutex_lock();
736         _tbm_set_last_result(TBM_ERROR_NONE);
737
738         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
739
740         size = tbm_module_bo_get_size(bo->bufmgr->module, bo, bo->bo_data, &error);
741         _tbm_set_last_result(error);
742
743         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
744
745         _tbm_bufmgr_mutex_unlock();
746
747         return size;
748 }
749
750 int
751 tbm_bo_locked(tbm_bo bo)
752 {
753         _tbm_bufmgr_mutex_lock();
754         _tbm_set_last_result(TBM_ERROR_NONE);
755
756         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
757
758         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
759                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
760                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
761                 _tbm_bufmgr_mutex_unlock();
762                 return 0;
763         }
764
765         if (bo->lock_cnt > 0) {
766                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
767                 _tbm_bufmgr_mutex_unlock();
768                 return 1;
769         }
770
771         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
772         _tbm_bufmgr_mutex_unlock();
773
774         return 0;
775 }
776
777 int
778 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
779 {
780         tbm_error_e error1, error2;
781         int size1 = -1, size2 = -2;
782         void *temp;
783
784         _tbm_bufmgr_mutex_lock();
785         _tbm_set_last_result(TBM_ERROR_NONE);
786
787         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
788         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
789
790         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
791
792         size1 = tbm_module_bo_get_size(bo1->bufmgr->module, bo1, bo1->bo_data, &error1);
793         _tbm_set_last_result(error1);
794         size2 = tbm_module_bo_get_size(bo2->bufmgr->module, bo2, bo2->bo_data, &error2);
795         _tbm_set_last_result(error2);
796
797         if (size1 != size2) {
798                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
799                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
800                 goto fail;
801         }
802
803         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
804
805         temp = bo1->priv;
806         bo1->priv = bo2->priv;
807         bo2->priv = temp;
808
809         _tbm_bufmgr_mutex_unlock();
810
811         return 1;
812
813 fail:
814         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
815         _tbm_bufmgr_mutex_unlock();
816
817         return 0;
818 }
819
820 int
821 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
822                      tbm_data_free data_free_func)
823 {
824         tbm_user_data *data;
825
826         _tbm_bufmgr_mutex_lock();
827         _tbm_set_last_result(TBM_ERROR_NONE);
828
829         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
830
831         /* check if the data according to the key exist if so, return false. */
832         data = user_data_lookup(&bo->user_data_list, key);
833         if (data) {
834                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
835                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
836                 _tbm_bufmgr_mutex_unlock();
837                 return 0;
838         }
839
840         data = user_data_create(key, data_free_func);
841         if (!data) {
842                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
843                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
844                 _tbm_bufmgr_mutex_unlock();
845                 return 0;
846         }
847
848         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
849
850         LIST_ADD(&data->item_link, &bo->user_data_list);
851
852         _tbm_bufmgr_mutex_unlock();
853
854         return 1;
855 }
856
857 int
858 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
859 {
860         tbm_user_data *old_data;
861
862         _tbm_bufmgr_mutex_lock();
863         _tbm_set_last_result(TBM_ERROR_NONE);
864
865         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
866
867         if (LIST_IS_EMPTY(&bo->user_data_list)) {
868                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
869                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
870                 _tbm_bufmgr_mutex_unlock();
871                 return 0;
872         }
873
874         old_data = user_data_lookup(&bo->user_data_list, key);
875         if (!old_data) {
876                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
877                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
878                 _tbm_bufmgr_mutex_unlock();
879                 return 0;
880         }
881
882         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
883
884         user_data_delete(old_data);
885
886         _tbm_bufmgr_mutex_unlock();
887
888         return 1;
889 }
890
891 int
892 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
893 {
894         tbm_user_data *old_data;
895
896         _tbm_bufmgr_mutex_lock();
897         _tbm_set_last_result(TBM_ERROR_NONE);
898
899         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
900
901         if (LIST_IS_EMPTY(&bo->user_data_list)) {
902                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
903                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
904                 _tbm_bufmgr_mutex_unlock();
905                 return 0;
906         }
907
908         old_data = user_data_lookup(&bo->user_data_list, key);
909         if (!old_data) {
910                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
911                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
912                 _tbm_bufmgr_mutex_unlock();
913                 return 0;
914         }
915
916         if (old_data->data && old_data->free_func)
917                 old_data->free_func(old_data->data);
918         old_data->data = data;
919
920         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
921
922         _tbm_bufmgr_mutex_unlock();
923
924         return 1;
925 }
926
927 int
928 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
929 {
930         tbm_user_data *old_data;
931
932         _tbm_bufmgr_mutex_lock();
933         _tbm_set_last_result(TBM_ERROR_NONE);
934
935         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
936
937         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
938                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
939                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
940                 _tbm_bufmgr_mutex_unlock();
941                 return 0;
942         }
943
944         old_data = user_data_lookup(&bo->user_data_list, key);
945         if (!old_data) {
946                 *data = NULL;
947                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
948                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
949                 _tbm_bufmgr_mutex_unlock();
950                 return 0;
951         }
952
953         *data = old_data->data;
954
955         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
956
957         _tbm_bufmgr_mutex_unlock();
958
959         return 1;
960 }
961
962 int
963 tbm_bo_get_flags(tbm_bo bo)
964 {
965         int flags;
966
967         _tbm_bufmgr_mutex_lock();
968
969         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
970
971         flags = bo->flags;
972
973         TBM_TRACE_BO("bo(%p)\n", bo);
974
975         _tbm_bufmgr_mutex_unlock();
976
977         return flags;
978 }
979
980 /* LCOV_EXCL_START */
981 /* internal function */
982 int
983 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
984 {
985         _tbm_bufmgr_mutex_lock();
986
987         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
988
989         bo->surface = surface;
990
991         _tbm_bufmgr_mutex_unlock();
992
993         return 1;
994 }
995
996 void
997 _tbm_bo_free(tbm_bo bo)
998 {
999         /* destory the user_data_list */
1000         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1001                 tbm_user_data *old_data = NULL, *tmp;
1002
1003                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1004                                 &bo->user_data_list, item_link) {
1005                         TBM_DBG("free user_data\n");
1006                         user_data_delete(old_data);
1007                 }
1008         }
1009
1010         while (bo->lock_cnt > 0) {
1011                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1012                 _bo_unlock(bo);
1013                 bo->lock_cnt--;
1014         }
1015
1016         tbm_module_bo_free(bo->bufmgr->module, bo, bo->bo_data, bo->get_from_hal_surface);
1017
1018         _tbm_bo_deinit(bo);
1019
1020         free(bo);
1021 }
1022 /* LCOV_EXCL_STOP */