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