1 /**************************************************************************
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
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>
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:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
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.
30 **************************************************************************/
33 #include "tbm_bufmgr.h"
34 #include "tbm_bufmgr_int.h"
38 #define TBM_BO_RETURN_IF_FAIL(cond) {\
40 TBM_ERR("'%s' failed.\n", #cond);\
41 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
42 _tbm_bufmgr_mutex_unlock();\
47 #define TBM_BO_RETURN_VAL_IF_FAIL(cond, val) {\
49 TBM_ERR("'%s' failed.\n", #cond);\
50 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
51 _tbm_bufmgr_mutex_unlock();\
57 _tbm_flag_to_str(int f)
61 if (f == TBM_BO_DEFAULT)
62 snprintf(str, 255, "DEFAULT");
66 if (f & TBM_BO_SCANOUT)
67 c += snprintf(&str[c], 255-c, "SCANOUT");
69 if (f & TBM_BO_NONCACHABLE) {
70 if (c >= 0 && c < 255)
71 c += snprintf(&str[c], 255-c, ", ");
73 if (c >= 0 && c < 255)
74 c += snprintf(&str[c], 255-c, "NONCACHABLE,");
78 if (c >= 0 && c < 255)
79 c += snprintf(&str[c], 255-c, ", ");
81 if (c >= 0 && c < 255)
82 c += snprintf(&str[c], 255-c, "WC");
92 user_data_lookup(struct list_head *user_data_list, unsigned long key)
94 tbm_user_data *old_data = NULL;
96 if (LIST_IS_EMPTY(user_data_list))
99 LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
100 if (old_data->key == key)
108 user_data_create(unsigned long key, tbm_data_free data_free_func)
110 tbm_user_data *user_data;
112 user_data = calloc(1, sizeof(tbm_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);
121 user_data->key = key;
122 user_data->free_func = data_free_func;
128 user_data_delete(tbm_user_data *user_data)
130 if (user_data->data && user_data->free_func)
131 user_data->free_func(user_data->data);
133 LIST_DEL(&user_data->item_link);
139 _bo_lock(tbm_bo bo, int device, int opt)
144 error = tbm_bo_data_lock(bo->bo_data, device, opt);
145 _tbm_set_last_result(error);
150 case TBM_ERROR_NOT_SUPPORTED:
152 _tbm_set_last_result(TBM_ERROR_NONE);
156 TBM_WRN("fail to lock. error:%d", error);
164 _bo_unlock(tbm_bo bo)
168 error = tbm_bo_data_unlock(bo->bo_data);
169 _tbm_set_last_result(error);
173 case TBM_ERROR_NOT_SUPPORTED:
174 _tbm_set_last_result(TBM_ERROR_NONE);
177 TBM_WRN("fail to lock. error:%d", error);
183 _tbm_bo_lock(tbm_bo bo, int device, int opt)
190 /* do not try to lock the bo */
191 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
194 if (bo->lock_cnt < 0) {
195 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
202 switch (bo->bufmgr->bo_lock_type) {
203 case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
204 if (bo->lock_cnt == 0) {
205 _tbm_bufmgr_mutex_unlock();
206 ret = _bo_lock(bo, device, opt);
207 _tbm_bufmgr_mutex_lock();
213 case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
214 _tbm_bufmgr_mutex_unlock();
215 ret = _bo_lock(bo, device, opt);
216 _tbm_bufmgr_mutex_lock();
221 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
222 bo, bo->bufmgr->bo_lock_type);
227 TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
233 _tbm_bo_unlock(tbm_bo bo)
237 /* do not try to unlock the bo */
238 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
243 switch (bo->bufmgr->bo_lock_type) {
244 case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
245 if (bo->lock_cnt > 0) {
247 if (bo->lock_cnt == 0)
251 case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
252 if (bo->lock_cnt > 0) {
258 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
259 bo, bo->bufmgr->bo_lock_type);
263 if (bo->lock_cnt < 0)
266 TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
270 _tbm_bo_magic_check(tbm_bo bo)
272 if (bo->magic != TBM_BO_MAGIC)
279 _tbm_bo_is_valid(tbm_bo bo)
282 TBM_ERR("error: bo is NULL.\n");
286 if (!_tbm_bo_magic_check(bo)) {
287 TBM_ERR("error: No valid bo(%p).\n", bo);
295 _tbm_bo_deinit(tbm_bo bo)
299 bo->bufmgr->bo_cnt--;
300 LIST_DEL(&bo->item_link);
304 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
309 _tbm_bufmgr_mutex_lock();
310 _tbm_set_last_result(TBM_ERROR_NONE);
312 TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
313 TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
315 bo = tbm_bufmgr_internal_alloc_bo(bufmgr, size, flags, &error);
317 /* LCOV_EXCL_START */
318 TBM_ERR("tbm_bufmgr_internal_alloc_bo failed. error:%d", error);
319 _tbm_set_last_result(error);
320 _tbm_bufmgr_mutex_unlock();
325 TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
326 _tbm_flag_to_str(bo->flags));
328 _tbm_bufmgr_mutex_unlock();
334 tbm_bo_ref(tbm_bo bo)
336 _tbm_bufmgr_mutex_lock();
337 _tbm_set_last_result(TBM_ERROR_NONE);
339 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
343 TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
345 _tbm_bufmgr_mutex_unlock();
351 tbm_bo_unref(tbm_bo bo)
353 _tbm_bufmgr_mutex_lock();
354 _tbm_set_last_result(TBM_ERROR_NONE);
356 TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
358 TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
360 if (bo->ref_cnt <= 0) {
361 _tbm_bufmgr_mutex_unlock();
366 if (bo->ref_cnt == 0)
369 _tbm_bufmgr_mutex_unlock();
373 tbm_bo_map(tbm_bo bo, int device, int opt)
375 tbm_bo_handle bo_handle;
378 _tbm_bufmgr_mutex_lock();
379 _tbm_set_last_result(TBM_ERROR_NONE);
381 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
383 if (!_tbm_bo_lock(bo, device, opt)) {
384 TBM_ERR("error: fail to lock bo:%p)\n", bo);
385 _tbm_bufmgr_mutex_unlock();
386 return (tbm_bo_handle) NULL;
389 bo_handle = tbm_bo_data_map(bo->bo_data, device, opt, &error);
390 if (bo_handle.ptr == NULL) {
391 /* LCOV_EXCL_START */
392 TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
393 _tbm_set_last_result(error);
395 _tbm_bufmgr_mutex_unlock();
396 return (tbm_bo_handle) NULL;
400 /* increase the map_count */
403 TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
405 _tbm_bufmgr_mutex_unlock();
411 tbm_bo_unmap(tbm_bo bo)
415 _tbm_bufmgr_mutex_lock();
416 _tbm_set_last_result(TBM_ERROR_NONE);
418 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
419 TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
421 error = tbm_bo_data_unmap(bo->bo_data);
422 if (error != TBM_ERROR_NONE) {
423 /* LCOV_EXCL_START */
424 TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
425 _tbm_set_last_result(error);
426 _tbm_bufmgr_mutex_unlock();
431 /* decrease the map_count */
434 TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
438 _tbm_bufmgr_mutex_unlock();
444 tbm_bo_get_handle(tbm_bo bo, int device)
446 tbm_bo_handle bo_handle;
449 _tbm_bufmgr_mutex_lock();
450 _tbm_set_last_result(TBM_ERROR_NONE);
452 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
454 bo_handle = tbm_bo_data_get_handle(bo->bo_data, device, &error);
455 if (bo_handle.ptr == NULL) {
456 /* LCOV_EXCL_START */
457 TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
458 _tbm_set_last_result(error);
459 _tbm_bufmgr_mutex_unlock();
460 return (tbm_bo_handle)NULL;
464 TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
466 _tbm_bufmgr_mutex_unlock();
472 tbm_bo_export(tbm_bo bo)
477 _tbm_bufmgr_mutex_lock();
478 _tbm_set_last_result(TBM_ERROR_NONE);
480 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
482 ret = tbm_bo_data_export_key(bo->bo_data, &error);
484 /* LCOV_EXCL_START */
485 TBM_ERR("tbm_moule_bo_export_key failed. bo:%p tbm_key:%d error:%d", bo, ret, error);
486 _tbm_set_last_result(error);
487 _tbm_bufmgr_mutex_unlock();
492 TBM_TRACE_BO("bo:%p tbm_key:%u", bo, ret);
494 _tbm_bufmgr_mutex_unlock();
500 tbm_bo_export_fd(tbm_bo bo)
505 _tbm_bufmgr_mutex_lock();
506 _tbm_set_last_result(TBM_ERROR_NONE);
508 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
510 fd = tbm_bo_data_export_fd(bo->bo_data, &error);
512 /* LCOV_EXCL_START */
513 TBM_ERR("tbm_bo_data_export_fd filed. bo:%p tbm_fd:%d error:%d", bo, fd, error);
514 _tbm_set_last_result(error);
515 _tbm_bufmgr_mutex_unlock();
520 TBM_TRACE_BO("bo:%p tbm_fd:%d", bo, fd);
522 _tbm_bufmgr_mutex_unlock();
528 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
532 bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key);
534 /* LCOV_EXCL_START */
535 TBM_ERR("tbm_bufmgr_internal_import_bo_with_key failed");
544 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
548 bo = tbm_bufmgr_internal_import_bo_with_fd(bufmgr, fd);
550 /* LCOV_EXCL_START */
551 TBM_ERR("tbm_bufmgr_internal_import_fd failed.");
560 tbm_bo_size(tbm_bo bo)
565 _tbm_bufmgr_mutex_lock();
566 _tbm_set_last_result(TBM_ERROR_NONE);
568 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
570 size = tbm_bo_data_get_size(bo->bo_data, &error);
571 _tbm_set_last_result(error);
573 TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
575 _tbm_bufmgr_mutex_unlock();
581 tbm_bo_locked(tbm_bo bo)
583 _tbm_bufmgr_mutex_lock();
584 _tbm_set_last_result(TBM_ERROR_NONE);
586 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
588 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
589 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
590 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
591 _tbm_bufmgr_mutex_unlock();
595 if (bo->lock_cnt > 0) {
596 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
597 _tbm_bufmgr_mutex_unlock();
601 TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
602 _tbm_bufmgr_mutex_unlock();
608 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
610 tbm_error_e error1, error2;
611 int size1 = -1, size2 = -2;
614 _tbm_bufmgr_mutex_lock();
615 _tbm_set_last_result(TBM_ERROR_NONE);
617 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
618 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
620 TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
622 size1 = tbm_bo_data_get_size(bo1->bo_data, &error1);
623 _tbm_set_last_result(error1);
624 size2 = tbm_bo_data_get_size(bo2->bo_data, &error2);
625 _tbm_set_last_result(error2);
627 if (size1 != size2) {
628 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
629 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
634 bo1->bo_data = bo2->bo_data;
637 TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
639 _tbm_bufmgr_mutex_unlock();
644 TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
645 _tbm_bufmgr_mutex_unlock();
651 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
652 tbm_data_free data_free_func)
656 _tbm_bufmgr_mutex_lock();
657 _tbm_set_last_result(TBM_ERROR_NONE);
659 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
661 /* check if the data according to the key exist if so, return false. */
662 data = user_data_lookup(&bo->user_data_list, key);
664 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
665 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
666 _tbm_bufmgr_mutex_unlock();
670 data = user_data_create(key, data_free_func);
672 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
673 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
674 _tbm_bufmgr_mutex_unlock();
678 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
680 LIST_ADD(&data->item_link, &bo->user_data_list);
682 _tbm_bufmgr_mutex_unlock();
688 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
690 tbm_user_data *old_data;
692 _tbm_bufmgr_mutex_lock();
693 _tbm_set_last_result(TBM_ERROR_NONE);
695 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
697 if (LIST_IS_EMPTY(&bo->user_data_list)) {
698 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
699 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
700 _tbm_bufmgr_mutex_unlock();
704 old_data = user_data_lookup(&bo->user_data_list, key);
706 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
707 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
708 _tbm_bufmgr_mutex_unlock();
712 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
714 user_data_delete(old_data);
716 _tbm_bufmgr_mutex_unlock();
722 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
724 tbm_user_data *old_data;
726 _tbm_bufmgr_mutex_lock();
727 _tbm_set_last_result(TBM_ERROR_NONE);
729 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
731 if (LIST_IS_EMPTY(&bo->user_data_list)) {
732 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
733 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
734 _tbm_bufmgr_mutex_unlock();
738 old_data = user_data_lookup(&bo->user_data_list, key);
740 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
741 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
742 _tbm_bufmgr_mutex_unlock();
746 if (old_data->data && old_data->free_func)
747 old_data->free_func(old_data->data);
748 old_data->data = data;
750 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
752 _tbm_bufmgr_mutex_unlock();
758 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
760 tbm_user_data *old_data;
762 _tbm_bufmgr_mutex_lock();
763 _tbm_set_last_result(TBM_ERROR_NONE);
765 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
767 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
768 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
769 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
770 _tbm_bufmgr_mutex_unlock();
774 old_data = user_data_lookup(&bo->user_data_list, key);
777 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
778 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
779 _tbm_bufmgr_mutex_unlock();
783 *data = old_data->data;
785 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
787 _tbm_bufmgr_mutex_unlock();
793 tbm_bo_get_flags(tbm_bo bo)
797 _tbm_bufmgr_mutex_lock();
799 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
803 TBM_TRACE_BO("bo(%p)\n", bo);
805 _tbm_bufmgr_mutex_unlock();
810 /* LCOV_EXCL_START */
811 /* internal function */
813 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
815 _tbm_bufmgr_mutex_lock();
817 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
819 bo->surface = surface;
821 _tbm_bufmgr_mutex_unlock();
827 _tbm_bo_free(tbm_bo bo)
829 /* destory the user_data_list */
830 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
831 tbm_user_data *old_data = NULL, *tmp;
833 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
834 TBM_DBG("free user_data\n");
835 user_data_delete(old_data);
838 LIST_INITHEAD(&bo->user_data_list); // TODO: remove this. build-break when it is removed.
841 while (bo->lock_cnt > 0) {
842 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
847 tbm_bo_data_free(bo->bo_data, bo->get_from_surface_data);