tbm_module: add tbm_module_bo_lock 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         tbm_error_e error;
142         int ret;
143
144         error = tbm_module_bo_lock(bo->bufmgr->module, bo, bo->bo_data, device, opt);
145         _tbm_set_last_result(error);
146         switch(error) {
147                 case TBM_ERROR_NONE:
148                         ret = 1;
149                         break;
150                 case TBM_ERROR_NOT_SUPPORTED:
151                         ret = 1;
152                         _tbm_set_last_result(TBM_ERROR_NONE);
153                         break;
154                 default:
155                         ret = 0;
156                         TBM_WRN("fail to lock. error:%d", error);
157                         break;
158         }
159
160         return ret;
161 }
162
163 static void
164 _bo_unlock(tbm_bo bo)
165 {
166         tbm_error_e error;
167
168         if (bo->bufmgr->use_hal_tbm) {
169                 error = (tbm_error_e)hal_tbm_bo_unlock((hal_tbm_bo *)bo->bo_data);
170                 if (error == TBM_ERROR_NOT_SUPPORTED) {
171                         _tbm_set_last_result(TBM_ERROR_NONE);
172                 } else {
173                         if (error != TBM_ERROR_NONE) {
174                                 TBM_WRN("fail to lock");
175                                 _tbm_set_last_result(error);
176                         }
177                 }
178         } else if (bo->bufmgr->backend_module_data) {
179                 if (bo->bufmgr->bo_func->bo_unlock) {
180                         error = bo->bufmgr->bo_func->bo_unlock(bo->bo_data);
181                         if (error != TBM_ERROR_NONE) {
182                                 TBM_WRN("fail to unlock");
183                                 _tbm_set_last_result(error);
184                         }
185                 }
186         } else {
187                 if (bo->bufmgr->backend->bo_unlock)
188                         bo->bufmgr->backend->bo_unlock(bo);
189         }
190 }
191
192 static int
193 _tbm_bo_lock(tbm_bo bo, int device, int opt)
194 {
195         int old, ret;
196
197         if (!bo)
198                 return 0;
199
200         /* do not try to lock the bo */
201         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
202                 return 1;
203
204         if (bo->lock_cnt < 0) {
205                 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
206                         bo, bo->lock_cnt);
207                 return 0;
208         }
209
210         old = bo->lock_cnt;
211
212         switch (bo->bufmgr->bo_lock_type) {
213         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
214                 if (bo->lock_cnt == 0) {
215                         _tbm_bufmgr_mutex_unlock();
216                         ret = _bo_lock(bo, device, opt);
217                         _tbm_bufmgr_mutex_lock();
218                         if (ret)
219                                 bo->lock_cnt++;
220                 } else
221                         ret = 1;
222                 break;
223         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
224                 _tbm_bufmgr_mutex_unlock();
225                 ret = _bo_lock(bo, device, opt);
226                 _tbm_bufmgr_mutex_lock();
227                 if (ret)
228                         bo->lock_cnt++;
229                 break;
230         default:
231                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
232                                 bo, bo->bufmgr->bo_lock_type);
233                 ret = 0;
234                 break;
235         }
236
237         TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
238
239         return ret;
240 }
241
242 static void
243 _tbm_bo_unlock(tbm_bo bo)
244 {
245         int old;
246
247         /* do not try to unlock the bo */
248         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
249                 return;
250
251         old = bo->lock_cnt;
252
253         switch (bo->bufmgr->bo_lock_type) {
254         case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
255                 if (bo->lock_cnt > 0) {
256                         bo->lock_cnt--;
257                         if (bo->lock_cnt == 0)
258                                 _bo_unlock(bo);
259                 }
260                 break;
261         case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
262                 if (bo->lock_cnt > 0) {
263                         bo->lock_cnt--;
264                         _bo_unlock(bo);
265                 }
266                 break;
267         default:
268                 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
269                                 bo, bo->bufmgr->bo_lock_type);
270                 break;
271         }
272
273         if (bo->lock_cnt < 0)
274                 bo->lock_cnt = 0;
275
276         TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
277 }
278
279 static int
280 _tbm_bo_magic_check(tbm_bo bo)
281 {
282         if (bo->magic != TBM_BO_MAGIC)
283                 return 0;
284
285         return 1;
286 }
287
288 static int
289 _tbm_bo_is_valid(tbm_bo bo)
290 {
291         if (!bo) {
292                 TBM_ERR("error: bo is NULL.\n");
293                 return 0;
294         }
295
296         if (!_tbm_bo_magic_check(bo)) {
297                 TBM_ERR("error: No valid bo(%p).\n", bo);
298                 return 0;
299         }
300
301         return 1;
302 }
303
304 static void
305 _tbm_bo_deinit(tbm_bo bo)
306 {
307         bo->magic = 0;
308
309         bo->bufmgr->bo_cnt--;
310         LIST_DEL(&bo->item_link);
311 }
312
313 tbm_bo
314 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
315 {
316         tbm_bo bo;
317         tbm_error_e error;
318
319         _tbm_bufmgr_mutex_lock();
320         _tbm_set_last_result(TBM_ERROR_NONE);
321
322         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
323         TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
324
325         bo = tbm_bufmgr_internal_alloc_bo(bufmgr, size, flags, &error);
326         if (!bo) {
327                 /* LCOV_EXCL_START */
328                 TBM_ERR("tbm_bufmgr_internal_alloc_bo failed. error:%d", error);
329                 _tbm_set_last_result(error);
330                 _tbm_bufmgr_mutex_unlock();
331                 return NULL;
332                 /* LCOV_EXCL_STOP */
333         }
334
335         TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
336                         _tbm_flag_to_str(bo->flags));
337
338         _tbm_bufmgr_mutex_unlock();
339
340         return bo;
341 }
342
343 tbm_bo
344 tbm_bo_ref(tbm_bo bo)
345 {
346         _tbm_bufmgr_mutex_lock();
347         _tbm_set_last_result(TBM_ERROR_NONE);
348
349         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
350
351         bo->ref_cnt++;
352
353         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
354
355         _tbm_bufmgr_mutex_unlock();
356
357         return bo;
358 }
359
360 void
361 tbm_bo_unref(tbm_bo bo)
362 {
363         _tbm_bufmgr_mutex_lock();
364         _tbm_set_last_result(TBM_ERROR_NONE);
365
366         TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
367
368         TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
369
370         if (bo->ref_cnt <= 0) {
371                 _tbm_bufmgr_mutex_unlock();
372                 return;
373         }
374
375         bo->ref_cnt--;
376         if (bo->ref_cnt == 0)
377                 _tbm_bo_free(bo);
378
379         _tbm_bufmgr_mutex_unlock();
380 }
381
382 tbm_bo_handle
383 tbm_bo_map(tbm_bo bo, int device, int opt)
384 {
385         tbm_bo_handle bo_handle;
386         tbm_error_e error;
387
388         _tbm_bufmgr_mutex_lock();
389         _tbm_set_last_result(TBM_ERROR_NONE);
390
391         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
392
393         if (!_tbm_bo_lock(bo, device, opt)) {
394                 TBM_ERR("error: fail to lock bo:%p)\n", bo);
395                 _tbm_bufmgr_mutex_unlock();
396                 return (tbm_bo_handle) NULL;
397         }
398
399         bo_handle = tbm_module_bo_map(bo->bufmgr->module, bo, bo->bo_data, device, opt, &error);
400         if (bo_handle.ptr == NULL) {
401                 /* LCOV_EXCL_START */
402                 TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
403                 _tbm_set_last_result(error);
404                 _tbm_bo_unlock(bo);
405                 _tbm_bufmgr_mutex_unlock();
406                 return (tbm_bo_handle) NULL;
407                 /* LCOV_EXCL_STOP */
408         }
409
410         /* increase the map_count */
411         bo->map_cnt++;
412
413         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
414
415         _tbm_bufmgr_mutex_unlock();
416
417         return bo_handle;
418 }
419
420 int
421 tbm_bo_unmap(tbm_bo bo)
422 {
423         tbm_error_e error;
424
425         _tbm_bufmgr_mutex_lock();
426         _tbm_set_last_result(TBM_ERROR_NONE);
427
428         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
429         TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
430
431         error = tbm_module_bo_unmap(bo->bufmgr->module, bo, bo->bo_data);
432         if (error != TBM_ERROR_NONE) {
433                 /* LCOV_EXCL_START */
434                 TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
435                 _tbm_set_last_result(error);
436                 _tbm_bufmgr_mutex_unlock();
437                 return 0;
438                 /* LCOV_EXCL_STOP */
439         }
440
441         /* decrease the map_count */
442         bo->map_cnt--;
443
444         TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
445
446         _tbm_bo_unlock(bo);
447
448         _tbm_bufmgr_mutex_unlock();
449
450         return 1;
451 }
452
453 tbm_bo_handle
454 tbm_bo_get_handle(tbm_bo bo, int device)
455 {
456         tbm_bo_handle bo_handle;
457         tbm_error_e error;
458
459         _tbm_bufmgr_mutex_lock();
460         _tbm_set_last_result(TBM_ERROR_NONE);
461
462         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
463
464         bo_handle = tbm_module_bo_get_handle(bo->bufmgr->module, bo, bo->bo_data, device, &error);
465         if (bo_handle.ptr == NULL) {
466                 /* LCOV_EXCL_START */
467                 TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
468                 _tbm_set_last_result(error);
469                 _tbm_bufmgr_mutex_unlock();
470                 return (tbm_bo_handle)NULL;
471                 /* LCOV_EXCL_STOP */
472         }
473
474         TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
475
476         _tbm_bufmgr_mutex_unlock();
477
478         return bo_handle;
479 }
480
481 tbm_key
482 tbm_bo_export(tbm_bo bo)
483 {
484         tbm_key ret;
485         tbm_error_e error;
486
487         _tbm_bufmgr_mutex_lock();
488         _tbm_set_last_result(TBM_ERROR_NONE);
489
490         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
491
492         if (bo->bufmgr->use_hal_tbm) {
493                 ret = (hal_tbm_key)hal_tbm_bo_export_key((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
494                 if (!ret) {
495                         /* LCOV_EXCL_START */
496                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
497                         _tbm_set_last_result(error);
498                         goto done;
499                         /* LCOV_EXCL_STOP */
500                 }
501         } else if (bo->bufmgr->backend_module_data) {
502                 if (!bo->bufmgr->bo_func->bo_export_key) {
503                         /* LCOV_EXCL_START */
504                         _tbm_bufmgr_mutex_unlock();
505                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
506                         return 0;
507                         /* LCOV_EXCL_STOP */
508                 }
509
510                 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
511                 if (!ret) {
512                         /* LCOV_EXCL_START */
513                         TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
514                         _tbm_set_last_result(error);
515                         goto done;
516                         /* LCOV_EXCL_STOP */
517                 }
518         } else {
519                 if (!bo->bufmgr->backend->bo_export) {
520                         /* LCOV_EXCL_START */
521                         _tbm_bufmgr_mutex_unlock();
522                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
523                         return 0;
524                         /* LCOV_EXCL_STOP */
525                 }
526
527                 ret = bo->bufmgr->backend->bo_export(bo);
528                 if (!ret) {
529                         /* LCOV_EXCL_START */
530                         TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
531                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
532                         goto done;
533                         /* LCOV_EXCL_STOP */
534                 }
535         }
536
537         TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
538
539 done:
540         _tbm_bufmgr_mutex_unlock();
541
542         return ret;
543 }
544
545 tbm_fd
546 tbm_bo_export_fd(tbm_bo bo)
547 {
548         tbm_fd ret;
549         tbm_error_e error;
550
551         _tbm_bufmgr_mutex_lock();
552         _tbm_set_last_result(TBM_ERROR_NONE);
553
554         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
555
556         if (bo->bufmgr->use_hal_tbm) {
557                 ret = (hal_tbm_fd)hal_tbm_bo_export_fd((hal_tbm_bo *)bo->bo_data, (hal_tbm_error *)&error);
558                 if (ret < 0) {
559                         /* LCOV_EXCL_START */
560                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
561                         _tbm_set_last_result(error);
562                         goto done;
563                         /* LCOV_EXCL_STOP */
564                 }
565         } else if (bo->bufmgr->backend_module_data) {
566                 if (!bo->bufmgr->bo_func->bo_export_fd) {
567                         /* LCOV_EXCL_START */
568                         _tbm_bufmgr_mutex_unlock();
569                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
570                         return -1;
571                         /* LCOV_EXCL_STOP */
572                 }
573
574                 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
575                 if (ret < 0) {
576                         /* LCOV_EXCL_START */
577                         TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
578                         _tbm_set_last_result(error);
579                         goto done;
580                         /* LCOV_EXCL_STOP */
581                 }
582         } else {
583                 if (!bo->bufmgr->backend->bo_export_fd) {
584                         /* LCOV_EXCL_START */
585                         _tbm_bufmgr_mutex_unlock();
586                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
587                         return -1;
588                         /* LCOV_EXCL_STOP */
589                 }
590
591                 ret = bo->bufmgr->backend->bo_export_fd(bo);
592                 if (ret < 0) {
593                         /* LCOV_EXCL_START */
594                         TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
595                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
596                         goto done;
597                         /* LCOV_EXCL_STOP */
598                 }
599         }
600
601         TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
602
603 done:
604         _tbm_bufmgr_mutex_unlock();
605
606         return ret;
607 }
608
609 tbm_bo
610 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
611 {
612         tbm_bo bo;
613         tbm_error_e error;
614
615         _tbm_bufmgr_mutex_lock();
616         _tbm_set_last_result(TBM_ERROR_NONE);
617
618         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
619
620         bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key, &error);
621         if (!bo) {
622                 /* LCOV_EXCL_START */
623                 TBM_ERR("tbm_bufmgr_internal_import_key failed. error:%d", error);
624                 _tbm_set_last_result(error);
625                 _tbm_bufmgr_mutex_unlock();
626                 return NULL;
627                 /* LCOV_EXCL_STOP */
628         }
629
630         TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
631                           bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
632
633         _tbm_bufmgr_mutex_unlock();
634
635         return bo;
636 }
637
638 tbm_bo
639 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
640 {
641         tbm_bo bo;
642         tbm_error_e error;
643
644         _tbm_bufmgr_mutex_lock();
645         _tbm_set_last_result(TBM_ERROR_NONE);
646
647         TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
648
649         bo = tbm_bufmgr_internal_import_bo_with_fd(bufmgr, fd, &error);
650         if (!bo) {
651                 /* LCOV_EXCL_START */
652                 TBM_ERR("tbm_bufmgr_internal_import_fd failed. error:%d", error);
653                 _tbm_set_last_result(error);
654                 _tbm_bufmgr_mutex_unlock();
655                 return NULL;
656                 /* LCOV_EXCL_STOP */
657         }
658
659         LIST_INITHEAD(&bo->user_data_list); // TODO: remove this. build-break when it is removed.
660
661         TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
662                         bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
663
664         _tbm_bufmgr_mutex_unlock();
665
666         return bo;
667 }
668
669 int
670 tbm_bo_size(tbm_bo bo)
671 {
672         int size;
673         tbm_error_e error;
674
675         _tbm_bufmgr_mutex_lock();
676         _tbm_set_last_result(TBM_ERROR_NONE);
677
678         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
679
680         size = tbm_module_bo_get_size(bo->bufmgr->module, bo, bo->bo_data, &error);
681         _tbm_set_last_result(error);
682
683         TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
684
685         _tbm_bufmgr_mutex_unlock();
686
687         return size;
688 }
689
690 int
691 tbm_bo_locked(tbm_bo bo)
692 {
693         _tbm_bufmgr_mutex_lock();
694         _tbm_set_last_result(TBM_ERROR_NONE);
695
696         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
697
698         if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
699                 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
700                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
701                 _tbm_bufmgr_mutex_unlock();
702                 return 0;
703         }
704
705         if (bo->lock_cnt > 0) {
706                 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
707                 _tbm_bufmgr_mutex_unlock();
708                 return 1;
709         }
710
711         TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
712         _tbm_bufmgr_mutex_unlock();
713
714         return 0;
715 }
716
717 int
718 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
719 {
720         tbm_error_e error1, error2;
721         int size1 = -1, size2 = -2;
722         void *temp;
723
724         _tbm_bufmgr_mutex_lock();
725         _tbm_set_last_result(TBM_ERROR_NONE);
726
727         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
728         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
729
730         TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
731
732         size1 = tbm_module_bo_get_size(bo1->bufmgr->module, bo1, bo1->bo_data, &error1);
733         _tbm_set_last_result(error1);
734         size2 = tbm_module_bo_get_size(bo2->bufmgr->module, bo2, bo2->bo_data, &error2);
735         _tbm_set_last_result(error2);
736
737         if (size1 != size2) {
738                 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
739                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
740                 goto fail;
741         }
742
743         TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
744
745         temp = bo1->priv;
746         bo1->priv = bo2->priv;
747         bo2->priv = temp;
748
749         _tbm_bufmgr_mutex_unlock();
750
751         return 1;
752
753 fail:
754         TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
755         _tbm_bufmgr_mutex_unlock();
756
757         return 0;
758 }
759
760 int
761 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
762                      tbm_data_free data_free_func)
763 {
764         tbm_user_data *data;
765
766         _tbm_bufmgr_mutex_lock();
767         _tbm_set_last_result(TBM_ERROR_NONE);
768
769         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
770
771         /* check if the data according to the key exist if so, return false. */
772         data = user_data_lookup(&bo->user_data_list, key);
773         if (data) {
774                 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
775                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
776                 _tbm_bufmgr_mutex_unlock();
777                 return 0;
778         }
779
780         data = user_data_create(key, data_free_func);
781         if (!data) {
782                 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
783                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
784                 _tbm_bufmgr_mutex_unlock();
785                 return 0;
786         }
787
788         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
789
790         LIST_ADD(&data->item_link, &bo->user_data_list);
791
792         _tbm_bufmgr_mutex_unlock();
793
794         return 1;
795 }
796
797 int
798 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
799 {
800         tbm_user_data *old_data;
801
802         _tbm_bufmgr_mutex_lock();
803         _tbm_set_last_result(TBM_ERROR_NONE);
804
805         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
806
807         if (LIST_IS_EMPTY(&bo->user_data_list)) {
808                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
809                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
810                 _tbm_bufmgr_mutex_unlock();
811                 return 0;
812         }
813
814         old_data = user_data_lookup(&bo->user_data_list, key);
815         if (!old_data) {
816                 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
817                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
818                 _tbm_bufmgr_mutex_unlock();
819                 return 0;
820         }
821
822         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
823
824         user_data_delete(old_data);
825
826         _tbm_bufmgr_mutex_unlock();
827
828         return 1;
829 }
830
831 int
832 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
833 {
834         tbm_user_data *old_data;
835
836         _tbm_bufmgr_mutex_lock();
837         _tbm_set_last_result(TBM_ERROR_NONE);
838
839         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
840
841         if (LIST_IS_EMPTY(&bo->user_data_list)) {
842                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
843                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
844                 _tbm_bufmgr_mutex_unlock();
845                 return 0;
846         }
847
848         old_data = user_data_lookup(&bo->user_data_list, key);
849         if (!old_data) {
850                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
851                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
852                 _tbm_bufmgr_mutex_unlock();
853                 return 0;
854         }
855
856         if (old_data->data && old_data->free_func)
857                 old_data->free_func(old_data->data);
858         old_data->data = data;
859
860         TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
861
862         _tbm_bufmgr_mutex_unlock();
863
864         return 1;
865 }
866
867 int
868 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
869 {
870         tbm_user_data *old_data;
871
872         _tbm_bufmgr_mutex_lock();
873         _tbm_set_last_result(TBM_ERROR_NONE);
874
875         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
876
877         if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
878                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
879                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
880                 _tbm_bufmgr_mutex_unlock();
881                 return 0;
882         }
883
884         old_data = user_data_lookup(&bo->user_data_list, key);
885         if (!old_data) {
886                 *data = NULL;
887                 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
888                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
889                 _tbm_bufmgr_mutex_unlock();
890                 return 0;
891         }
892
893         *data = old_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_flags(tbm_bo bo)
904 {
905         int flags;
906
907         _tbm_bufmgr_mutex_lock();
908
909         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
910
911         flags = bo->flags;
912
913         TBM_TRACE_BO("bo(%p)\n", bo);
914
915         _tbm_bufmgr_mutex_unlock();
916
917         return flags;
918 }
919
920 /* LCOV_EXCL_START */
921 /* internal function */
922 int
923 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
924 {
925         _tbm_bufmgr_mutex_lock();
926
927         TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
928
929         bo->surface = surface;
930
931         _tbm_bufmgr_mutex_unlock();
932
933         return 1;
934 }
935
936 void
937 _tbm_bo_free(tbm_bo bo)
938 {
939         /* destory the user_data_list */
940         if (!LIST_IS_EMPTY(&bo->user_data_list)) {
941                 tbm_user_data *old_data = NULL, *tmp;
942
943                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
944                                 &bo->user_data_list, item_link) {
945                         TBM_DBG("free user_data\n");
946                         user_data_delete(old_data);
947                 }
948         }
949
950         while (bo->lock_cnt > 0) {
951                 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
952                 _bo_unlock(bo);
953                 bo->lock_cnt--;
954         }
955
956         tbm_module_bo_free(bo->bufmgr->module, bo, bo->bo_data, bo->get_from_hal_surface);
957
958         _tbm_bo_deinit(bo);
959
960         free(bo);
961 }
962 /* LCOV_EXCL_STOP */