tbm_bufmgr: add tbm_bufmgr_internal_import_bo_with_fd 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         if (bo->bufmgr->use_hal_tbm) {
525                 hal_tbm_bo_handle hbo_handle;
526                 hbo_handle = hal_tbm_bo_get_handle((hal_tbm_bo *)bo->bo_data, device, (hal_tbm_error *)&error);
527                 if (hbo_handle.ptr == NULL) {
528                         /* LCOV_EXCL_START */
529                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, hbo_handle.ptr, error);
530                         _tbm_set_last_result(error);
531                         goto bo_handle_fail;
532                         /* LCOV_EXCL_STOP */
533                 }
534                 memcpy(&bo_handle.ptr, &hbo_handle.ptr, sizeof(tbm_bo_handle));
535         } else if (bo->bufmgr->backend_module_data) {
536                 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
537                 if (bo_handle.ptr == NULL) {
538                         /* LCOV_EXCL_START */
539                         TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
540                         _tbm_set_last_result(error);
541                         goto bo_handle_fail;
542                         /* LCOV_EXCL_STOP */
543                 }
544         } else {
545                 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
546                 if (bo_handle.ptr == NULL) {
547                         /* LCOV_EXCL_START */
548                         TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
549                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
550                         goto bo_handle_fail;
551                         /* LCOV_EXCL_STOP */
552                 }
553         }
554
555         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
556
557         _tbm_bufmgr_mutex_unlock();
558
559         return bo_handle;
560
561 bo_handle_fail:
562         _tbm_bufmgr_mutex_unlock();
563         return (tbm_bo_handle) NULL;
564 }
565
566 tbm_key
567 tbm_bo_export(tbm_bo bo)
568 {
569         tbm_key ret;
570         tbm_error_e error;
571
572         _tbm_bufmgr_mutex_lock();
573         _tbm_set_last_result(TBM_ERROR_NONE);
574
575         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
576
577         if (bo->bufmgr->use_hal_tbm) {
578                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
579                 if (!ret) {
580                         /* LCOV_EXCL_START */
581                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
582                         _tbm_set_last_result(error);
583                         goto done;
584                         /* LCOV_EXCL_STOP */
585                 }
586         } else if (bo->bufmgr->backend_module_data) {
587                 if (!bo->bufmgr->bo_func->bo_export_key) {
588                         /* LCOV_EXCL_START */
589                         _tbm_bufmgr_mutex_unlock();
590                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
591                         return 0;
592                         /* LCOV_EXCL_STOP */
593                 }
594
595                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
596                 if (!ret) {
597                         /* LCOV_EXCL_START */
598                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
599                         _tbm_set_last_result(error);
600                         goto done;
601                         /* LCOV_EXCL_STOP */
602                 }
603         } else {
604                 if (!bo->bufmgr->backend->bo_export) {
605                         /* LCOV_EXCL_START */
606                         _tbm_bufmgr_mutex_unlock();
607                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
608                         return 0;
609                         /* LCOV_EXCL_STOP */
610                 }
611
612                 ret = bo->bufmgr->backend->bo_export(bo);
613                 if (!ret) {
614                         /* LCOV_EXCL_START */
615                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
616                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
617                         goto done;
618                         /* LCOV_EXCL_STOP */
619                 }
620         }
621
622         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
623
624 done:
625         _tbm_bufmgr_mutex_unlock();
626
627         return ret;
628 }
629
630 tbm_fd
631 tbm_bo_export_fd(tbm_bo bo)
632 {
633         tbm_fd ret;
634         tbm_error_e error;
635
636         _tbm_bufmgr_mutex_lock();
637         _tbm_set_last_result(TBM_ERROR_NONE);
638
639         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
640
641         if (bo->bufmgr->use_hal_tbm) {
642                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
643                 if (ret < 0) {
644                         /* LCOV_EXCL_START */
645                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
646                         _tbm_set_last_result(error);
647                         goto done;
648                         /* LCOV_EXCL_STOP */
649                 }
650         } else if (bo->bufmgr->backend_module_data) {
651                 if (!bo->bufmgr->bo_func->bo_export_fd) {
652                         /* LCOV_EXCL_START */
653                         _tbm_bufmgr_mutex_unlock();
654                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
655                         return -1;
656                         /* LCOV_EXCL_STOP */
657                 }
658
659                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
660                 if (ret < 0) {
661                         /* LCOV_EXCL_START */
662                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
663                         _tbm_set_last_result(error);
664                         goto done;
665                         /* LCOV_EXCL_STOP */
666                 }
667         } else {
668                 if (!bo->bufmgr->backend->bo_export_fd) {
669                         /* LCOV_EXCL_START */
670                         _tbm_bufmgr_mutex_unlock();
671                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
672                         return -1;
673                         /* LCOV_EXCL_STOP */
674                 }
675
676                 ret = bo->bufmgr->backend->bo_export_fd(bo);
677                 if (ret < 0) {
678                         /* LCOV_EXCL_START */
679                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
680                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
681                         goto done;
682                         /* LCOV_EXCL_STOP */
683                 }
684         }
685
686         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
687
688 done:
689         _tbm_bufmgr_mutex_unlock();
690
691         return ret;
692 }
693
694 tbm_bo
695 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
696 {
697         tbm_bo bo;
698         tbm_error_e error;
699
700         _tbm_bufmgr_mutex_lock();
701         _tbm_set_last_result(TBM_ERROR_NONE);
702
703         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
704
705         bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key, &error);
706         if (!bo) {
707                 /* LCOV_EXCL_START */
708                 TBM_ERR("tbm_bufmgr_internal_import_key failed. error:%d", error);
709                 _tbm_set_last_result(error);
710                 _tbm_bufmgr_mutex_unlock();
711                 return NULL;
712                 /* LCOV_EXCL_STOP */
713         }
714
715         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
716                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
717
718         _tbm_bufmgr_mutex_unlock();
719
720         return bo;
721 }
722
723 tbm_bo
724 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
725 {
726         tbm_bo bo;
727         tbm_error_e error;
728
729         _tbm_bufmgr_mutex_lock();
730         _tbm_set_last_result(TBM_ERROR_NONE);
731
732         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
733
734         bo = tbm_bufmgr_internal_import_bo_with_fd(bufmgr, fd, &error);
735         if (!bo) {
736                 /* LCOV_EXCL_START */
737                 TBM_ERR("tbm_bufmgr_internal_import_fd failed. error:%d", error);
738                 _tbm_set_last_result(error);
739                 _tbm_bufmgr_mutex_unlock();
740                 return NULL;
741                 /* LCOV_EXCL_STOP */
742         }
743
744         LIST_INITHEAD(&bo->user_data_list); // TODO: remove this. build-break when it is removed.
745
746         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
747                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
748
749         _tbm_bufmgr_mutex_unlock();
750
751         return bo;
752 }
753
754 int
755 tbm_bo_size(tbm_bo bo)
756 {
757         int size;
758         tbm_error_e error;
759
760         _tbm_bufmgr_mutex_lock();
761         _tbm_set_last_result(TBM_ERROR_NONE);
762
763         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
764
765         if (bo->bufmgr->use_hal_tbm) {
766                 size = hal_tbm_bo_get_size((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
767                 if (error != TBM_ERROR_NONE) {
768                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
769                         _tbm_set_last_result(TBM_ERROR_NONE);
770                 }
771         } else if (bo->bufmgr->backend_module_data) {
772                 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
773                 if (error != TBM_ERROR_NONE) {
774                         TBM_ERR("fail to get the size of the bo_data(%d).", error);
775                         _tbm_set_last_result(TBM_ERROR_NONE);
776                 }
777         } else
778                 size = bo->bufmgr->backend->bo_size(bo);
779
780         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
781
782         _tbm_bufmgr_mutex_unlock();
783
784         return size;
785 }
786
787 int
788 tbm_bo_locked(tbm_bo bo)
789 {
790         _tbm_bufmgr_mutex_lock();
791         _tbm_set_last_result(TBM_ERROR_NONE);
792
793         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
794
795         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
796                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
797                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
798                 _tbm_bufmgr_mutex_unlock();
799                 return 0;
800         }
801
802         if (bo->lock_cnt > 0) {
803                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
804                 _tbm_bufmgr_mutex_unlock();
805                 return 1;
806         }
807
808         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
809         _tbm_bufmgr_mutex_unlock();
810
811         return 0;
812 }
813
814 int
815 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
816 {
817         tbm_error_e error1, error2;
818         int size1 = -1, size2 = -2;
819         void *temp;
820
821         _tbm_bufmgr_mutex_lock();
822         _tbm_set_last_result(TBM_ERROR_NONE);
823
824         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
825         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
826
827         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
828
829         if (bo1->bufmgr->use_hal_tbm) {
830                 size1 = hal_tbm_bo_get_size((hal_tbm_bo *)bo1->bo_data, (hal_tbm_error *)&error1);
831                 if (error1 != TBM_ERROR_NONE) {
832                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
833                         _tbm_set_last_result(error1);
834                         goto fail;
835                 }
836                 size2 = hal_tbm_bo_get_size((hal_tbm_bo *)bo2->bo_data, (hal_tbm_error *)&error2);
837                 if (error2 != TBM_ERROR_NONE) {
838                         TBM_ERR("fail to get the size of bo1.(%d)", error2);
839                         _tbm_set_last_result(error2);
840                         goto fail;
841                 }
842         } else if (bo1->bufmgr->backend_module_data) {
843                 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
844                 if (error1 != TBM_ERROR_NONE) {
845                         TBM_ERR("fail to get the size of bo1.(%d)", error1);
846                         _tbm_set_last_result(error1);
847                         goto fail;
848                 }
849                 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
850                 if (error2 != TBM_ERROR_NONE) {
851                         TBM_ERR("fail to get the size of bo2.(%d)", error2);
852                         _tbm_set_last_result(error2);
853                         goto fail;
854                 }
855         } else {
856                 size1 = bo1->bufmgr->backend->bo_size(bo1);
857                 size2 = bo2->bufmgr->backend->bo_size(bo2);
858         }
859
860         if (size1 != size2) {
861                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
862                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
863                 goto fail;
864         }
865
866         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
867
868         temp = bo1->priv;
869         bo1->priv = bo2->priv;
870         bo2->priv = temp;
871
872         _tbm_bufmgr_mutex_unlock();
873
874         return 1;
875
876 fail:
877         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
878         _tbm_bufmgr_mutex_unlock();
879
880         return 0;
881 }
882
883 int
884 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
885                      tbm_data_free data_free_func)
886 {
887         tbm_user_data *data;
888
889         _tbm_bufmgr_mutex_lock();
890         _tbm_set_last_result(TBM_ERROR_NONE);
891
892         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
893
894         /* check if the data according to the key exist if so, return false. */
895         data = user_data_lookup(&bo->user_data_list, key);
896         if (data) {
897                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
898                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
899                 _tbm_bufmgr_mutex_unlock();
900                 return 0;
901         }
902
903         data = user_data_create(key, data_free_func);
904         if (!data) {
905                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
906                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
907                 _tbm_bufmgr_mutex_unlock();
908                 return 0;
909         }
910
911         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
912
913         LIST_ADD(&data->item_link, &bo->user_data_list);
914
915         _tbm_bufmgr_mutex_unlock();
916
917         return 1;
918 }
919
920 int
921 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
922 {
923         tbm_user_data *old_data;
924
925         _tbm_bufmgr_mutex_lock();
926         _tbm_set_last_result(TBM_ERROR_NONE);
927
928         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
929
930         if (LIST_IS_EMPTY(&bo->user_data_list)) {
931                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
932                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
933                 _tbm_bufmgr_mutex_unlock();
934                 return 0;
935         }
936
937         old_data = user_data_lookup(&bo->user_data_list, key);
938         if (!old_data) {
939                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
940                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
941                 _tbm_bufmgr_mutex_unlock();
942                 return 0;
943         }
944
945         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
946
947         user_data_delete(old_data);
948
949         _tbm_bufmgr_mutex_unlock();
950
951         return 1;
952 }
953
954 int
955 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
956 {
957         tbm_user_data *old_data;
958
959         _tbm_bufmgr_mutex_lock();
960         _tbm_set_last_result(TBM_ERROR_NONE);
961
962         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
963
964         if (LIST_IS_EMPTY(&bo->user_data_list)) {
965                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
966                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
967                 _tbm_bufmgr_mutex_unlock();
968                 return 0;
969         }
970
971         old_data = user_data_lookup(&bo->user_data_list, key);
972         if (!old_data) {
973                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
974                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
975                 _tbm_bufmgr_mutex_unlock();
976                 return 0;
977         }
978
979         if (old_data->data && old_data->free_func)
980                 old_data->free_func(old_data->data);
981         old_data->data = data;
982
983         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
984
985         _tbm_bufmgr_mutex_unlock();
986
987         return 1;
988 }
989
990 int
991 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
992 {
993         tbm_user_data *old_data;
994
995         _tbm_bufmgr_mutex_lock();
996         _tbm_set_last_result(TBM_ERROR_NONE);
997
998         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
999
1000         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1001                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1002                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1003                 _tbm_bufmgr_mutex_unlock();
1004                 return 0;
1005         }
1006
1007         old_data = user_data_lookup(&bo->user_data_list, key);
1008         if (!old_data) {
1009                 *data = NULL;
1010                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1011                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1012                 _tbm_bufmgr_mutex_unlock();
1013                 return 0;
1014         }
1015
1016         *data = old_data->data;
1017
1018         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1019
1020         _tbm_bufmgr_mutex_unlock();
1021
1022         return 1;
1023 }
1024
1025 int
1026 tbm_bo_get_flags(tbm_bo bo)
1027 {
1028         int flags;
1029
1030         _tbm_bufmgr_mutex_lock();
1031
1032         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1033
1034         flags = bo->flags;
1035
1036         TBM_TRACE_BO("bo(%p)\n", bo);
1037
1038         _tbm_bufmgr_mutex_unlock();
1039
1040         return flags;
1041 }
1042
1043 /* LCOV_EXCL_START */
1044 /* internal function */
1045 int
1046 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1047 {
1048         _tbm_bufmgr_mutex_lock();
1049
1050         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1051
1052         bo->surface = surface;
1053
1054         _tbm_bufmgr_mutex_unlock();
1055
1056         return 1;
1057 }
1058
1059 void
1060 _tbm_bo_free(tbm_bo bo)
1061 {
1062         /* destory the user_data_list */
1063         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1064                 tbm_user_data *old_data = NULL, *tmp;
1065
1066                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1067                                 &bo->user_data_list, item_link) {
1068                         TBM_DBG("free user_data\n");
1069                         user_data_delete(old_data);
1070                 }
1071         }
1072
1073         while (bo->lock_cnt > 0) {
1074                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1075                 _bo_unlock(bo);
1076                 bo->lock_cnt--;
1077         }
1078
1079         /* call the bo_free */
1080         if (bo->bufmgr->use_hal_tbm) {
1081                 // call hal_tbm_bo_free when bo is created by tbm_bo_alloc api.
1082                 if (!bo->get_from_hal_surface) {
1083                         bo->get_from_hal_surface = 0;
1084
1085                         hal_tbm_bo_free(bo->bo_data);
1086                         bo->bo_data = NULL;
1087                 }
1088         } else if (bo->bufmgr->backend_module_data) {
1089                 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1090                 bo->bo_data = NULL;
1091         } else {
1092                 bo->bufmgr->backend->bo_free(bo);
1093                 bo->priv = NULL;
1094         }
1095
1096         _tbm_bo_deinit(bo);
1097
1098         free(bo);
1099 }
1100 /* LCOV_EXCL_STOP */