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"
37 static pthread_mutex_t tbm_bo_lock = PTHREAD_MUTEX_INITIALIZER;
38 static void _tbm_bo_mutex_unlock(void);
41 #define TBM_BO_RETURN_IF_FAIL(cond) {\
43 TBM_ERR("'%s' failed.\n", #cond);\
44 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
45 _tbm_bo_mutex_unlock();\
50 #define TBM_BO_RETURN_VAL_IF_FAIL(cond, val) {\
52 TBM_ERR("'%s' failed.\n", #cond);\
53 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
54 _tbm_bo_mutex_unlock();\
61 _tbm_bo_mutex_init(void)
63 static bool tbm_bo_mutex_init = false;
65 if (tbm_bo_mutex_init)
68 if (pthread_mutex_init(&tbm_bo_lock, NULL)) {
69 TBM_ERR("fail: Cannot pthread_mutex_init for tbm_bo_lock.\n");
73 tbm_bo_mutex_init = true;
79 _tbm_bo_mutex_lock(void)
81 if (!_tbm_bo_mutex_init()) {
82 TBM_ERR("fail: _tbm_bo_mutex_init()\n");
86 pthread_mutex_lock(&tbm_bo_lock);
90 _tbm_bo_mutex_unlock(void)
92 pthread_mutex_unlock(&tbm_bo_lock);
96 _tbm_flag_to_str(int f)
100 if (f == TBM_BO_DEFAULT)
101 snprintf(str, 255, "DEFAULT");
105 if (f & TBM_BO_SCANOUT)
106 c += snprintf(&str[c], 255-c, "SCANOUT");
108 if (f & TBM_BO_NONCACHABLE) {
109 if (c >= 0 && c < 255)
110 c += snprintf(&str[c], 255-c, ", ");
112 if (c >= 0 && c < 255)
113 c += snprintf(&str[c], 255-c, "NONCACHABLE,");
117 if (c >= 0 && c < 255)
118 c += snprintf(&str[c], 255-c, ", ");
120 if (c >= 0 && c < 255)
121 c += snprintf(&str[c], 255-c, "WC");
129 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
131 static int last_chk_bo_cnt = 0;
133 if ((bufmgr->bo_cnt >= 500) && ((bufmgr->bo_cnt % 20) == 0) &&
134 (bufmgr->bo_cnt > last_chk_bo_cnt)) {
135 TBM_DBG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
136 tbm_bufmgr_debug_show(bufmgr);
137 last_chk_bo_cnt = bufmgr->bo_cnt;
143 user_data_lookup(struct list_head *user_data_list, unsigned long key)
145 tbm_user_data *old_data = NULL;
147 if (LIST_IS_EMPTY(user_data_list))
150 LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
151 if (old_data->key == key)
159 user_data_create(unsigned long key, tbm_data_free data_free_func)
161 tbm_user_data *user_data;
163 user_data = calloc(1, sizeof(tbm_user_data));
165 /* LCOV_EXCL_START */
166 TBM_ERR("fail to allocate an user_date\n");
167 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
172 user_data->key = key;
173 user_data->free_func = data_free_func;
179 user_data_delete(tbm_user_data *user_data)
181 if (user_data->data && user_data->free_func)
182 user_data->free_func(user_data->data);
184 LIST_DEL(&user_data->item_link);
190 _bo_lock(tbm_bo bo, int device, int opt)
195 if (bo->bufmgr->backend_module_data) {
196 if (bo->bufmgr->bo_func->bo_lock) {
197 error = bo->bufmgr->bo_func->bo_lock(bo->bo_data, device, opt);
198 if (error != TBM_ERROR_NONE) {
199 TBM_WRN("fail to lock");
200 _tbm_set_last_result(error);
205 if (bo->bufmgr->backend->bo_lock) {
206 ret = bo->bufmgr->backend->bo_lock(bo, device, opt);
208 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
216 _bo_unlock(tbm_bo bo)
220 if (bo->bufmgr->backend_module_data) {
221 if (bo->bufmgr->bo_func->bo_unlock) {
222 error = bo->bufmgr->bo_func->bo_unlock(bo->bo_data);
223 if (error != TBM_ERROR_NONE) {
224 TBM_WRN("fail to unlock");
225 _tbm_set_last_result(error);
229 if (bo->bufmgr->backend->bo_unlock)
230 bo->bufmgr->backend->bo_unlock(bo);
235 _tbm_bo_lock(tbm_bo bo, int device, int opt)
242 /* do not try to lock the bo */
243 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
246 if (bo->lock_cnt < 0) {
247 TBM_ERR("error bo:%p LOCK_CNT=%d\n",
254 switch (bo->bufmgr->bo_lock_type) {
255 case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
256 if (bo->lock_cnt == 0) {
257 _tbm_bo_mutex_unlock();
258 ret = _bo_lock(bo, device, opt);
259 _tbm_bo_mutex_lock();
265 case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
266 _tbm_bo_mutex_unlock();
267 ret = _bo_lock(bo, device, opt);
268 _tbm_bo_mutex_lock();
273 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
274 bo, bo->bufmgr->bo_lock_type);
279 TBM_DBG(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
285 _tbm_bo_unlock(tbm_bo bo)
289 /* do not try to unlock the bo */
290 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER)
295 switch (bo->bufmgr->bo_lock_type) {
296 case TBM_BUFMGR_BO_LOCK_TYPE_ONCE:
297 if (bo->lock_cnt > 0) {
299 if (bo->lock_cnt == 0)
303 case TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS:
304 if (bo->lock_cnt > 0) {
310 TBM_ERR("error bo:%p bo_lock_type[%d] is wrong.\n",
311 bo, bo->bufmgr->bo_lock_type);
315 if (bo->lock_cnt < 0)
318 TBM_DBG(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
322 _tbm_bo_is_valid(tbm_bo bo)
324 tbm_bufmgr bufmgr = NULL;
325 tbm_bo old_data = NULL;
328 TBM_ERR("error: bo is NULL.\n");
332 bufmgr = tbm_bufmgr_get();
333 if (bufmgr == NULL) {
334 TBM_ERR("error: bufmgr is NULL.\n");
338 if (LIST_IS_EMPTY(&bufmgr->bo_list)) {
339 TBM_ERR("error: bo->bo->bufmgr->bo_list is EMPTY.\n");
343 LIST_FOR_EACH_ENTRY(old_data, &bufmgr->bo_list, item_link) {
348 TBM_ERR("error: No valid bo(%p).\n", bo);
354 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
358 tbm_backend_bo_data *bo_data;
361 _tbm_bo_mutex_lock();
362 _tbm_set_last_result(TBM_ERROR_NONE);
364 TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
365 TBM_BO_RETURN_VAL_IF_FAIL(size > 0, NULL);
367 bo = calloc(1, sizeof(struct _tbm_bo));
369 /* LCOV_EXCL_START */
370 TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n",
371 size, _tbm_flag_to_str(flags));
372 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
373 _tbm_bo_mutex_unlock();
378 _tbm_util_check_bo_cnt(bufmgr);
382 if (bufmgr->backend_module_data) {
383 bo_data = bufmgr->bufmgr_func->bufmgr_alloc_bo(bufmgr->bufmgr_data, (unsigned int)size, flags, &error);
385 /* LCOV_EXCL_START */
386 TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n",
387 size, _tbm_flag_to_str(flags));
388 _tbm_set_last_result(error);
390 _tbm_bo_mutex_unlock();
394 bo->bo_data = bo_data;
396 bo_priv = bo->bufmgr->backend->bo_alloc(bo, size, flags);
398 /* LCOV_EXCL_START */
399 TBM_ERR("error: fail to create of tbm_bo size(%d) flag(%s)\n",
400 size, _tbm_flag_to_str(flags));
401 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
403 _tbm_bo_mutex_unlock();
410 bo->bufmgr->bo_cnt++;
414 TBM_TRACE_BO("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
415 _tbm_flag_to_str(bo->flags));
417 LIST_INITHEAD(&bo->user_data_list);
419 LIST_ADD(&bo->item_link, &bo->bufmgr->bo_list);
421 _tbm_bo_mutex_unlock();
427 tbm_bo_ref(tbm_bo bo)
429 _tbm_bo_mutex_lock();
430 _tbm_set_last_result(TBM_ERROR_NONE);
432 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
436 TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
438 _tbm_bo_mutex_unlock();
444 tbm_bo_unref(tbm_bo bo)
446 _tbm_bo_mutex_lock();
447 _tbm_set_last_result(TBM_ERROR_NONE);
449 TBM_BO_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
451 TBM_TRACE_BO("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
453 if (bo->ref_cnt <= 0) {
454 _tbm_bo_mutex_unlock();
459 if (bo->ref_cnt == 0)
462 _tbm_bo_mutex_unlock();
466 tbm_bo_map(tbm_bo bo, int device, int opt)
468 tbm_bo_handle bo_handle;
471 _tbm_bo_mutex_lock();
472 _tbm_set_last_result(TBM_ERROR_NONE);
474 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
476 if (!_tbm_bo_lock(bo, device, opt)) {
477 TBM_ERR("error: fail to lock bo:%p)\n", bo);
478 _tbm_bo_mutex_unlock();
479 return (tbm_bo_handle) NULL;
482 if (bo->bufmgr->backend_module_data) {
483 bo_handle = bo->bufmgr->bo_func->bo_map(bo->bo_data, device, opt, &error);
484 if (bo_handle.ptr == NULL) {
485 /* LCOV_EXCL_START */
486 _tbm_set_last_result(error);
487 TBM_ERR("error: fail to map bo:%p error:%d\n", bo, error);
489 _tbm_bo_mutex_unlock();
490 return (tbm_bo_handle) NULL;
494 bo_handle = bo->bufmgr->backend->bo_map(bo, device, opt);
495 if (bo_handle.ptr == NULL) {
496 /* LCOV_EXCL_START */
497 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
498 TBM_ERR("error: fail to map bo:%p\n", bo);
500 _tbm_bo_mutex_unlock();
501 return (tbm_bo_handle) NULL;
506 /* increase the map_count */
509 TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
511 _tbm_bo_mutex_unlock();
517 tbm_bo_unmap(tbm_bo bo)
522 _tbm_bo_mutex_lock();
523 _tbm_set_last_result(TBM_ERROR_NONE);
525 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
526 TBM_BO_RETURN_VAL_IF_FAIL(bo->map_cnt > 0, 0);
528 if (bo->bufmgr->backend_module_data) {
529 error = bo->bufmgr->bo_func->bo_unmap(bo->bo_data);
530 if (error != TBM_ERROR_NONE) {
531 /* LCOV_EXCL_START */
532 TBM_ERR("error: bo(%p) map_cnt(%d) error(%d)\n", bo, bo->map_cnt, error);
533 _tbm_set_last_result(error);
535 _tbm_bo_mutex_unlock();
540 ret = bo->bufmgr->backend->bo_unmap(bo);
542 /* LCOV_EXCL_START */
543 TBM_ERR("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
544 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
545 _tbm_bo_mutex_unlock();
551 /* decrease the map_count */
554 TBM_TRACE_BO("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
558 _tbm_bo_mutex_unlock();
564 tbm_bo_get_handle(tbm_bo bo, int device)
566 tbm_bo_handle bo_handle;
569 _tbm_bo_mutex_lock();
570 _tbm_set_last_result(TBM_ERROR_NONE);
572 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
574 if (bo->bufmgr->backend_module_data) {
575 bo_handle = bo->bufmgr->bo_func->bo_get_handle(bo->bo_data, device, &error);
576 if (bo_handle.ptr == NULL) {
577 /* LCOV_EXCL_START */
578 TBM_ERR("error: bo(%p) bo_handle(%p) error(%d)\n", bo, bo_handle.ptr, error);
579 _tbm_set_last_result(error);
580 _tbm_bo_mutex_unlock();
581 return (tbm_bo_handle) NULL;
585 bo_handle = bo->bufmgr->backend->bo_get_handle(bo, device);
586 if (bo_handle.ptr == NULL) {
587 /* LCOV_EXCL_START */
588 TBM_ERR("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
589 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
590 _tbm_bo_mutex_unlock();
591 return (tbm_bo_handle) NULL;
596 TBM_TRACE_BO("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
598 _tbm_bo_mutex_unlock();
604 tbm_bo_export(tbm_bo bo)
609 _tbm_bo_mutex_lock();
610 _tbm_set_last_result(TBM_ERROR_NONE);
612 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
614 if (bo->bufmgr->backend_module_data) {
615 if (!bo->bufmgr->bo_func->bo_export_key) {
616 /* LCOV_EXCL_START */
617 _tbm_bo_mutex_unlock();
618 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
623 ret = bo->bufmgr->bo_func->bo_export_key(bo->bo_data, &error);
625 /* LCOV_EXCL_START */
626 TBM_ERR("error: bo(%p) tbm_key(%d) error(%d)\n", bo, ret, error);
627 _tbm_set_last_result(error);
628 _tbm_bo_mutex_unlock();
633 if (!bo->bufmgr->backend->bo_export) {
634 /* LCOV_EXCL_START */
635 _tbm_bo_mutex_unlock();
636 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
641 ret = bo->bufmgr->backend->bo_export(bo);
643 /* LCOV_EXCL_START */
644 TBM_ERR("error: bo(%p) tbm_key(%d)\n", bo, ret);
645 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
646 _tbm_bo_mutex_unlock();
652 TBM_TRACE_BO("bo(%p) tbm_key(%u)\n", bo, ret);
654 _tbm_bo_mutex_unlock();
660 tbm_bo_export_fd(tbm_bo bo)
665 _tbm_bo_mutex_lock();
666 _tbm_set_last_result(TBM_ERROR_NONE);
668 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
670 if (bo->bufmgr->backend_module_data) {
671 if (!bo->bufmgr->bo_func->bo_export_fd) {
672 /* LCOV_EXCL_START */
673 _tbm_bo_mutex_unlock();
674 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
679 ret = bo->bufmgr->bo_func->bo_export_fd(bo->bo_data, &error);
681 /* LCOV_EXCL_START */
682 TBM_ERR("error: bo(%p) tbm_fd(%d) error(%d)\n", bo, ret, error);
683 _tbm_set_last_result(error);
684 _tbm_bo_mutex_unlock();
689 if (!bo->bufmgr->backend->bo_export_fd) {
690 /* LCOV_EXCL_START */
691 _tbm_bo_mutex_unlock();
692 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
697 ret = bo->bufmgr->backend->bo_export_fd(bo);
699 /* LCOV_EXCL_START */
700 TBM_ERR("error: bo(%p) tbm_fd(%d)\n", bo, ret);
701 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
702 _tbm_bo_mutex_unlock();
708 TBM_TRACE_BO("bo(%p) tbm_fd(%d)\n", bo, ret);
710 _tbm_bo_mutex_unlock();
716 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
722 tbm_backend_bo_data *bo_data;
724 _tbm_bo_mutex_lock();
725 _tbm_set_last_result(TBM_ERROR_NONE);
727 TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
729 if (bufmgr->backend_module_data) {
730 if (!bufmgr->bufmgr_func->bufmgr_import_key) {
731 /* LCOV_EXCL_START */
732 _tbm_bo_mutex_unlock();
733 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
738 if (!bufmgr->backend->bo_import) {
739 /* LCOV_EXCL_START */
740 _tbm_bo_mutex_unlock();
741 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
747 _tbm_util_check_bo_cnt(bufmgr);
749 bo = calloc(1, sizeof(struct _tbm_bo));
751 /* LCOV_EXCL_START */
752 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
753 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
754 _tbm_bo_mutex_unlock();
761 if (bo->bufmgr->backend_module_data) {
762 bo_data = bo->bufmgr->bufmgr_func->bufmgr_import_key(bufmgr->bufmgr_data, key, &error);
764 /* LCOV_EXCL_START */
765 TBM_ERR("error: fail to import of tbm_bo by key(%d). error(%d)\n", key, error);
766 _tbm_set_last_result(error);
768 _tbm_bo_mutex_unlock();
773 if (!LIST_IS_EMPTY(&bo->bufmgr->bo_list)) {
774 LIST_FOR_EACH_ENTRY(bo2, &bo->bufmgr->bo_list, item_link) {
775 if (bo2->bo_data == bo_data) {
776 TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
777 bo2, bo2->ref_cnt, key,
778 _tbm_flag_to_str(bo2->flags));
781 _tbm_bo_mutex_unlock();
786 bo->bo_data = bo_data;
788 bo_priv = bo->bufmgr->backend->bo_import(bo, key);
790 /* LCOV_EXCL_START */
791 TBM_ERR("error: fail to import of tbm_bo by key(%d)\n", key);
792 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
794 _tbm_bo_mutex_unlock();
799 if (!LIST_IS_EMPTY(&bo->bufmgr->bo_list)) {
800 LIST_FOR_EACH_ENTRY(bo2, &bo->bufmgr->bo_list, item_link) {
801 if (bo2->priv == bo_priv) {
802 TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
803 bo2, bo2->ref_cnt, key,
804 _tbm_flag_to_str(bo2->flags));
807 _tbm_bo_mutex_unlock();
815 bo->bufmgr->bo_cnt++;
818 if (bo->bufmgr->backend_module_data) {
819 bo->flags = bo->bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
820 if (error != TBM_ERROR_NONE) {
821 TBM_ERR("fail to get the bo flags(memory_types)");
822 _tbm_set_last_result(error);
823 bo->flags = TBM_BO_DEFAULT;
826 if (bo->bufmgr->backend->bo_get_flags)
827 bo->flags = bo->bufmgr->backend->bo_get_flags(bo);
829 bo->flags = TBM_BO_DEFAULT;
832 TBM_TRACE_BO("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
833 bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
835 LIST_INITHEAD(&bo->user_data_list);
837 LIST_ADD(&bo->item_link, &bo->bufmgr->bo_list);
839 _tbm_bo_mutex_unlock();
845 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
850 tbm_backend_bo_data *bo_data;
853 _tbm_bo_mutex_lock();
854 _tbm_set_last_result(TBM_ERROR_NONE);
856 TBM_BO_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
858 if (bufmgr->backend_module_data) {
859 if (!bufmgr->bufmgr_func->bufmgr_import_fd) {
860 /* LCOV_EXCL_START */
861 _tbm_bo_mutex_unlock();
862 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
867 if (!bufmgr->backend->bo_import_fd) {
868 /* LCOV_EXCL_START */
869 _tbm_bo_mutex_unlock();
870 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
876 _tbm_util_check_bo_cnt(bufmgr);
878 bo = calloc(1, sizeof(struct _tbm_bo));
880 /* LCOV_EXCL_START */
881 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
882 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
883 _tbm_bo_mutex_unlock();
890 if (bo->bufmgr->backend_module_data) {
891 bo_data = bo->bufmgr->bufmgr_func->bufmgr_import_fd(bufmgr->bufmgr_data, fd, &error);
893 /* LCOV_EXCL_START */
894 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d). error(%d)\n", fd, error);
895 _tbm_set_last_result(error);
897 _tbm_bo_mutex_unlock();
902 if (!LIST_IS_EMPTY(&bo->bufmgr->bo_list)) {
903 LIST_FOR_EACH_ENTRY(bo2, &bo->bufmgr->bo_list, item_link) {
904 if (bo2->bo_data == bo_data) {
905 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
906 bo2, bo2->ref_cnt, fd,
907 _tbm_flag_to_str(bo2->flags));
910 _tbm_bo_mutex_unlock();
915 bo->bo_data = bo_data;
917 bo_priv = bo->bufmgr->backend->bo_import_fd(bo, fd);
919 /* LCOV_EXCL_START */
920 TBM_ERR("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
921 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
923 _tbm_bo_mutex_unlock();
928 if (!LIST_IS_EMPTY(&bo->bufmgr->bo_list)) {
929 LIST_FOR_EACH_ENTRY(bo2, &bo->bufmgr->bo_list, item_link) {
930 if (bo2->priv == bo_priv) {
931 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
932 bo2, bo2->ref_cnt, fd,
933 _tbm_flag_to_str(bo2->flags));
936 _tbm_bo_mutex_unlock();
944 bo->bufmgr->bo_cnt++;
947 if (bo->bufmgr->backend_module_data) {
948 bo->flags = bo->bufmgr->bo_func->bo_get_memory_types(bo->bo_data, &error);
949 if (error != TBM_ERROR_NONE) {
950 TBM_ERR("fail to get the bo flags(memory_types)");
951 _tbm_set_last_result(error);
952 bo->flags = TBM_BO_DEFAULT;
955 if (bo->bufmgr->backend->bo_get_flags)
956 bo->flags = bo->bufmgr->backend->bo_get_flags(bo);
958 bo->flags = TBM_BO_DEFAULT;
961 TBM_TRACE_BO("import bo(%p) ref(%d) fd(%d) flag(%s)\n",
962 bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
964 LIST_INITHEAD(&bo->user_data_list);
966 LIST_ADD(&bo->item_link, &bo->bufmgr->bo_list);
968 _tbm_bo_mutex_unlock();
974 tbm_bo_size(tbm_bo bo)
979 _tbm_bo_mutex_lock();
980 _tbm_set_last_result(TBM_ERROR_NONE);
982 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
984 if (bo->bufmgr->backend_module_data) {
985 size = bo->bufmgr->bo_func->bo_get_size(bo->bo_data, &error);
986 if (error != TBM_ERROR_NONE) {
987 TBM_ERR("fail to get the size of the bo_data(%d).", error);
988 _tbm_set_last_result(TBM_ERROR_NONE);
991 size = bo->bufmgr->backend->bo_size(bo);
993 TBM_TRACE_BO("bo(%p) size(%d)\n", bo, size);
995 _tbm_bo_mutex_unlock();
1001 tbm_bo_locked(tbm_bo bo)
1003 _tbm_bo_mutex_lock();
1004 _tbm_set_last_result(TBM_ERROR_NONE);
1006 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1008 if (bo->bufmgr->bo_lock_type == TBM_BUFMGR_BO_LOCK_TYPE_NEVER) {
1009 TBM_ERR("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1010 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1011 _tbm_bo_mutex_unlock();
1015 if (bo->lock_cnt > 0) {
1016 TBM_TRACE_BO("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1017 _tbm_bo_mutex_unlock();
1021 TBM_TRACE_BO("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1022 _tbm_bo_mutex_unlock();
1028 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1030 tbm_error_e error1, error2;
1031 int size1 = -1, size2 = -2;
1034 _tbm_bo_mutex_lock();
1035 _tbm_set_last_result(TBM_ERROR_NONE);
1037 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1038 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1040 TBM_TRACE_BO("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1042 if (bo1->bufmgr->backend_module_data) {
1043 size1 = bo1->bufmgr->bo_func->bo_get_size(bo1->bo_data, &error1);
1044 if (error1 != TBM_ERROR_NONE) {
1045 TBM_ERR("fail to get the size of bo1.(%d)", error1);
1046 _tbm_set_last_result(error1);
1049 size2 = bo2->bufmgr->bo_func->bo_get_size(bo2->bo_data, &error2);
1050 if (error2 != TBM_ERROR_NONE) {
1051 TBM_ERR("fail to get the size of bo2.(%d)", error2);
1052 _tbm_set_last_result(error2);
1056 size1 = bo1->bufmgr->backend->bo_size(bo1);
1057 size2 = bo2->bufmgr->backend->bo_size(bo2);
1060 if (size1 != size2) {
1061 TBM_ERR("error: bo1 size(%d) and bo2 size(%d) is different.", size1, size2);
1062 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1066 TBM_TRACE_BO("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1069 bo1->priv = bo2->priv;
1072 _tbm_bo_mutex_unlock();
1077 TBM_ERR("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1078 _tbm_bo_mutex_unlock();
1084 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1085 tbm_data_free data_free_func)
1087 tbm_user_data *data;
1089 _tbm_bo_mutex_lock();
1090 _tbm_set_last_result(TBM_ERROR_NONE);
1092 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1094 /* check if the data according to the key exist if so, return false. */
1095 data = user_data_lookup(&bo->user_data_list, key);
1097 TBM_TRACE_BO("warning: user data already exist key(%ld)\n", key);
1098 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1099 _tbm_bo_mutex_unlock();
1103 data = user_data_create(key, data_free_func);
1105 TBM_ERR("error: bo(%p) key(%lu)\n", bo, key);
1106 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1107 _tbm_bo_mutex_unlock();
1111 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1113 LIST_ADD(&data->item_link, &bo->user_data_list);
1115 _tbm_bo_mutex_unlock();
1121 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1123 tbm_user_data *old_data;
1125 _tbm_bo_mutex_lock();
1126 _tbm_set_last_result(TBM_ERROR_NONE);
1128 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1130 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1131 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1132 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1133 _tbm_bo_mutex_unlock();
1137 old_data = user_data_lookup(&bo->user_data_list, key);
1139 TBM_TRACE_BO("bo(%p) key(%lu)\n", bo, key);
1140 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1141 _tbm_bo_mutex_unlock();
1145 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1147 user_data_delete(old_data);
1149 _tbm_bo_mutex_unlock();
1155 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1157 tbm_user_data *old_data;
1159 _tbm_bo_mutex_lock();
1160 _tbm_set_last_result(TBM_ERROR_NONE);
1162 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1164 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1165 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1166 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1167 _tbm_bo_mutex_unlock();
1171 old_data = user_data_lookup(&bo->user_data_list, key);
1173 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1174 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1175 _tbm_bo_mutex_unlock();
1179 if (old_data->data && old_data->free_func)
1180 old_data->free_func(old_data->data);
1181 old_data->data = data;
1183 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1185 _tbm_bo_mutex_unlock();
1191 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1193 tbm_user_data *old_data;
1195 _tbm_bo_mutex_lock();
1196 _tbm_set_last_result(TBM_ERROR_NONE);
1198 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1200 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1201 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1202 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1203 _tbm_bo_mutex_unlock();
1207 old_data = user_data_lookup(&bo->user_data_list, key);
1210 TBM_TRACE_BO("error: bo(%p) key(%lu)\n", bo, key);
1211 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1212 _tbm_bo_mutex_unlock();
1216 *data = old_data->data;
1218 TBM_TRACE_BO("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1220 _tbm_bo_mutex_unlock();
1226 tbm_bo_get_flags(tbm_bo bo)
1230 _tbm_bo_mutex_lock();
1232 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1236 TBM_TRACE_BO("bo(%p)\n", bo);
1238 _tbm_bo_mutex_unlock();
1243 /* LCOV_EXCL_START */
1244 /* internal function */
1246 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1248 _tbm_bo_mutex_lock();
1250 TBM_BO_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1252 bo->surface = surface;
1254 _tbm_bo_mutex_unlock();
1260 _tbm_bo_free(tbm_bo bo)
1262 /* destory the user_data_list */
1263 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
1264 tbm_user_data *old_data = NULL, *tmp;
1266 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
1267 &bo->user_data_list, item_link) {
1268 TBM_DBG("free user_data\n");
1269 user_data_delete(old_data);
1273 while (bo->lock_cnt > 0) {
1274 TBM_ERR("error lock_cnt:%d\n", bo->lock_cnt);
1279 /* call the bo_free */
1280 if (bo->bufmgr->backend_module_data) {
1281 bo->bufmgr->bo_func->bo_free(bo->bo_data);
1284 bo->bufmgr->backend->bo_free(bo);
1288 bo->bufmgr->bo_cnt--;
1290 LIST_DEL(&bo->item_link);
1293 /* LCOV_EXCL_STOP */