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)
308 bo = tbm_bufmgr_internal_alloc_bo(bufmgr, size, flags);
310 /* LCOV_EXCL_START */
311 TBM_ERR("tbm_bufmgr_internal_alloc_bo failed.");
320 tbm_bo_ref(tbm_bo bo)
322 _tbm_bufmgr_mutex_lock();
323 _tbm_set_last_result(TBM_ERROR_NONE);
325 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
329 TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
331 _tbm_bufmgr_mutex_unlock();
337 tbm_bo_unref(tbm_bo bo)
339 _tbm_bufmgr_mutex_lock();
340 _tbm_set_last_result(TBM_ERROR_NONE);
342 TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
344 TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
346 if (bo->ref_cnt <= 0) {
347 _tbm_bufmgr_mutex_unlock();
352 if (bo->ref_cnt == 0)
355 _tbm_bufmgr_mutex_unlock();
359 tbm_bo_map(tbm_bo bo, int device, int opt)
361 tbm_bo_handle bo_handle;
364 _tbm_bufmgr_mutex_lock();
365 _tbm_set_last_result(TBM_ERROR_NONE);
367 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
369 if (!_tbm_bo_lock(bo, device, opt)) {
370 TBM_ERR("error: fail to lock bo:%p)\n", bo);
371 _tbm_bufmgr_mutex_unlock();
372 return (tbm_bo_handle) NULL;
375 bo_handle = tbm_bo_data_map(bo->bo_data, device, opt, &error);
376 if (bo_handle.ptr == NULL) {
377 /* LCOV_EXCL_START */
378 TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
379 _tbm_set_last_result(error);
381 _tbm_bufmgr_mutex_unlock();
382 return (tbm_bo_handle) NULL;
386 /* increase the map_count */
389 TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
391 _tbm_bufmgr_mutex_unlock();
397 tbm_bo_unmap(tbm_bo bo)
401 _tbm_bufmgr_mutex_lock();
402 _tbm_set_last_result(TBM_ERROR_NONE);
404 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
405 TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
407 error = tbm_bo_data_unmap(bo->bo_data);
408 if (error != TBM_ERROR_NONE) {
409 /* LCOV_EXCL_START */
410 TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
411 _tbm_set_last_result(error);
412 _tbm_bufmgr_mutex_unlock();
417 /* decrease the map_count */
420 TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
424 _tbm_bufmgr_mutex_unlock();
430 tbm_bo_get_handle(tbm_bo bo, int device)
432 tbm_bo_handle bo_handle;
435 _tbm_bufmgr_mutex_lock();
436 _tbm_set_last_result(TBM_ERROR_NONE);
438 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
440 bo_handle = tbm_bo_data_get_handle(bo->bo_data, device, &error);
441 if (bo_handle.ptr == NULL) {
442 /* LCOV_EXCL_START */
443 TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
444 _tbm_set_last_result(error);
445 _tbm_bufmgr_mutex_unlock();
446 return (tbm_bo_handle)NULL;
450 TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
452 _tbm_bufmgr_mutex_unlock();
458 tbm_bo_export(tbm_bo bo)
463 _tbm_bufmgr_mutex_lock();
464 _tbm_set_last_result(TBM_ERROR_NONE);
466 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
468 ret = tbm_bo_data_export_key(bo->bo_data, &error);
470 /* LCOV_EXCL_START */
471 TBM_ERR("tbm_moule_bo_export_key failed. bo:%p tbm_key:%d error:%d", bo, ret, error);
472 _tbm_set_last_result(error);
473 _tbm_bufmgr_mutex_unlock();
478 TBM_TRACE_BO("bo:%p tbm_key:%u", bo, ret);
480 _tbm_bufmgr_mutex_unlock();
486 tbm_bo_export_fd(tbm_bo bo)
491 _tbm_bufmgr_mutex_lock();
492 _tbm_set_last_result(TBM_ERROR_NONE);
494 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
496 fd = tbm_bo_data_export_fd(bo->bo_data, &error);
498 /* LCOV_EXCL_START */
499 TBM_ERR("tbm_bo_data_export_fd filed. bo:%p tbm_fd:%d error:%d", bo, fd, error);
500 _tbm_set_last_result(error);
501 _tbm_bufmgr_mutex_unlock();
506 TBM_TRACE_BO("bo:%p tbm_fd:%d", bo, fd);
508 _tbm_bufmgr_mutex_unlock();
514 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
518 bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key);
520 /* LCOV_EXCL_START */
521 TBM_ERR("tbm_bufmgr_internal_import_bo_with_key failed");
530 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
534 bo = tbm_bufmgr_internal_import_bo_with_fd(bufmgr, fd);
536 /* LCOV_EXCL_START */
537 TBM_ERR("tbm_bufmgr_internal_import_fd failed.");
546 tbm_bo_size(tbm_bo bo)
551 _tbm_bufmgr_mutex_lock();
552 _tbm_set_last_result(TBM_ERROR_NONE);
554 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
556 size = tbm_bo_data_get_size(bo->bo_data, &error);
557 _tbm_set_last_result(error);
559 TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
561 _tbm_bufmgr_mutex_unlock();
567 tbm_bo_locked(tbm_bo bo)
569 _tbm_bufmgr_mutex_lock();
570 _tbm_set_last_result(TBM_ERROR_NONE);
572 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
574 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
575 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
576 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
577 _tbm_bufmgr_mutex_unlock();
581 if (bo->lock_cnt > 0) {
582 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
583 _tbm_bufmgr_mutex_unlock();
587 TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
588 _tbm_bufmgr_mutex_unlock();
594 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
596 tbm_error_e error1, error2;
597 int size1 = -1, size2 = -2;
600 _tbm_bufmgr_mutex_lock();
601 _tbm_set_last_result(TBM_ERROR_NONE);
603 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
604 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
606 TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
608 size1 = tbm_bo_data_get_size(bo1->bo_data, &error1);
609 _tbm_set_last_result(error1);
610 size2 = tbm_bo_data_get_size(bo2->bo_data, &error2);
611 _tbm_set_last_result(error2);
613 if (size1 != size2) {
614 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
615 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
620 bo1->bo_data = bo2->bo_data;
623 TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
625 _tbm_bufmgr_mutex_unlock();
630 TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
631 _tbm_bufmgr_mutex_unlock();
637 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
638 tbm_data_free data_free_func)
642 _tbm_bufmgr_mutex_lock();
643 _tbm_set_last_result(TBM_ERROR_NONE);
645 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
647 /* check if the data according to the key exist if so, return false. */
648 data = user_data_lookup(&bo->user_data_list, key);
650 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
651 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
652 _tbm_bufmgr_mutex_unlock();
656 data = user_data_create(key, data_free_func);
658 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
659 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
660 _tbm_bufmgr_mutex_unlock();
664 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
666 LIST_ADD(&data->item_link, &bo->user_data_list);
668 _tbm_bufmgr_mutex_unlock();
674 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
676 tbm_user_data *old_data;
678 _tbm_bufmgr_mutex_lock();
679 _tbm_set_last_result(TBM_ERROR_NONE);
681 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
683 if (LIST_IS_EMPTY(&bo->user_data_list)) {
684 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
685 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
686 _tbm_bufmgr_mutex_unlock();
690 old_data = user_data_lookup(&bo->user_data_list, key);
692 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
693 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
694 _tbm_bufmgr_mutex_unlock();
698 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
700 user_data_delete(old_data);
702 _tbm_bufmgr_mutex_unlock();
708 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
710 tbm_user_data *old_data;
712 _tbm_bufmgr_mutex_lock();
713 _tbm_set_last_result(TBM_ERROR_NONE);
715 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
717 if (LIST_IS_EMPTY(&bo->user_data_list)) {
718 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
719 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
720 _tbm_bufmgr_mutex_unlock();
724 old_data = user_data_lookup(&bo->user_data_list, key);
726 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
727 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
728 _tbm_bufmgr_mutex_unlock();
732 if (old_data->data && old_data->free_func)
733 old_data->free_func(old_data->data);
734 old_data->data = data;
736 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
738 _tbm_bufmgr_mutex_unlock();
744 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
746 tbm_user_data *old_data;
748 _tbm_bufmgr_mutex_lock();
749 _tbm_set_last_result(TBM_ERROR_NONE);
751 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
753 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
754 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
755 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
756 _tbm_bufmgr_mutex_unlock();
760 old_data = user_data_lookup(&bo->user_data_list, key);
763 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
764 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
765 _tbm_bufmgr_mutex_unlock();
769 *data = old_data->data;
771 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
773 _tbm_bufmgr_mutex_unlock();
779 tbm_bo_get_flags(tbm_bo bo)
783 _tbm_bufmgr_mutex_lock();
785 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
789 TBM_TRACE_BO("bo(%p)\n", bo);
791 _tbm_bufmgr_mutex_unlock();
796 /* LCOV_EXCL_START */
797 /* internal function */
799 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
801 _tbm_bufmgr_mutex_lock();
803 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
805 bo->surface = surface;
807 _tbm_bufmgr_mutex_unlock();
813 _tbm_bo_free(tbm_bo bo)
815 /* destory the user_data_list */
816 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
817 tbm_user_data *old_data = NULL, *tmp;
819 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
820 TBM_DBG("free user_data\n");
821 user_data_delete(old_data);
824 LIST_INITHEAD(&bo->user_data_list); // TODO: remove this. build-break when it is removed.
827 while (bo->lock_cnt > 0) {
828 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
833 tbm_bo_data_free(bo->bo_data, bo->get_from_surface_data);