tbm_module: add tbm_module_bo_get_memory_types 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         size = tbm_module_bo_get_size(bo->bufmgr->module, bo, bo->bo_data, &error);
766         _tbm_set_last_result(error);
767
768         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
769
770         _tbm_bufmgr_mutex_unlock();
771
772         return size;
773 }
774
775 int
776 tbm_bo_locked(tbm_bo bo)
777 {
778         _tbm_bufmgr_mutex_lock();
779         _tbm_set_last_result(TBM_ERROR_NONE);
780
781         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
782
783         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
784                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
785                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
786                 _tbm_bufmgr_mutex_unlock();
787                 return 0;
788         }
789
790         if (bo->lock_cnt > 0) {
791                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
792                 _tbm_bufmgr_mutex_unlock();
793                 return 1;
794         }
795
796         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
797         _tbm_bufmgr_mutex_unlock();
798
799         return 0;
800 }
801
802 int
803 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
804 {
805         tbm_error_e error1, error2;
806         int size1 = -1, size2 = -2;
807         void *temp;
808
809         _tbm_bufmgr_mutex_lock();
810         _tbm_set_last_result(TBM_ERROR_NONE);
811
812         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
813         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
814
815         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
816
817         size1 = tbm_module_bo_get_size(bo1->bufmgr->module, bo1, bo1->bo_data, &error1);
818         _tbm_set_last_result(error1);
819         size2 = tbm_module_bo_get_size(bo2->bufmgr->module, bo2, bo2->bo_data, &error2);
820         _tbm_set_last_result(error2);
821
822         if (size1 != size2) {
823                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
824                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
825                 goto fail;
826         }
827
828         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
829
830         temp = bo1->priv;
831         bo1->priv = bo2->priv;
832         bo2->priv = temp;
833
834         _tbm_bufmgr_mutex_unlock();
835
836         return 1;
837
838 fail:
839         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
840         _tbm_bufmgr_mutex_unlock();
841
842         return 0;
843 }
844
845 int
846 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
847                      tbm_data_free data_free_func)
848 {
849         tbm_user_data *data;
850
851         _tbm_bufmgr_mutex_lock();
852         _tbm_set_last_result(TBM_ERROR_NONE);
853
854         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
855
856         /* check if the data according to the key exist if so, return false. */
857         data = user_data_lookup(&bo->user_data_list, key);
858         if (data) {
859                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
860                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
861                 _tbm_bufmgr_mutex_unlock();
862                 return 0;
863         }
864
865         data = user_data_create(key, data_free_func);
866         if (!data) {
867                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
868                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
869                 _tbm_bufmgr_mutex_unlock();
870                 return 0;
871         }
872
873         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
874
875         LIST_ADD(&data->item_link, &bo->user_data_list);
876
877         _tbm_bufmgr_mutex_unlock();
878
879         return 1;
880 }
881
882 int
883 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
884 {
885         tbm_user_data *old_data;
886
887         _tbm_bufmgr_mutex_lock();
888         _tbm_set_last_result(TBM_ERROR_NONE);
889
890         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
891
892         if (LIST_IS_EMPTY(&bo->user_data_list)) {
893                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
894                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
895                 _tbm_bufmgr_mutex_unlock();
896                 return 0;
897         }
898
899         old_data = user_data_lookup(&bo->user_data_list, key);
900         if (!old_data) {
901                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
902                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
903                 _tbm_bufmgr_mutex_unlock();
904                 return 0;
905         }
906
907         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
908
909         user_data_delete(old_data);
910
911         _tbm_bufmgr_mutex_unlock();
912
913         return 1;
914 }
915
916 int
917 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
918 {
919         tbm_user_data *old_data;
920
921         _tbm_bufmgr_mutex_lock();
922         _tbm_set_last_result(TBM_ERROR_NONE);
923
924         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
925
926         if (LIST_IS_EMPTY(&bo->user_data_list)) {
927                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
928                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
929                 _tbm_bufmgr_mutex_unlock();
930                 return 0;
931         }
932
933         old_data = user_data_lookup(&bo->user_data_list, key);
934         if (!old_data) {
935                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
936                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
937                 _tbm_bufmgr_mutex_unlock();
938                 return 0;
939         }
940
941         if (old_data->data && old_data->free_func)
942                 old_data->free_func(old_data->data);
943         old_data->data = data;
944
945         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
946
947         _tbm_bufmgr_mutex_unlock();
948
949         return 1;
950 }
951
952 int
953 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
954 {
955         tbm_user_data *old_data;
956
957         _tbm_bufmgr_mutex_lock();
958         _tbm_set_last_result(TBM_ERROR_NONE);
959
960         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
961
962         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
963                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
964                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
965                 _tbm_bufmgr_mutex_unlock();
966                 return 0;
967         }
968
969         old_data = user_data_lookup(&bo->user_data_list, key);
970         if (!old_data) {
971                 *data = NULL;
972                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
973                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
974                 _tbm_bufmgr_mutex_unlock();
975                 return 0;
976         }
977
978         *data = old_data->data;
979
980         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
981
982         _tbm_bufmgr_mutex_unlock();
983
984         return 1;
985 }
986
987 int
988 tbm_bo_get_flags(tbm_bo bo)
989 {
990         int flags;
991
992         _tbm_bufmgr_mutex_lock();
993
994         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
995
996         flags = bo->flags;
997
998         TBM_TRACE_BO("bo(%p)\n", bo);
999
1000         _tbm_bufmgr_mutex_unlock();
1001
1002         return flags;
1003 }
1004
1005 /* LCOV_EXCL_START */
1006 /* internal function */
1007 int
1008 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1009 {
1010         _tbm_bufmgr_mutex_lock();
1011
1012         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1013
1014         bo->surface = surface;
1015
1016         _tbm_bufmgr_mutex_unlock();
1017
1018         return 1;
1019 }
1020
1021 void
1022 _tbm_bo_free(tbm_bo bo)
1023 {
1024         /* destory the user_data_list */
1025         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1026                 tbm_user_data *old_data = NULL, *tmp;
1027
1028                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1029                                 &bo->user_data_list, item_link) {
1030                         TBM_DBG("free user_data\n");
1031                         user_data_delete(old_data);
1032                 }
1033         }
1034
1035         while (bo->lock_cnt > 0) {
1036                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1037                 _bo_unlock(bo);
1038                 bo->lock_cnt--;
1039         }
1040
1041         tbm_module_bo_free(bo->bufmgr->module, bo, bo->bo_data, bo->get_from_hal_surface);
1042
1043         _tbm_bo_deinit(bo);
1044
1045         free(bo);
1046 }
1047 /* LCOV_EXCL_STOP */