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.", #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.", #cond);\
50 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
51 _tbm_bufmgr_mutex_unlock();\
59 _tbm_flag_to_str(int f)
63 if (f == TBM_BO_DEFAULT)
64 snprintf(str, 255, "DEFAULT");
68 if (f & TBM_BO_SCANOUT)
69 c += snprintf(&str[c], 255-c, "SCANOUT");
71 if (f & TBM_BO_NONCACHABLE) {
72 if (c >= 0 && c < 255)
73 c += snprintf(&str[c], 255-c, ", ");
75 if (c >= 0 && c < 255)
76 c += snprintf(&str[c], 255-c, "NONCACHABLE,");
80 if (c >= 0 && c < 255)
81 c += snprintf(&str[c], 255-c, ", ");
83 if (c >= 0 && c < 255)
84 c += snprintf(&str[c], 255-c, "WC");
94 user_data_lookup(struct list_head *user_data_list, unsigned long key)
96 tbm_user_data *old_data = NULL;
98 if (LIST_IS_EMPTY(user_data_list))
101 LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
102 if (old_data->key == key)
110 user_data_create(unsigned long key, tbm_data_free data_free_func)
112 tbm_user_data *user_data;
114 user_data = calloc(1, sizeof(tbm_user_data));
116 /* LCOV_EXCL_START */
117 TBM_ERR("fail to allocate an user_date");
118 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
123 user_data->key = key;
124 user_data->free_func = data_free_func;
130 user_data_delete(tbm_user_data *user_data)
132 if (user_data->data && user_data->free_func)
133 user_data->free_func(user_data->data);
135 LIST_DEL(&user_data->item_link);
141 _bo_lock(tbm_bo bo, int device, int opt)
146 error = tbm_bo_data_lock(bo->bo_data, device, opt);
147 _tbm_set_last_result(error);
152 case TBM_ERROR_NOT_SUPPORTED:
154 _tbm_set_last_result(TBM_ERROR_NONE);
158 TBM_WRN("fail to lock. error:%d", error);
166 _bo_unlock(tbm_bo bo)
170 error = tbm_bo_data_unlock(bo->bo_data);
171 _tbm_set_last_result(error);
175 case TBM_ERROR_NOT_SUPPORTED:
176 _tbm_set_last_result(TBM_ERROR_NONE);
179 TBM_WRN("fail to lock. error:%d", error);
185 _tbm_bo_lock(tbm_bo bo, int device, int opt)
192 /* do not try to lock the bo */
193 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
196 if (bo->lock_cnt < 0) {
197 TBM_ERR("error bo:%p LOCK_CNT=%d",
204 switch (bo->bufmgr->bo_lock_type) {
205 case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
206 if (bo->lock_cnt == 0) {
207 _tbm_bufmgr_mutex_unlock();
208 ret = _bo_lock(bo, device, opt);
209 _tbm_bufmgr_mutex_lock();
215 case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
216 _tbm_bufmgr_mutex_unlock();
217 ret = _bo_lock(bo, device, opt);
218 _tbm_bufmgr_mutex_lock();
223 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.",
224 bo, bo->bufmgr->bo_lock_type);
229 TBM_DBG(">> LOCK bo:%p(%d->%d)", bo, old, bo->lock_cnt);
235 _tbm_bo_unlock(tbm_bo bo)
239 /* do not try to unlock the bo */
240 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
245 switch (bo->bufmgr->bo_lock_type) {
246 case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
247 if (bo->lock_cnt > 0) {
249 if (bo->lock_cnt == 0)
253 case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
254 if (bo->lock_cnt > 0) {
260 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.",
261 bo, bo->bufmgr->bo_lock_type);
265 if (bo->lock_cnt < 0)
268 TBM_DBG(">> UNLOCK bo:%p(%d->%d)", bo, old, bo->lock_cnt);
272 _tbm_bo_magic_check(tbm_bo bo)
274 if (bo->magic != TBM_BO_MAGIC)
281 _tbm_bo_is_valid(tbm_bo bo)
284 TBM_ERR("error: bo is NULL.");
288 if (!_tbm_bo_magic_check(bo)) {
289 TBM_ERR("error: No valid bo(%p).", bo);
297 _tbm_bo_deinit(tbm_bo bo)
301 bo->bufmgr->bo_cnt--;
302 LIST_DEL(&bo->item_link);
306 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
310 bo = tbm_bufmgr_internal_alloc_bo(bufmgr, size, flags);
312 /* LCOV_EXCL_START */
313 TBM_ERR("tbm_bufmgr_internal_alloc_bo failed.");
322 tbm_bo_ref(tbm_bo bo)
324 _tbm_bufmgr_mutex_lock();
325 _tbm_set_last_result(TBM_ERROR_NONE);
327 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
331 TBM_TRACE_BO("bo(%p) ref_cnt(%d)", bo, bo->ref_cnt);
333 _tbm_bufmgr_mutex_unlock();
339 tbm_bo_unref(tbm_bo bo)
341 _tbm_bufmgr_mutex_lock();
342 _tbm_set_last_result(TBM_ERROR_NONE);
344 TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
346 TBM_TRACE_BO("bo(%p) ref_cnt(%d)", bo, bo->ref_cnt - 1);
348 if (bo->ref_cnt <= 0) {
349 _tbm_bufmgr_mutex_unlock();
354 if (bo->ref_cnt == 0)
357 _tbm_bufmgr_mutex_unlock();
361 tbm_bo_map(tbm_bo bo, int device, int opt)
363 tbm_bo_handle bo_handle;
366 _tbm_bufmgr_mutex_lock();
367 _tbm_set_last_result(TBM_ERROR_NONE);
369 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
371 if (!_tbm_bo_lock(bo, device, opt)) {
372 TBM_ERR("error: fail to lock bo:%p)", bo);
373 _tbm_bufmgr_mutex_unlock();
374 return (tbm_bo_handle) NULL;
377 bo_handle = tbm_bo_data_map(bo->bo_data, device, opt, &error);
378 if (bo_handle.ptr == NULL) {
379 /* LCOV_EXCL_START */
380 TBM_ERR("error: fail to map bo:%p error:%d", bo, error);
382 _tbm_set_last_result(error);
383 _tbm_bufmgr_mutex_unlock();
384 return (tbm_bo_handle) NULL;
388 /* increase the map_count */
391 TBM_TRACE_BO("bo(%p) map_cnt(%d)", bo, bo->map_cnt);
393 _tbm_bufmgr_mutex_unlock();
399 tbm_bo_unmap(tbm_bo bo)
403 _tbm_bufmgr_mutex_lock();
404 _tbm_set_last_result(TBM_ERROR_NONE);
406 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
407 TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
409 error = tbm_bo_data_unmap(bo->bo_data);
410 if (error != TBM_ERROR_NONE) {
411 /* LCOV_EXCL_START */
412 TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)", bo, bo->map_cnt, error);
413 _tbm_set_last_result(error);
414 _tbm_bufmgr_mutex_unlock();
419 /* decrease the map_count */
422 TBM_TRACE_BO("bo(%p) map_cnt(%d)", bo, bo->map_cnt);
426 _tbm_bufmgr_mutex_unlock();
432 tbm_bo_get_handle(tbm_bo bo, int device)
434 tbm_bo_handle bo_handle;
437 _tbm_bufmgr_mutex_lock();
438 _tbm_set_last_result(TBM_ERROR_NONE);
440 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
442 bo_handle = tbm_bo_data_get_handle(bo->bo_data, device, &error);
443 if (bo_handle.ptr == NULL) {
444 /* LCOV_EXCL_START */
445 TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)", bo, bo_handle.ptr, error);
446 _tbm_set_last_result(error);
447 _tbm_bufmgr_mutex_unlock();
448 return (tbm_bo_handle)NULL;
452 TBM_TRACE_BO("bo(%p) bo_handle(%p)", bo, bo_handle.ptr);
454 _tbm_bufmgr_mutex_unlock();
460 tbm_bo_export(tbm_bo bo)
465 _tbm_bufmgr_mutex_lock();
466 _tbm_set_last_result(TBM_ERROR_NONE);
468 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
470 ret = tbm_bo_data_export_key(bo->bo_data, &error);
472 /* LCOV_EXCL_START */
473 TBM_ERR("tbm_moule_bo_export_key failed. bo:%p tbm_key:%d error:%d", bo, ret, error);
474 _tbm_set_last_result(error);
475 _tbm_bufmgr_mutex_unlock();
480 TBM_TRACE_BO("bo:%p tbm_key:%u", bo, ret);
482 _tbm_bufmgr_mutex_unlock();
488 tbm_bo_export_fd(tbm_bo bo)
493 _tbm_bufmgr_mutex_lock();
494 _tbm_set_last_result(TBM_ERROR_NONE);
496 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
498 fd = tbm_bo_data_export_fd(bo->bo_data, &error);
500 /* LCOV_EXCL_START */
501 TBM_ERR("tbm_bo_data_export_fd filed. bo:%p tbm_fd:%d error:%d", bo, fd, error);
502 _tbm_set_last_result(error);
503 _tbm_bufmgr_mutex_unlock();
508 TBM_TRACE_BO("bo:%p tbm_fd:%d", bo, fd);
510 _tbm_bufmgr_mutex_unlock();
516 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
520 bo = tbm_bufmgr_internal_import_bo_with_key(bufmgr, key);
522 /* LCOV_EXCL_START */
523 TBM_ERR("tbm_bufmgr_internal_import_bo_with_key failed");
532 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
536 bo = tbm_bufmgr_internal_import_bo_with_fd(bufmgr, fd);
538 /* LCOV_EXCL_START */
539 TBM_ERR("tbm_bufmgr_internal_import_fd failed.");
548 tbm_bo_size(tbm_bo bo)
553 _tbm_bufmgr_mutex_lock();
554 _tbm_set_last_result(TBM_ERROR_NONE);
556 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
558 size = tbm_bo_data_get_size(bo->bo_data, &error);
559 _tbm_set_last_result(error);
561 TBM_TRACE_BO("bo(%p) size(%d)", bo, size);
563 _tbm_bufmgr_mutex_unlock();
569 tbm_bo_locked(tbm_bo bo)
571 _tbm_bufmgr_mutex_lock();
572 _tbm_set_last_result(TBM_ERROR_NONE);
574 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
576 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
577 TBM_ERR("bo(%p) lock_cnt(%d)", bo, bo->lock_cnt);
578 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
579 _tbm_bufmgr_mutex_unlock();
583 if (bo->lock_cnt > 0) {
584 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)", bo, bo->lock_cnt);
585 _tbm_bufmgr_mutex_unlock();
589 TBM_TRACE_BO("bo(%p) lock_cnt(%d)", bo, bo->lock_cnt);
590 _tbm_bufmgr_mutex_unlock();
596 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
598 tbm_error_e error1, error2;
599 int size1 = -1, size2 = -2;
602 _tbm_bufmgr_mutex_lock();
603 _tbm_set_last_result(TBM_ERROR_NONE);
605 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
606 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
608 TBM_TRACE_BO("before: bo1(%p) bo2(%p)", bo1, bo2);
610 size1 = tbm_bo_data_get_size(bo1->bo_data, &error1);
611 _tbm_set_last_result(error1);
612 size2 = tbm_bo_data_get_size(bo2->bo_data, &error2);
613 _tbm_set_last_result(error2);
615 if (size1 != size2) {
616 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
617 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
622 bo1->bo_data = bo2->bo_data;
625 TBM_TRACE_BO("after: bo1(%p) bo2(%p)", bo1, bo2);
627 _tbm_bufmgr_mutex_unlock();
632 TBM_ERR("error: bo1(%p) bo2(%p)", bo1, bo2);
633 _tbm_bufmgr_mutex_unlock();
639 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
640 tbm_data_free data_free_func)
644 _tbm_bufmgr_mutex_lock();
645 _tbm_set_last_result(TBM_ERROR_NONE);
647 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
649 /* check if the data according to the key exist if so, return false. */
650 data = user_data_lookup(&bo->user_data_list, key);
652 TBM_TRACE_BO("warning: user data already exist key(%ld)", key);
653 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
654 _tbm_bufmgr_mutex_unlock();
658 data = user_data_create(key, data_free_func);
660 TBM_ERR("error: bo(%p) key(%lu)", bo, key);
661 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
662 _tbm_bufmgr_mutex_unlock();
666 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)", bo, key, data->data);
668 LIST_ADD(&data->item_link, &bo->user_data_list);
670 _tbm_bufmgr_mutex_unlock();
676 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
678 tbm_user_data *old_data;
680 _tbm_bufmgr_mutex_lock();
681 _tbm_set_last_result(TBM_ERROR_NONE);
683 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
685 if (LIST_IS_EMPTY(&bo->user_data_list)) {
686 TBM_TRACE_BO("bo(%p) key(%lu)", bo, key);
687 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
688 _tbm_bufmgr_mutex_unlock();
692 old_data = user_data_lookup(&bo->user_data_list, key);
694 TBM_TRACE_BO("bo(%p) key(%lu)", bo, key);
695 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
696 _tbm_bufmgr_mutex_unlock();
700 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)", bo, key, old_data->data);
702 user_data_delete(old_data);
704 _tbm_bufmgr_mutex_unlock();
710 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
712 tbm_user_data *old_data;
714 _tbm_bufmgr_mutex_lock();
715 _tbm_set_last_result(TBM_ERROR_NONE);
717 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
719 if (LIST_IS_EMPTY(&bo->user_data_list)) {
720 TBM_TRACE_BO("error: bo(%p) key(%lu)", bo, key);
721 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
722 _tbm_bufmgr_mutex_unlock();
726 old_data = user_data_lookup(&bo->user_data_list, key);
728 TBM_TRACE_BO("error: bo(%p) key(%lu)", bo, key);
729 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
730 _tbm_bufmgr_mutex_unlock();
734 if (old_data->data && old_data->free_func)
735 old_data->free_func(old_data->data);
736 old_data->data = data;
738 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)", bo, key, old_data->data);
740 _tbm_bufmgr_mutex_unlock();
746 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
748 tbm_user_data *old_data;
750 _tbm_bufmgr_mutex_lock();
751 _tbm_set_last_result(TBM_ERROR_NONE);
753 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
755 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
756 TBM_TRACE_BO("error: bo(%p) key(%lu)", bo, key);
757 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
758 _tbm_bufmgr_mutex_unlock();
762 old_data = user_data_lookup(&bo->user_data_list, key);
765 TBM_TRACE_BO("error: bo(%p) key(%lu)", bo, key);
766 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
767 _tbm_bufmgr_mutex_unlock();
771 *data = old_data->data;
773 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)", bo, key, old_data->data);
775 _tbm_bufmgr_mutex_unlock();
781 tbm_bo_get_flags(tbm_bo bo)
786 _tbm_bufmgr_mutex_lock();
787 _tbm_set_last_result(TBM_ERROR_NONE);
789 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
791 flags = tbm_bo_data_get_memory_types(bo->bo_data, &error);
792 if (error != TBM_ERROR_NONE) {
793 TBM_ERR("tbm_bo_data_get_memory_types filed.");
794 flags = TBM_BO_DEFAULT;
795 _tbm_set_last_result(error);
798 TBM_TRACE_BO("bo(%p)", bo);
800 _tbm_bufmgr_mutex_unlock();
805 /* LCOV_EXCL_START */
806 /* internal function */
808 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
810 _tbm_bufmgr_mutex_lock();
812 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
814 bo->surface = surface;
816 _tbm_bufmgr_mutex_unlock();
822 _tbm_bo_free(tbm_bo bo)
824 /* destory the user_data_list */
825 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
826 tbm_user_data *old_data = NULL, *tmp;
828 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
829 TBM_DBG("free user_data");
830 user_data_delete(old_data);
833 LIST_INITHEAD(&bo->user_data_list); // TODO: remove this. build-break when it is removed.
836 while (bo->lock_cnt > 0) {
837 TBM_ERR("error lock_cnt:%d", bo->lock_cnt);
842 tbm_bo_data_free(bo->bo_data, bo->get_from_surface_data);