From 3b2ea9bbd4f335ed70ccc472414d6edc01e9f28e Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 18 Jan 2018 15:45:39 +0900 Subject: [PATCH 01/16] thread: support cb for multi-thread communication Change-Id: Ic59dd29fbc574232ec28e3a34e63533a8bd4d6f8 --- common/tdm_log.c | 7 + include/tdm_log.h | 1 + src/tdm.c | 6 + src/tdm_display.c | 7 +- src/tdm_macro.h | 14 ++ src/tdm_private.h | 3 + src/tdm_private_types.h | 4 + src/tdm_thread.c | 386 +++++++++++++++++++++++++++++++++++++++++++++--- src/tdm_thread.h | 13 ++ 9 files changed, 419 insertions(+), 22 deletions(-) diff --git a/common/tdm_log.c b/common/tdm_log.c index 0bad256..b77e765 100644 --- a/common/tdm_log.c +++ b/common/tdm_log.c @@ -189,3 +189,10 @@ tdm_log_print(int level, const char *fmt, ...) assert(0); #endif } + +EXTERN void +tdm_log_reset(void) +{ + pthread_mutex_trylock(&log_lock); + pthread_mutex_unlock(&log_lock); +} diff --git a/include/tdm_log.h b/include/tdm_log.h index 7ee4d95..02e8b0c 100644 --- a/include/tdm_log.h +++ b/include/tdm_log.h @@ -71,6 +71,7 @@ void tdm_log_set_debug_level(int level); void tdm_log_set_assert_level(int level); void tdm_log_set_path(const char *path); void tdm_log_print(int level, const char *fmt, ...); +void tdm_log_reset(void); extern unsigned int tdm_log_debug_level; diff --git a/src/tdm.c b/src/tdm.c index 69d9ebd..2536479 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -1120,6 +1120,12 @@ tdm_display_deinit(tdm_display *dpy) TDM_INFO("done"); } +INTERN tdm_private_display * +tdm_display_get(void) +{ + return g_private_display; +} + INTERN int tdm_display_is_valid(tdm_display *dpy) { diff --git a/src/tdm_display.c b/src/tdm_display.c index 5bd7ca6..abf4374 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -359,10 +359,13 @@ tdm_display_handle_events(tdm_display *dpy) if (tdm_debug_module & TDM_DEBUG_EVENT) TDM_INFO("fd(%d) polling out", fd); - if (tdm_thread_is_running()) + if (tdm_thread_is_running()) { + _pthread_mutex_lock(&private_display->lock); ret = tdm_thread_handle_cb(private_display->private_loop); - else + _pthread_mutex_unlock(&private_display->lock); + } else { ret = tdm_event_loop_dispatch(private_display); + } return ret; } diff --git a/src/tdm_macro.h b/src/tdm_macro.h index e75220c..77538a3 100644 --- a/src/tdm_macro.h +++ b/src/tdm_macro.h @@ -232,6 +232,20 @@ static struct tdm_type_name tdm_value_type_names[] = { }; TDM_TYPE_NAME_FN(value_type) +static struct tdm_type_name tdm_cb_type_names[] = { + { TDM_THREAD_CB_NONE, "none" }, + { TDM_THREAD_CB_OUTPUT_COMMIT, "output-commit" }, + { TDM_THREAD_CB_OUTPUT_VBLANK, "output-vblank" }, + { TDM_THREAD_CB_OUTPUT_STATUS, "output-status" }, + { TDM_THREAD_CB_OUTPUT_DPMS, "output-dpms" }, + { TDM_THREAD_CB_PP_DONE, "pp-done" }, + { TDM_THREAD_CB_CAPTURE_DONE, "capture-done" }, + { TDM_THREAD_CB_VBLANK_SW, "vblank-sw" }, + { TDM_THREAD_CB_VBLANK_CREATE, "vblank-create" }, + { TDM_THREAD_CB_NEED_VALIDATE, "need-validate" }, +}; +TDM_TYPE_NAME_FN(cb_type) + #define TDM_BIT_NAME_FB(res) \ static inline const char * tdm_##res##_str(int type, char **reply, int *len) \ { \ diff --git a/src/tdm_private.h b/src/tdm_private.h index 30dfb81..f04eebb 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,8 @@ extern int tdm_ttrace_output; int tdm_display_is_valid(tdm_display *display); +tdm_private_display * +tdm_display_get(void); int tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, int abimin); diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index 6c7d2d5..a4ac11d 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -440,6 +440,7 @@ typedef enum { TDM_THREAD_CB_VBLANK_SW, TDM_THREAD_CB_VBLANK_CREATE, TDM_THREAD_CB_NEED_VALIDATE, + TDM_THREAD_CB_MAX, } tdm_thread_cb_type; typedef struct _tdm_thread_cb_base tdm_thread_cb_base; @@ -456,6 +457,9 @@ typedef struct _tdm_thread_cb_need_validate tdm_thread_cb_need_validate; struct _tdm_thread_cb_base { tdm_thread_cb_type type; unsigned int length; + double object_stamp; + void *data; + unsigned int sync; }; struct _tdm_thread_cb_output_vblank { diff --git a/src/tdm_thread.c b/src/tdm_thread.c index ebac0be..5b7f00e 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -44,15 +44,56 @@ static tdm_private_thread *keep_private_thread; struct _tdm_private_thread { tdm_private_loop *private_loop; + pthread_cond_t event_cond; pthread_t event_thread; pid_t display_tid; pid_t thread_tid; - /* 0: read, 1: write */ + /* 0: read, 1: write (tdm-thread -> display-thread) */ int pipe[2]; + + /* 0: read, 1: write (tdm-thread <- display-thread) */ + int sub_pipe[2]; + tdm_event_loop_source *sub_event_source; }; +typedef struct _tdm_private_thread_cb { + struct list_head link; + struct list_head call_link; + + void *object; + tdm_thread_cb_type cb_type; + void *cb_data; + tdm_thread_cb func; + void *user_data; + + pid_t owner_tid; + unsigned int called; +} tdm_private_thread_cb; + +static tdm_thread_find_object find_funcs[TDM_THREAD_CB_MAX] = {0, }; +static struct list_head cb_list; + +static void _tdm_thread_free_cb(tdm_private_thread_cb *cb); + +static tdm_error +_tdm_thread_handle_events(int fd, tdm_event_loop_mask mask, void *user_data) +{ + tdm_private_loop *private_loop = user_data; + tdm_error ret; + + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); + TDM_RETURN_VAL_IF_FAIL(private_loop != NULL, TDM_ERROR_OPERATION_FAILED); + TDM_RETURN_VAL_IF_FAIL(private_loop->dpy != NULL, TDM_ERROR_OPERATION_FAILED); + + ret = tdm_thread_handle_cb(private_loop); + + TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); + + return TDM_ERROR_NONE; +} + static void* _tdm_thread_main(void *data) { @@ -61,6 +102,7 @@ _tdm_thread_main(void *data) int fd; struct pollfd fds; int ret; + tdm_error error; /* Not lock/unlock for the private_thread and private_loop structure * because they won't be destroyed as long as tdm thread is running. @@ -71,6 +113,28 @@ _tdm_thread_main(void *data) TDM_INFO("display_tid:%d, thread_tid: %d", private_thread->display_tid, private_thread->thread_tid); + /* fd SHOULD be the same with sub_pipe[0] to make sure that using + * tdm_thread_get_fd, tdm_thread_send_cb, tdm_thread_handle_cb in + * both threads is fine. Otherwise, assert. + */ + tdm_display_lock(private_loop->dpy); + assert(tdm_thread_get_fd(private_loop) == private_thread->sub_pipe[0]); + + private_thread->sub_event_source = + tdm_event_loop_add_fd_handler(private_loop->dpy, + private_thread->sub_pipe[0], + TDM_EVENT_LOOP_READABLE, + _tdm_thread_handle_events, + private_loop, + &error); + TDM_GOTO_IF_FAIL(error == TDM_ERROR_NONE, exit_thread); + TDM_GOTO_IF_FAIL(private_thread->sub_event_source != NULL, exit_thread); + + pthread_cond_signal(&private_thread->event_cond); + + /* mutex shall be locked by the thread calling pthread_cond_signal() */ + tdm_display_unlock(private_loop->dpy); + fd = tdm_event_loop_get_fd(private_loop->dpy); if (fd < 0) { TDM_ERR("couldn't get fd"); @@ -111,6 +175,7 @@ _tdm_thread_main(void *data) } exit_thread: + tdm_display_unlock(private_loop->dpy); pthread_exit(NULL); } @@ -128,6 +193,8 @@ tdm_thread_init(tdm_private_loop *private_loop) private_display = private_loop->dpy; TDM_RETURN_VAL_IF_FAIL(private_display->private_loop, TDM_ERROR_OPERATION_FAILED); + LIST_INITHEAD(&cb_list); + if (private_loop->private_thread) return TDM_ERROR_NONE; @@ -144,24 +211,49 @@ tdm_thread_init(tdm_private_loop *private_loop) return TDM_ERROR_OUT_OF_MEMORY; } + if (pthread_cond_init(&private_thread->event_cond, NULL)) { + TDM_ERR("pthread_cond_init failed: %m"); + free(private_thread); + return TDM_ERROR_OUT_OF_MEMORY; + } + if (pipe(private_thread->pipe) != 0) { - TDM_ERR("socketpair failed: %m"); + TDM_ERR("pipe failed: %m"); + pthread_cond_destroy(&private_thread->event_cond); free(private_thread); return TDM_ERROR_OPERATION_FAILED; } + if (pipe(private_thread->sub_pipe) != 0) { + TDM_ERR("sub_pipe failed: %m"); + close(private_thread->pipe[0]); + close(private_thread->pipe[1]); + pthread_cond_destroy(&private_thread->event_cond); + free(private_thread); + return TDM_ERROR_OPERATION_FAILED; + } + + keep_private_thread = private_thread; + private_thread->private_loop = private_loop; private_loop->private_thread = private_thread; private_thread->display_tid = syscall(SYS_gettid); + /* pthread_cond_wait atomically release mutex, Upon successful return, + * the mutex shall have been locked and shall be owned by the calling thread + */ + tdm_mutex_locked = 0; pthread_create(&private_thread->event_thread, NULL, _tdm_thread_main, private_thread); - keep_private_thread = private_thread; + /* wait until the tdm thread starts */ + pthread_cond_wait(&private_thread->event_cond, &private_display->lock); + tdm_mutex_locked = 1; - TDM_INFO("using a TDM event thread. pipe(%d,%d)", - private_thread->pipe[0], private_thread->pipe[1]); + TDM_INFO("using a TDM event thread. pipe(%d,%d) sub_pipe(%d,%d)", + private_thread->pipe[0], private_thread->pipe[1], + private_thread->sub_pipe[0], private_thread->sub_pipe[1]); return TDM_ERROR_NONE; } @@ -170,12 +262,17 @@ INTERN void tdm_thread_deinit(tdm_private_loop *private_loop) { tdm_private_display *private_display; + tdm_private_thread_cb *cb = NULL, *hh = NULL; + int i; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); if (!private_loop->private_thread) return; + if (private_loop->private_thread->sub_event_source) + tdm_event_loop_source_remove(private_loop->private_thread->sub_event_source); + pthread_cancel(private_loop->private_thread->event_thread); private_display = private_loop->dpy; @@ -186,15 +283,31 @@ tdm_thread_deinit(tdm_private_loop *private_loop) _pthread_mutex_unlock(&private_display->lock); pthread_join(private_loop->private_thread->event_thread, NULL); + tdm_log_reset(); + + LIST_FOR_EACH_ENTRY_SAFE(cb, hh, &cb_list, link) { + _tdm_thread_free_cb(cb); + } + if (private_loop->private_thread->pipe[0] >= 0) close(private_loop->private_thread->pipe[0]); if (private_loop->private_thread->pipe[1] >= 0) close(private_loop->private_thread->pipe[1]); + if (private_loop->private_thread->sub_pipe[0] >= 0) + close(private_loop->private_thread->sub_pipe[0]); + if (private_loop->private_thread->sub_pipe[1] >= 0) + close(private_loop->private_thread->sub_pipe[1]); + + pthread_cond_destroy(&private_loop->private_thread->event_cond); + free(private_loop->private_thread); private_loop->private_thread = NULL; keep_private_thread = NULL; + for (i = 0; i < TDM_THREAD_CB_MAX; i++) + find_funcs[i] = NULL; + TDM_INFO("Finish a TDM event thread"); } @@ -202,6 +315,7 @@ INTERN int tdm_thread_get_fd(tdm_private_loop *private_loop) { tdm_private_thread *private_thread; + int in_main; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(private_loop, -1); @@ -209,7 +323,13 @@ tdm_thread_get_fd(tdm_private_loop *private_loop) private_thread = private_loop->private_thread; - return private_thread->pipe[0]; + /* seems like ticky. but easy way to use the same APIs for both threads */ + in_main = tdm_thread_in_display_thread(syscall(SYS_gettid)); + + if (in_main) + return private_thread->pipe[0]; + else + return private_thread->sub_pipe[0]; } INTERN tdm_error @@ -217,6 +337,7 @@ tdm_thread_send_cb(tdm_private_loop *private_loop, tdm_thread_cb_base *base) { tdm_private_thread *private_thread; ssize_t len; + int pipe, in_main; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(base, TDM_ERROR_INVALID_PARAMETER); @@ -225,43 +346,58 @@ tdm_thread_send_cb(tdm_private_loop *private_loop, tdm_thread_cb_base *base) private_thread = private_loop->private_thread; + /* seems like ticky. but easy way to use the same APIs for both threads */ + in_main = tdm_thread_in_display_thread(syscall(SYS_gettid)); + + if (in_main) + pipe = private_thread->sub_pipe[1]; + else + pipe = private_thread->pipe[1]; + if (tdm_debug_module & TDM_DEBUG_THREAD) - TDM_INFO("fd(%d) type(%d), length(%d)", - private_thread->pipe[1], base->type, base->length); + TDM_INFO("fd(%d) type(%d), length(%d)", pipe, base->type, base->length); - len = write(private_thread->pipe[1], base, base->length); + len = write(pipe, base, base->length); if (len != base->length) { TDM_ERR("write failed (%d != %d): %m", (int)len, base->length); return TDM_ERROR_OPERATION_FAILED; } + if (tdm_debug_module & TDM_DEBUG_THREAD) + TDM_INFO("[%s] write fd(%d) length(%d)", (in_main) ? "main" : "sub", pipe, len); + return TDM_ERROR_NONE; } INTERN tdm_error tdm_thread_handle_cb(tdm_private_loop *private_loop) { - tdm_private_display *private_display; tdm_private_thread *private_thread; tdm_thread_cb_base *base; char buffer[1024]; unsigned int i; - int len; - - /* DON'T check TDM_MUTEX_IS_LOCKED here */ + int len, pipe, in_main; + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(private_loop, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(private_loop->private_thread, TDM_ERROR_INVALID_PARAMETER); private_thread = private_loop->private_thread; - private_display = private_loop->dpy; + + /* seems like ticky. but easy way to use the same APIs for both threads */ + in_main = tdm_thread_in_display_thread(syscall(SYS_gettid)); + + if (in_main) + pipe = private_thread->pipe[0]; + else + pipe = private_thread->sub_pipe[0]; do { - len = read(private_thread->pipe[0], buffer, sizeof buffer); + len = read(pipe, buffer, sizeof buffer); } while (len < 0 && errno == EINTR); if (tdm_debug_module & TDM_DEBUG_THREAD) - TDM_INFO("fd(%d) read length(%d)", private_thread->pipe[0], len); + TDM_INFO("[%s] read fd(%d) length(%d)", (in_main) ? "main" : "sub", pipe, len); if (len < 0) { TDM_ERR("read failed: errno(%d), len(%d) %m", errno, len); @@ -276,8 +412,6 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) return TDM_ERROR_OPERATION_FAILED; } - _pthread_mutex_lock(&private_display->lock); - i = 0; while (i < len) { base = (tdm_thread_cb_base*)&buffer[i]; @@ -380,8 +514,6 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) i += base->length; } - _pthread_mutex_unlock(&private_display->lock); - return TDM_ERROR_NONE; } @@ -403,3 +535,217 @@ tdm_thread_is_running(void) return (keep_private_thread) ? 1 : 0; } + +static void +_tdm_thread_free_cb(tdm_private_thread_cb *cb) +{ + if (tdm_debug_module & TDM_DEBUG_THREAD) + TDM_INFO("cb(%p) removed", cb); + + assert(LIST_IS_EMPTY(&cb->call_link)); + + LIST_DEL(&cb->link); + free(cb); +} + +static tdm_private_thread_cb * +_tdm_thread_find_cb(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_thread_cb func, void *user_data, pid_t owner_tid) +{ + tdm_private_thread_cb *cb = NULL; + + LIST_FOR_EACH_ENTRY(cb, &cb_list, link) { + if (cb->object == object && + cb->cb_type == cb_type && + cb->cb_data == cb_data && + cb->func == func && + cb->user_data == user_data && + cb->owner_tid == owner_tid) + return cb; + } + + return NULL; +} + +static void +_tdm_thread_reset_cb(tdm_thread_cb_type cb_type) +{ + tdm_private_thread_cb *cb = NULL; + + LIST_FOR_EACH_ENTRY(cb, &cb_list, link) { + if (cb->cb_type == cb_type) + cb->called = 0; + } +} + +INTERN void +tdm_thread_cb_set_find_func(tdm_thread_cb_type cb_type, tdm_thread_find_object func) +{ + TDM_RETURN_IF_FAIL(cb_type > 0); + + if (func && find_funcs[cb_type]) + TDM_NEVER_GET_HERE(); + + find_funcs[cb_type] = func; +} + +INTERN tdm_error +tdm_thread_cb_add(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_thread_cb func, void *user_data) +{ + tdm_private_thread_cb *cb = NULL; + pid_t caller_tid; + + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); + TDM_RETURN_VAL_IF_FAIL(object != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(cb_type > 0, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + caller_tid = syscall(SYS_gettid); + + cb = _tdm_thread_find_cb(object, cb_type, cb_data, func, user_data, caller_tid); + if (cb) { + TDM_ERR("can't be added twice with same data"); +#if 1 + assert(0); +#endif + return TDM_ERROR_BAD_REQUEST; + } + + cb = calloc(1, sizeof *cb); + if (!cb) { + TDM_ERR("calloc failed"); + return TDM_ERROR_OUT_OF_MEMORY; + } + + LIST_ADDTAIL(&cb->link, &cb_list); + LIST_INITHEAD(&cb->call_link); + + cb->object = object; + cb->cb_type = cb_type; + cb->cb_data = cb_data; + cb->func = func; + cb->user_data = user_data; + cb->owner_tid = caller_tid; + + if (tdm_debug_module & TDM_DEBUG_THREAD) + TDM_INFO("cb_type(%d) cb(%p) added", cb_type, cb); + + return TDM_ERROR_NONE; +} + +INTERN void +tdm_thread_cb_remove(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_thread_cb func, void *user_data) +{ + tdm_private_thread_cb *cb; + pid_t caller_tid; + + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + TDM_RETURN_IF_FAIL(object != NULL); + TDM_RETURN_IF_FAIL(cb_type > 0); + TDM_RETURN_IF_FAIL(func != NULL); + + caller_tid = syscall(SYS_gettid); + + cb = _tdm_thread_find_cb(object, cb_type, cb_data, func, user_data, caller_tid); + if (!cb) + return; + + _tdm_thread_free_cb(cb); +} + +/* when call a callback, we check both cb_base's type and cb_base's data, + * because a callback is added with cb_type and cb_data. + */ +INTERN tdm_error +tdm_thread_cb_call(void *object, tdm_thread_cb_base *cb_base) +{ + tdm_private_display *private_display = tdm_display_get(); + tdm_private_thread_cb *cb = NULL, *hh = NULL; + int handler_in_other_thread = 0; + pid_t caller_tid; + struct list_head call_list; + tdm_error ret; + + TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); + TDM_RETURN_VAL_IF_FAIL(cb_base != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(cb_base->type > 0, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(cb_base->length > 0, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(cb_base->sync == 0 || cb_base->sync == 1, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(cb_base->object_stamp > 0, TDM_ERROR_INVALID_PARAMETER); + + caller_tid = syscall(SYS_gettid); + + assert(find_funcs[cb_base->type] != NULL); + + if (!object) { + object = find_funcs[cb_base->type](private_display, cb_base->object_stamp); + if (!object) { + TDM_WRN("%p gone", object); + return TDM_ERROR_NONE; + } + } + + LIST_INITHEAD(&call_list); + + LIST_FOR_EACH_ENTRY_SAFE(cb, hh, &cb_list, link) { + if (cb->called || + cb->object != object || + cb->cb_type != cb_base->type || + cb->cb_data != cb_base->data) + continue; + + if (cb->owner_tid == caller_tid) + LIST_ADDTAIL(&cb->call_link, &call_list); + else + handler_in_other_thread = 1; + } + + if (!LIST_IS_EMPTY(&call_list)) { + LIST_FOR_EACH_ENTRY_SAFE(cb, hh, &call_list, call_link) { + LIST_DELINIT(&cb->call_link); + cb->called = 1; + if (tdm_debug_module & TDM_DEBUG_THREAD) + TDM_INFO("cb_type(%d) cb(%p) called", cb->cb_type, cb); + cb->func(private_display, cb->object, cb_base, cb->user_data); + } + } + + assert(LIST_IS_EMPTY(&call_list)); + + if (!handler_in_other_thread) { + _tdm_thread_reset_cb(cb_base->type); + if (keep_private_thread) { + if (cb_base->sync) { + pthread_cond_signal(&keep_private_thread->event_cond); + if (tdm_debug_module & TDM_DEBUG_THREAD) + TDM_INFO("pthread broadcase"); + } + } + if (tdm_debug_module & TDM_DEBUG_THREAD) + TDM_INFO("'%s' thread_cb done(sync:%d)", tdm_cb_type_str(cb_base->type), cb_base->sync); + return TDM_ERROR_NONE; + } + + /* Once we reach here, it means that keep_private_thread is not NULL. + * Just make the crash. Avoiding it is not going to help us. + */ + ret = tdm_thread_send_cb(private_display->private_loop, cb_base); + TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, TDM_ERROR_OPERATION_FAILED); + + /* waiting until all cb are done in another thread */ + if (cb_base->sync) { + if (tdm_debug_module & TDM_DEBUG_THREAD) + TDM_INFO("pthread wait"); + + /* pthread_cond_wait atomically release mutex, Upon successful return, + * the mutex shall have been locked and shall be owned by the calling thread + */ + tdm_mutex_locked = 0; + pthread_cond_wait(&keep_private_thread->event_cond, &private_display->lock); + tdm_mutex_locked = 1; + } + + if (tdm_debug_module & TDM_DEBUG_THREAD) + TDM_INFO("'%s' thread_cb done(sync:%d)", tdm_cb_type_str(cb_base->type), cb_base->sync); + + return TDM_ERROR_NONE; +} diff --git a/src/tdm_thread.h b/src/tdm_thread.h index c9ef06d..1a91933 100644 --- a/src/tdm_thread.h +++ b/src/tdm_thread.h @@ -57,6 +57,19 @@ tdm_thread_in_display_thread(pid_t tid); int tdm_thread_is_running(void); +typedef void* (*tdm_thread_find_object)(tdm_private_display *private_display, double stamp); +typedef void (*tdm_thread_cb)(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data); + +void +tdm_thread_cb_set_find_func(tdm_thread_cb_type cb_type, tdm_thread_find_object func); +tdm_error +tdm_thread_cb_add(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_thread_cb func, void *user_data); +void +tdm_thread_cb_remove(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_thread_cb func, void *user_data); +tdm_error +tdm_thread_cb_call(void *object, tdm_thread_cb_base *cb_base); + + #ifdef __cplusplus } #endif -- 2.7.4 From 8b977463ed4b95abc75aa2ab547a877cb6d08d09 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 29 Jan 2018 09:53:05 +0900 Subject: [PATCH 02/16] pp: using thread_cb Change-Id: I02bdd31434f95ff5c249e839442fd397afaffdef --- src/tdm.c | 4 +++ src/tdm_pp.c | 85 +++++++++++++++++++++++++++++++++---------------- src/tdm_private.h | 7 ++-- src/tdm_private_types.h | 2 -- src/tdm_thread.c | 12 ++----- 5 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/tdm.c b/src/tdm.c index 2536479..a35bb4b 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -974,6 +974,10 @@ tdm_display_init(tdm_error *error) TDM_INFO("event loop init time: %.3f ms", (stamp2 - stamp1) * 1000.0); stamp1 = stamp2; + ret = tdm_pp_init(private_display); + if (ret != TDM_ERROR_NONE) + goto failed_load; + ret = _tdm_display_load_module(private_display); if (ret != TDM_ERROR_NONE) goto failed_load; diff --git a/src/tdm_pp.c b/src/tdm_pp.c index 6e1dafd..8f4fd8d 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -68,7 +68,7 @@ _tdm_pp_print_list(struct list_head *list) break; } - TDM_WRN("\t %s", str); + TDM_INFO("\t %s", str); } static tdm_pp_private_buffer * @@ -97,35 +97,21 @@ _tdm_pp_find_buffer(struct list_head *list, tdm_pp_private_buffer *pp_buffer) return NULL; } -INTERN void -tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, - void *user_data) +static void +_tdm_pp_thread_cb_done(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) { - tdm_private_pp *private_pp = user_data; - tdm_private_display *private_display = private_pp->private_display; + tdm_thread_cb_pp_done *pp_done = (tdm_thread_cb_pp_done *)cb_base; + tdm_private_pp *private_pp = object; tdm_pp_private_buffer *pp_buffer = NULL, *first_entry = NULL; + tbm_surface_h src; + tbm_surface_h dst; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - if (private_pp->owner_tid != syscall(SYS_gettid)) { - tdm_thread_cb_pp_done pp_done; - tdm_error ret; - - pp_done.base.type = TDM_THREAD_CB_PP_DONE; - pp_done.base.length = sizeof pp_done; - pp_done.pp_stamp = private_pp->stamp; - pp_done.src = src; - pp_done.dst = dst; - pp_done.user_data = user_data; - - ret = tdm_thread_send_cb(private_display->private_loop, &pp_done.base); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - - return; - } + assert(private_pp->owner_tid == syscall(SYS_gettid)); - if (private_pp->owner_tid != syscall(SYS_gettid)) - TDM_NEVER_GET_HERE(); + src = pp_done->src; + dst = pp_done->dst; if (tdm_debug_dump & TDM_DUMP_FLAG_PP) { /* LCOV_EXCL_START */ @@ -167,8 +153,30 @@ tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, } } -INTERN tdm_private_pp * -tdm_pp_find_stamp(tdm_private_display *private_display, double stamp) +static void +_tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, void *user_data) +{ + tdm_thread_cb_pp_done pp_done; + tdm_private_pp *private_pp = user_data; + tdm_error ret; + + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + + memset(&pp_done, 0, sizeof pp_done); + pp_done.base.type = TDM_THREAD_CB_PP_DONE; + pp_done.base.length = sizeof pp_done; + pp_done.base.object_stamp = private_pp->stamp; + pp_done.base.data = NULL; + pp_done.base.sync = 0; + pp_done.src = src; + pp_done.dst = dst; + + ret = tdm_thread_cb_call(private_pp, &pp_done.base); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); +} + +static void * +_tdm_pp_find_object(tdm_private_display *private_display, double stamp) { tdm_private_pp *private_pp = NULL; @@ -182,6 +190,14 @@ tdm_pp_find_stamp(tdm_private_display *private_display, double stamp) return NULL; } +INTERN tdm_error +tdm_pp_init(tdm_private_display *private_display) +{ + tdm_thread_cb_set_find_func(TDM_THREAD_CB_PP_DONE, _tdm_pp_find_object); + + return TDM_ERROR_NONE; +} + INTERN tdm_private_pp * tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error) { @@ -225,11 +241,22 @@ tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error) /* LCOV_EXCL_STOP */ } - ret = func_pp->pp_set_done_handler(pp_backend, tdm_pp_cb_done, private_pp); + ret = tdm_thread_cb_add(private_pp, TDM_THREAD_CB_PP_DONE, NULL, _tdm_pp_thread_cb_done, NULL); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("pp tdm_thread_cb_add failed"); + func_pp->pp_destroy(pp_backend); + free(private_pp); + if (error) + *error = ret; + return NULL; + } + + ret = func_pp->pp_set_done_handler(pp_backend, _tdm_pp_cb_done, private_pp); if (ret != TDM_ERROR_NONE) { /* LCOV_EXCL_START */ TDM_ERR("spp(%p) et pp_done_handler failed", private_pp); func_pp->pp_destroy(pp_backend); + free(private_pp); if (error) *error = ret; return NULL; @@ -237,7 +264,7 @@ tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error) } private_pp->stamp = tdm_helper_get_time(); - while (tdm_pp_find_stamp(private_display, private_pp->stamp)) + while (_tdm_pp_find_object(private_display, private_pp->stamp)) private_pp->stamp++; LIST_ADD(&private_pp->link, &private_display->pp_list); @@ -267,6 +294,8 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp) if (!private_pp) return; + tdm_thread_cb_remove(private_pp, TDM_THREAD_CB_PP_DONE, NULL, _tdm_pp_thread_cb_done, NULL); + private_display = private_pp->private_display; func_pp = &private_display->func_pp; diff --git a/src/tdm_private.h b/src/tdm_private.h index f04eebb..fb1886f 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -92,8 +92,6 @@ tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, i tdm_private_output * tdm_display_find_output_stamp(tdm_private_display *private_display, double stamp); -tdm_private_pp * -tdm_pp_find_stamp(tdm_private_display *private_display, double stamp); tdm_private_capture * tdm_capture_find_stamp(tdm_private_display *private_display, double stamp); @@ -151,9 +149,6 @@ tdm_error tdm_layer_unset_buffer_internal(tdm_private_layer *private_layer); void -tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, - void *user_data); -void tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, void *user_data); tdm_error @@ -181,6 +176,8 @@ tdm_output_call_change_handler_internal(tdm_private_output *private_output, tdm_output_change_type type, tdm_value value); +tdm_error +tdm_pp_init(tdm_private_display *private_display); tdm_private_pp * tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error); void diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index a4ac11d..85413c4 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -487,10 +487,8 @@ struct _tdm_thread_cb_output_dpms { struct _tdm_thread_cb_pp_done { tdm_thread_cb_base base; - double pp_stamp; tbm_surface_h src; tbm_surface_h dst; - void *user_data; }; struct _tdm_thread_cb_capture_done { diff --git a/src/tdm_thread.c b/src/tdm_thread.c index 5b7f00e..0bd4e86 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -471,17 +471,9 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) break; /* LCOV_EXCL_STOP */ } - case TDM_THREAD_CB_PP_DONE: { - tdm_thread_cb_pp_done *pp_done = (tdm_thread_cb_pp_done*)base; - tdm_pp *pp_backend = - tdm_pp_find_stamp(private_loop->dpy, pp_done->pp_stamp); - if (!pp_backend) { - TDM_WRN("no pp(%f)", pp_done->pp_stamp); - break; - } - tdm_pp_cb_done(pp_backend, pp_done->src, pp_done->dst, pp_done->user_data); + case TDM_THREAD_CB_PP_DONE: + tdm_thread_cb_call(NULL, base); break; - } case TDM_THREAD_CB_CAPTURE_DONE: { tdm_thread_cb_capture_done *capture_done = (tdm_thread_cb_capture_done*)base; tdm_capture *capture_backend = -- 2.7.4 From e95be5f458e48a9eb5968fb98e6fc71f27804ff7 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 29 Jan 2018 09:53:31 +0900 Subject: [PATCH 03/16] capture: using thread_cb Change-Id: I9c2e914fb12d472aac1faf354e893a18c3b060e3 --- src/tdm.c | 4 +++ src/tdm_capture.c | 82 ++++++++++++++++++++++++++++++++----------------- src/tdm_private.h | 7 ++--- src/tdm_private_types.h | 2 -- src/tdm_thread.c | 12 +------- 5 files changed, 61 insertions(+), 46 deletions(-) diff --git a/src/tdm.c b/src/tdm.c index a35bb4b..b81347d 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -978,6 +978,10 @@ tdm_display_init(tdm_error *error) if (ret != TDM_ERROR_NONE) goto failed_load; + ret = tdm_capture_init(private_display); + if (ret != TDM_ERROR_NONE) + goto failed_load; + ret = _tdm_display_load_module(private_display); if (ret != TDM_ERROR_NONE) goto failed_load; diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 2ba0e5f..869e31f 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -97,34 +97,19 @@ _tdm_capture_find_buffer(struct list_head *list, tdm_capture_private_buffer *cap return NULL; } -INTERN void -tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, - void *user_data) +static void +_tdm_capture_thread_cb_done(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) { - tdm_private_capture *private_capture = user_data; - tdm_private_display *private_display = private_capture->private_display; + tdm_thread_cb_capture_done *capture_done = (tdm_thread_cb_capture_done *)cb_base; + tdm_private_capture *private_capture = object; tdm_capture_private_buffer *capture_buffer = NULL, *first_entry = NULL; + tbm_surface_h buffer; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - if (private_capture->owner_tid != syscall(SYS_gettid)) { - tdm_thread_cb_capture_done capture_done; - tdm_error ret; - - capture_done.base.type = TDM_THREAD_CB_CAPTURE_DONE; - capture_done.base.length = sizeof capture_done; - capture_done.capture_stamp = private_capture->stamp; - capture_done.buffer = buffer; - capture_done.user_data = user_data; - - ret = tdm_thread_send_cb(private_display->private_loop, &capture_done.base); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - - return; - } + assert(private_capture->owner_tid == syscall(SYS_gettid)); - if (private_capture->owner_tid != syscall(SYS_gettid)) - TDM_NEVER_GET_HERE(); + buffer = capture_done->buffer; if (tdm_debug_dump & TDM_DUMP_FLAG_CAPTURE) { /* LCOV_EXCL_START */ @@ -165,8 +150,29 @@ tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, } } -INTERN tdm_private_capture * -tdm_capture_find_stamp(tdm_private_display *private_display, double stamp) +static void +_tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, void *user_data) +{ + tdm_private_capture *private_capture = user_data; + tdm_thread_cb_capture_done capture_done; + tdm_error ret; + + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + + memset(&capture_done, 0, sizeof capture_done); + capture_done.base.type = TDM_THREAD_CB_CAPTURE_DONE; + capture_done.base.length = sizeof capture_done; + capture_done.base.object_stamp = private_capture->stamp; + capture_done.base.data = NULL; + capture_done.base.sync = 0; + capture_done.buffer = buffer; + + ret = tdm_thread_cb_call(private_capture, &capture_done.base); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); +} + +static void * +_tdm_capture_find_object(tdm_private_display *private_display, double stamp) { tdm_private_capture *private_capture = NULL; @@ -180,6 +186,14 @@ tdm_capture_find_stamp(tdm_private_display *private_display, double stamp) return NULL; } +INTERN tdm_error +tdm_capture_init(tdm_private_display *private_display) +{ + tdm_thread_cb_set_find_func(TDM_THREAD_CB_CAPTURE_DONE, _tdm_capture_find_object); + + return TDM_ERROR_NONE; +} + INTERN tdm_private_capture * tdm_capture_create_output_internal(tdm_private_output *private_output, tdm_error *error) @@ -232,12 +246,22 @@ tdm_capture_create_output_internal(tdm_private_output *private_output, /* LCOV_EXCL_STOP */ } - ret = func_capture->capture_set_done_handler(capture_backend, - tdm_capture_cb_done, private_capture); + ret = tdm_thread_cb_add(private_capture, TDM_THREAD_CB_CAPTURE_DONE, NULL, _tdm_capture_thread_cb_done, NULL); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("capture tdm_thread_cb_add failed"); + func_capture->capture_destroy(capture_backend); + free(private_capture); + if (error) + *error = ret; + return NULL; + } + + ret = func_capture->capture_set_done_handler(capture_backend, _tdm_capture_cb_done, private_capture); if (ret != TDM_ERROR_NONE) { /* LCOV_EXCL_START */ TDM_ERR("capture(%p) set capture_done_handler failed", private_capture); func_capture->capture_destroy(capture_backend); + free(private_capture); if (error) *error = ret; return NULL; @@ -245,7 +269,7 @@ tdm_capture_create_output_internal(tdm_private_output *private_output, } private_capture->stamp = tdm_helper_get_time(); - while (tdm_capture_find_stamp(private_display, private_capture->stamp)) + while (_tdm_capture_find_object(private_display, private_capture->stamp)) private_capture->stamp++; LIST_ADD(&private_capture->link, &private_output->capture_list); @@ -313,7 +337,7 @@ tdm_capture_create_layer_internal(tdm_private_layer *private_layer, } private_capture->stamp = tdm_helper_get_time(); - while (tdm_capture_find_stamp(private_display, private_capture->stamp)) + while (_tdm_capture_find_object(private_display, private_capture->stamp)) private_capture->stamp++; LIST_ADD(&private_capture->link, &private_layer->capture_list); @@ -353,6 +377,8 @@ tdm_capture_destroy_internal(tdm_private_capture *private_capture) private_display = private_capture->private_display; + tdm_thread_cb_remove(private_capture, TDM_THREAD_CB_CAPTURE_DONE, NULL, _tdm_capture_thread_cb_done, NULL); + LIST_DEL(&private_capture->link); LIST_DEL(&private_capture->display_link); diff --git a/src/tdm_private.h b/src/tdm_private.h index fb1886f..c19ceb4 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -92,8 +92,6 @@ tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, i tdm_private_output * tdm_display_find_output_stamp(tdm_private_display *private_display, double stamp); -tdm_private_capture * -tdm_capture_find_stamp(tdm_private_display *private_display, double stamp); int tdm_output_is_valid(tdm_output *output); @@ -148,9 +146,6 @@ tdm_layer_set_buffer_internal(tdm_private_layer *private_layer, tbm_surface_h bu tdm_error tdm_layer_unset_buffer_internal(tdm_private_layer *private_layer); -void -tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, - void *user_data); tdm_error tdm_vblank_init(tdm_display *dpy); void @@ -188,6 +183,8 @@ tdm_hwc_window_create_internal(tdm_private_output *private_output, int is_video, tdm_error tdm_hwc_window_destroy_internal(tdm_private_hwc_window * private_hwc_window); +tdm_error +tdm_capture_init(tdm_private_display *private_display); tdm_private_capture * tdm_capture_create_output_internal(tdm_private_output *private_output, tdm_error *error); diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index 85413c4..188d3fe 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -493,9 +493,7 @@ struct _tdm_thread_cb_pp_done { struct _tdm_thread_cb_capture_done { tdm_thread_cb_base base; - double capture_stamp; tbm_surface_h buffer; - void *user_data; }; struct _tdm_thread_cb_vblank_sw { diff --git a/src/tdm_thread.c b/src/tdm_thread.c index 0bd4e86..ff0d0c8 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -472,19 +472,9 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) /* LCOV_EXCL_STOP */ } case TDM_THREAD_CB_PP_DONE: + case TDM_THREAD_CB_CAPTURE_DONE: tdm_thread_cb_call(NULL, base); break; - case TDM_THREAD_CB_CAPTURE_DONE: { - tdm_thread_cb_capture_done *capture_done = (tdm_thread_cb_capture_done*)base; - tdm_capture *capture_backend = - tdm_capture_find_stamp(private_loop->dpy, capture_done->capture_stamp); - if (!capture_backend) { - TDM_WRN("no capture(%f)", capture_done->capture_stamp); - break; - } - tdm_capture_cb_done(capture_backend, capture_done->buffer, capture_done->user_data); - break; - } case TDM_THREAD_CB_VBLANK_SW: { tdm_thread_cb_vblank_sw *vblank_sw = (tdm_thread_cb_vblank_sw*)base; tdm_vblank_cb_vblank_SW(NULL, vblank_sw->vblank_stamp); -- 2.7.4 From 37fd93539622189a546c8f00296d3e3a0ac8a9ae Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 29 Jan 2018 09:53:49 +0900 Subject: [PATCH 04/16] vblank: using thread_cb Change-Id: I2974baaff66cbe7fd1ea0e18ed89e68229efdd0f --- src/tdm.c | 2 + src/tdm_private.h | 4 - src/tdm_private_types.h | 3 +- src/tdm_thread.c | 12 +-- src/tdm_vblank.c | 228 ++++++++++++++++++++++++++++-------------------- 5 files changed, 138 insertions(+), 111 deletions(-) diff --git a/src/tdm.c b/src/tdm.c index b81347d..0213cb7 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -940,6 +940,8 @@ tdm_display_init(tdm_error *error) /* LCOV_EXCL_STOP */ } + private_display->stamp = tdm_helper_get_time(); + str = tdm_config_get_string(TDM_CONFIG_KEY_DEBUG_MODULE, NULL); if (str) tdm_display_enable_debug_module(str); diff --git a/src/tdm_private.h b/src/tdm_private.h index c19ceb4..44359f9 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -151,10 +151,6 @@ tdm_vblank_init(tdm_display *dpy); void tdm_vblank_deinit(tdm_display *dpy); tdm_error -tdm_vblank_cb_vblank_SW(tdm_vblank *vblank, double vblank_stamp); -tdm_error -tdm_vblank_cb_vblank_create(tdm_vblank *vblank, double vblank_stamp); -tdm_error tdm_vblank_set_add_front(tdm_vblank *vblank, unsigned int add_front); tdm_error tdm_vblank_set_resource(tdm_vblank *vblank, struct wl_resource *resource); diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index 188d3fe..4f3da84 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -118,6 +118,8 @@ struct _tdm_private_display { pthread_mutex_t lock; unsigned int init_count; + double stamp; + /* backend module info */ void *module; tdm_backend_module *module_data; @@ -498,7 +500,6 @@ struct _tdm_thread_cb_capture_done { struct _tdm_thread_cb_vblank_sw { tdm_thread_cb_base base; - double vblank_stamp; }; struct _tdm_thread_cb_vblank_create { diff --git a/src/tdm_thread.c b/src/tdm_thread.c index ff0d0c8..e9fec48 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -473,18 +473,10 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) } case TDM_THREAD_CB_PP_DONE: case TDM_THREAD_CB_CAPTURE_DONE: + case TDM_THREAD_CB_VBLANK_SW: + case TDM_THREAD_CB_VBLANK_CREATE: tdm_thread_cb_call(NULL, base); break; - case TDM_THREAD_CB_VBLANK_SW: { - tdm_thread_cb_vblank_sw *vblank_sw = (tdm_thread_cb_vblank_sw*)base; - tdm_vblank_cb_vblank_SW(NULL, vblank_sw->vblank_stamp); - break; - } - case TDM_THREAD_CB_VBLANK_CREATE: { - tdm_thread_cb_vblank_create *vblank_create = (tdm_thread_cb_vblank_create*)base; - tdm_vblank_cb_vblank_create(NULL, vblank_create->vblank_stamp); - break; - } case TDM_THREAD_CB_NEED_VALIDATE: { tdm_thread_cb_need_validate *ev = (tdm_thread_cb_need_validate*)base; tdm_output_cb_need_validate(ev->o); diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index ad4b9c0..12b760d 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -169,7 +169,8 @@ static unsigned int vblank_list_inited; static unsigned int vblank_global_fps; static double stamp = 0; -static tdm_error _tdm_vblank_cb_vblank_SW(void *user_data); +static void _tdm_vblank_cb_vblank_SW(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data); +static tdm_error _tdm_vblank_cb_timeout_SW(void *user_data); static tdm_error _tdm_vblank_wait_SW(tdm_vblank_wait_info *wait_info); static void _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, @@ -180,14 +181,25 @@ static void _tdm_vblank_get_client_information(tdm_private_vblank *private_vblan #if 0 static void -_print_list(struct list_head *list) +_print_list(tdm_private_vblank *private_vblank) { tdm_vblank_wait_info *w = NULL; + int count = 0; - LIST_FOR_EACH_ENTRY(w, list, link) { - printf(" %d", w->interval); + LIST_FOR_EACH_ENTRY(w, &private_vblank->HW_wait_list, link) { + VIN("HW_wait(%p): type(%d) req_time(%.6f) target_time(%.6f) target_seq(%u)", + w, w->type, w->req_time, w->target_time, w->target_seq); + count++; + } + + LIST_FOR_EACH_ENTRY(w, &private_vblank->SW_wait_list, link) { + VIN("SW_wait(%p): type(%d) req_time(%.6f) target_time(%.6f) target_seq(%u)", + w, w->type, w->req_time, w->target_time, w->target_seq); + count++; } - printf("\n"); + + if (!count) + VIN("NO_wait"); } #endif @@ -226,14 +238,11 @@ _tdm_vblank_valid_list_del(struct list_head *valid_link) pthread_mutex_unlock(&valid_list_lock); } -static inline tdm_private_vblank* -_tdm_vblank_find(double vblank_stamp) +static inline void* +_tdm_vblank_find_object(tdm_private_display *private_display, double vblank_stamp) { tdm_private_vblank *v = NULL; - if (!vblank_stamp) - return 0; - pthread_mutex_lock(&valid_list_lock); LIST_FOR_EACH_ENTRY(v, &valid_vblank_list, valid_link) { if (v->stamp == vblank_stamp) { @@ -243,7 +252,7 @@ _tdm_vblank_find(double vblank_stamp) } pthread_mutex_unlock(&valid_list_lock); - return 0; + return NULL; } static inline unsigned int @@ -353,7 +362,7 @@ _tdm_vblank_free_HW_wait(tdm_private_vblank *private_vblank, tdm_error error, un tdm_display_unlock(private_vblank->dpy); VDB("wait(%p) last(%.6f) sequence(%u) done (error:%d, call_cb:%u)", - w, 0, w->target_seq, error, call_cb); + w, (double)0.0, w->target_seq, error, call_cb); if (call_cb && w->func) w->func(private_vblank, error, 0, 0, 0, w->user_data); @@ -550,47 +559,45 @@ tdm_vblank_enable_global_fps(unsigned int enable, unsigned int fps) return TDM_ERROR_NONE; } -INTERN tdm_error -tdm_vblank_cb_vblank_create(tdm_vblank *vblank, double vblank_stamp) +static void +_tdm_vblank_thread_cb_create(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) { + tdm_thread_cb_vblank_create *vblank_create = (tdm_thread_cb_vblank_create *)cb_base; + tdm_vblank_create_handler_info *ch_info = user_data; tdm_private_vblank *private_vblank; - tdm_vblank_create_handler_info *ch_info = NULL, *hh = NULL; - TDM_RETURN_VAL_IF_FAIL(vblank || vblank_stamp > 0, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - if (vblank) - private_vblank = vblank; - else { - private_vblank = _tdm_vblank_find(vblank_stamp); - if (!private_vblank) { - TDM_DBG("can't find vblank(%.0f) from valid_list", vblank_stamp); - return TDM_ERROR_NONE; - } - } + assert(ch_info != NULL); - if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) { - tdm_thread_cb_vblank_create vblank_create; - tdm_private_display *private_display = private_vblank->dpy; - tdm_error ret; + private_vblank = _tdm_vblank_find_object(private_display, vblank_create->vblank_stamp); + if (!private_vblank) { + TDM_DBG("can't find vblank(%.0f) from valid_list", vblank_create->vblank_stamp); + return; + } - vblank_create.base.type = TDM_THREAD_CB_VBLANK_CREATE; - vblank_create.base.length = sizeof vblank_create; - vblank_create.vblank_stamp = private_vblank->stamp; + /* use in_create_handler instead of mutext unlock/lock */ + private_vblank->in_create_handler = 1; + ch_info->func(private_vblank, ch_info->user_data); + private_vblank->in_create_handler = 0; +} - ret = tdm_thread_send_cb(private_display->private_loop, &vblank_create.base); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); +static tdm_error +_tdm_vblank_call_thread_cb(tdm_private_vblank *private_vblank) +{ + tdm_thread_cb_vblank_create vblank_create; + tdm_error ret; - return TDM_ERROR_NONE; - } + memset(&vblank_create, 0, sizeof vblank_create); + vblank_create.base.type = TDM_THREAD_CB_VBLANK_CREATE; + vblank_create.base.length = sizeof vblank_create; + vblank_create.base.object_stamp = 1; + vblank_create.base.data = NULL; + vblank_create.base.sync = 0; + vblank_create.vblank_stamp = private_vblank->stamp; - LIST_FOR_EACH_ENTRY_SAFE(ch_info, hh, &create_handler_list, link) { - /* use in_create_handler instead of mutext unlock/lock */ - private_vblank->in_create_handler = 1; - //_pthread_mutex_unlock(&private_display->lock); - ch_info->func(private_vblank, ch_info->user_data); - //_pthread_mutex_lock(&private_display->lock); - private_vblank->in_create_handler = 0; - } + ret = tdm_thread_cb_call(private_vblank->dpy, &vblank_create.base); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); return TDM_ERROR_NONE; } @@ -598,27 +605,36 @@ tdm_vblank_cb_vblank_create(tdm_vblank *vblank, double vblank_stamp) EXTERN tdm_error tdm_vblank_add_create_handler(tdm_display *dpy, tdm_vblank_create_handler func, void *user_data) { - tdm_vblank_create_handler_info *ch_info; + tdm_vblank_create_handler_info *ch_info = NULL; + tdm_error ret; + TDM_RETURN_VAL_IF_FAIL(!TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); - /* we don't allow adding a create handler in sub-thread because tdm_vblank_create() - * can be called in both threads and tdm_thread_send_cb supports only one-way - * communication now. - */ - if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) { - TDM_ERR("add_create_handler should be called in main thread"); - return TDM_ERROR_BAD_REQUEST; + LIST_FOR_EACH_ENTRY(ch_info, &create_handler_list, link) { + if (ch_info->func == func && ch_info->user_data == user_data) { + TDM_ERR("can't be added twice"); + return TDM_ERROR_BAD_REQUEST; + } } ch_info = calloc(1, sizeof *ch_info); TDM_RETURN_VAL_IF_FAIL(ch_info != NULL, TDM_ERROR_OUT_OF_MEMORY); + tdm_display_lock(dpy); + ret = tdm_thread_cb_add(dpy, TDM_THREAD_CB_VBLANK_CREATE, NULL, _tdm_vblank_thread_cb_create, ch_info); + tdm_display_unlock(dpy); + + if (ret != TDM_ERROR_NONE) { + TDM_ERR("tdm_thread_cb_add failed"); + free(ch_info); + return ret; + } + ch_info->func = func; ch_info->user_data = user_data; LIST_ADDTAIL(&ch_info->link, &create_handler_list); - return TDM_ERROR_NONE; } @@ -627,6 +643,8 @@ tdm_vblank_remove_create_handler(tdm_display *dpy, tdm_vblank_create_handler fun { tdm_vblank_create_handler_info *ch_info = NULL, *hh = NULL; + TDM_RETURN_IF_FAIL(!TDM_MUTEX_IS_LOCKED()); + /* we don't allow adding a create handler in sub-thread because tdm_vblank_create() * can be called in both threads and tdm_thread_send_cb supports only one-way * communication now. @@ -636,14 +654,27 @@ tdm_vblank_remove_create_handler(tdm_display *dpy, tdm_vblank_create_handler fun return; } + tdm_display_lock(dpy); + LIST_FOR_EACH_ENTRY_SAFE(ch_info, hh, &create_handler_list, link) { if (ch_info->func != func && ch_info->user_data != user_data) continue; + tdm_thread_cb_remove(dpy, TDM_THREAD_CB_VBLANK_CREATE, NULL, _tdm_vblank_thread_cb_create, ch_info); + LIST_DEL(&ch_info->link); free(ch_info); + tdm_display_unlock(dpy); return; } + + tdm_display_unlock(dpy); +} + +static void* +_tdm_vblank_find_display(tdm_private_display *private_display, double stamp) +{ + return private_display; } INTERN tdm_error @@ -661,6 +692,9 @@ tdm_vblank_init(tdm_display *dpy) LIST_INITHEAD(&valid_wait_list); LIST_INITHEAD(&create_handler_list); + tdm_thread_cb_set_find_func(TDM_THREAD_CB_VBLANK_SW, _tdm_vblank_find_object); + tdm_thread_cb_set_find_func(TDM_THREAD_CB_VBLANK_CREATE, _tdm_vblank_find_display); + vblank_list_inited = 1; return TDM_ERROR_NONE; @@ -736,7 +770,7 @@ tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error) private_vblank->vrefresh, private_vblank->connection); tdm_display_lock(private_vblank->dpy); - tdm_vblank_cb_vblank_create(NULL, private_vblank->stamp); + _tdm_vblank_call_thread_cb(private_vblank); tdm_display_unlock(private_vblank->dpy); return (tdm_vblank *)private_vblank; @@ -759,6 +793,7 @@ tdm_vblank_destroy(tdm_vblank *vblank) if (private_vblank->SW_timer) { tdm_display_lock(private_vblank->dpy); + tdm_thread_cb_remove(private_vblank, TDM_THREAD_CB_VBLANK_SW, NULL, _tdm_vblank_cb_vblank_SW, NULL); tdm_event_loop_source_remove(private_vblank->SW_timer); tdm_display_unlock(private_vblank->dpy); } @@ -1083,7 +1118,7 @@ _tdm_vblank_sw_timer_update(tdm_private_vblank *private_vblank) if (!private_vblank->SW_timer) { private_vblank->SW_timer = tdm_event_loop_add_timer_handler(private_vblank->dpy, - _tdm_vblank_cb_vblank_SW, + _tdm_vblank_cb_timeout_SW, private_vblank, &ret); if (!private_vblank->SW_timer) { @@ -1091,6 +1126,16 @@ _tdm_vblank_sw_timer_update(tdm_private_vblank *private_vblank) VER("couldn't add timer"); return ret; } + + ret = tdm_thread_cb_add(private_vblank, TDM_THREAD_CB_VBLANK_SW, NULL, _tdm_vblank_cb_vblank_SW, NULL); + if (ret != TDM_ERROR_NONE) { + tdm_event_loop_source_remove(private_vblank->SW_timer); + private_vblank->SW_timer = NULL; + tdm_display_unlock(private_vblank->dpy); + VER("couldn't add thread_cb"); + return ret; + } + VIN("Create SW timer"); } @@ -1126,6 +1171,8 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, private_vblank = wait_info->private_vblank; TDM_RETURN_IF_FAIL(tdm_vblank_is_valid(private_vblank)); + assert(private_vblank->owner_tid == syscall(SYS_gettid)); + if (!_tdm_vblank_find_wait(wait_info, &private_vblank->HW_wait_list)) { VER("can't find wait(%p)", wait_info); return; @@ -1146,7 +1193,7 @@ _tdm_vblank_cb_vblank_HW(tdm_output *output, unsigned int sequence, ret = _tdm_vblank_sw_timer_update(private_vblank); - /* wait_info will be freed in _tdm_vblank_cb_vblank_SW() */ + /* wait_info will be freed in _tdm_vblank_cb_timeout_SW() */ if (ret == TDM_ERROR_NONE) { VIN("wait(%p) SW timer", wait_info); return; @@ -1271,59 +1318,26 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info) return TDM_ERROR_NONE; } -static tdm_error -_tdm_vblank_cb_vblank_SW(void *user_data) -{ - tdm_private_vblank *private_vblank = user_data; - - TDM_RETURN_VAL_IF_FAIL(tdm_vblank_is_valid(private_vblank), TDM_ERROR_OPERATION_FAILED); - - return tdm_vblank_cb_vblank_SW(private_vblank, 0); -} - -INTERN tdm_error -tdm_vblank_cb_vblank_SW(tdm_vblank *vblank, double vblank_stamp) +static void +_tdm_vblank_cb_vblank_SW(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) { - tdm_private_vblank *private_vblank; + tdm_private_vblank *private_vblank = object; tdm_vblank_wait_info *first_wait_info = NULL, *w = NULL, *ww = NULL; - TDM_RETURN_VAL_IF_FAIL(vblank || vblank_stamp > 0, TDM_ERROR_INVALID_PARAMETER); - - if (vblank) - private_vblank = vblank; - else { - private_vblank = _tdm_vblank_find(vblank_stamp); - if (!private_vblank) { - TDM_ERR("can't find vblank(%.0f) from valid_list", vblank_stamp); - return TDM_ERROR_NONE; - } - } - - if (private_vblank->owner_tid != syscall(SYS_gettid)) { - tdm_thread_cb_vblank_sw vblank_sw; - tdm_private_display *private_display = private_vblank->dpy; - tdm_error ret; + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - vblank_sw.base.type = TDM_THREAD_CB_VBLANK_SW; - vblank_sw.base.length = sizeof vblank_sw; - vblank_sw.vblank_stamp = private_vblank->stamp; - - ret = tdm_thread_send_cb(private_display->private_loop, &vblank_sw.base); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - - return TDM_ERROR_NONE; - } + assert(private_vblank->owner_tid == syscall(SYS_gettid)); if (LIST_IS_EMPTY(&private_vblank->SW_wait_list)) { VER("no wait_info"); - return TDM_ERROR_OPERATION_FAILED; + return; } if (!LIST_IS_EMPTY(&private_vblank->HW_wait_list)) TDM_NEVER_GET_HERE(); first_wait_info = container_of(private_vblank->SW_wait_list.next, first_wait_info, link); - TDM_RETURN_VAL_IF_FAIL(first_wait_info != NULL, TDM_ERROR_OPERATION_FAILED); + TDM_RETURN_IF_FAIL(first_wait_info != NULL); _tdm_vblank_timeout_timer_update(private_vblank, 0); @@ -1352,6 +1366,28 @@ tdm_vblank_cb_vblank_SW(tdm_vblank *vblank, double vblank_stamp) free(w); } +} + +static tdm_error +_tdm_vblank_cb_timeout_SW(void *user_data) +{ + tdm_private_vblank *private_vblank = user_data; + tdm_thread_cb_vblank_sw vblank_sw; + tdm_error ret; + + TDM_RETURN_VAL_IF_FAIL(tdm_vblank_is_valid(private_vblank), TDM_ERROR_OPERATION_FAILED); + + VIN("timeout_SW -> thread-cb"); + + memset(&vblank_sw, 0, sizeof vblank_sw); + vblank_sw.base.type = TDM_THREAD_CB_VBLANK_SW; + vblank_sw.base.length = sizeof vblank_sw; + vblank_sw.base.object_stamp = private_vblank->stamp; + vblank_sw.base.data = NULL; + vblank_sw.base.sync = 0; + + ret = tdm_thread_cb_call(private_vblank, &vblank_sw.base); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); return TDM_ERROR_NONE; } -- 2.7.4 From d7a3a75c32b83cc1859589e38ba5b1d0cb1a20ff Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 29 Jan 2018 09:54:16 +0900 Subject: [PATCH 05/16] output: using thread_cb Change-Id: I00fa06b60a2fa808df7a54d6739d1c4d8b3ae54e --- src/tdm.c | 54 +++--- src/tdm_macro.h | 3 +- src/tdm_output.c | 491 +++++++++++++++++++++--------------------------- src/tdm_private.h | 20 +- src/tdm_private_types.h | 34 +--- src/tdm_thread.c | 62 +----- 6 files changed, 263 insertions(+), 401 deletions(-) diff --git a/src/tdm.c b/src/tdm.c index 0213cb7..7fabc4a 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -61,9 +61,8 @@ _tdm_display_find_private_layer(tdm_private_output *private_output, return NULL; } -static tdm_private_output * -_tdm_display_find_private_output(tdm_private_display *private_display, - tdm_output *output_backend) +INTERN tdm_private_output * +tdm_display_find_private_output(tdm_private_display *private_display, tdm_output *output_backend) { tdm_private_output *private_output = NULL; @@ -75,7 +74,7 @@ _tdm_display_find_private_output(tdm_private_display *private_display, return NULL; } -INTERN tdm_private_output * +INTERN void * tdm_display_find_output_stamp(tdm_private_display *private_display, double stamp) { tdm_private_output *private_output = NULL; @@ -135,8 +134,6 @@ _tdm_display_destroy_private_layer(tdm_private_layer *private_layer) { tdm_private_capture *c = NULL, *cc = NULL; - LIST_DEL(&private_layer->link); - tdm_layer_unset_buffer_internal(private_layer); LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_layer->capture_list, link) @@ -144,6 +141,11 @@ _tdm_display_destroy_private_layer(tdm_private_layer *private_layer) _tdm_display_destroy_caps_layer(&private_layer->caps); + /* when destroying layer, someone could check if layer is valid. So delete + * the layer's link at last. + */ + LIST_DEL(&private_layer->link); + free(private_layer); } @@ -154,13 +156,11 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output) tdm_private_layer *l = NULL, *ll = NULL; tdm_private_hwc_window *hw = NULL, *hww = NULL; tdm_private_capture *c = NULL, *cc = NULL; - tdm_private_vblank_handler *v = NULL, *vv = NULL; + tdm_private_output_vblank_handler *v = NULL, *vv = NULL; tdm_private_output_commit_handler *om = NULL, *omm = NULL; tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL; tdm_private_output_change_handler *h = NULL, *hh = NULL; - LIST_DEL(&private_output->link); - free(private_output->layers_ptr); if (private_output->vblank_timeout_timer) @@ -186,13 +186,9 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output) free(lm); } - LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) { - LIST_DEL(&h->link); - free(h); - } - - LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) { + LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list, link) { LIST_DEL(&h->link); + tdm_thread_cb_remove(h->private_output, TDM_THREAD_CB_OUTPUT_CHANGE, NULL, tdm_output_thread_cb_change, h); free(h); } @@ -221,12 +217,16 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output) _tdm_display_destroy_caps_output(&private_output->caps); - if (private_output->dpms_changed_timer) - tdm_event_loop_source_remove(private_output->dpms_changed_timer); - + tdm_thread_cb_remove(private_output, TDM_THREAD_CB_NEED_VALIDATE, NULL, + tdm_output_need_validate_handler_thread, NULL); tdm_event_loop_source_remove(private_output->need_validate.event_source); close(private_output->need_validate.event_fd); + /* when destroying output, vblank objects are also destroyed. vblank checks + * if output object is valid. So delete the output's link at last. + */ + LIST_DEL(&private_output->link); + private_output->stamp = 0; free(private_output); } @@ -401,7 +401,7 @@ tdm_display_update_output(tdm_private_display *private_display, int layer_count = 0, i; tdm_error ret; - private_output = _tdm_display_find_private_output(private_display, output_backend); + private_output = tdm_display_find_private_output(private_display, output_backend); if (!private_output) { private_output = calloc(1, sizeof(tdm_private_output)); TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY); @@ -425,8 +425,7 @@ tdm_display_update_output(tdm_private_display *private_display, LIST_INITHEAD(&private_output->output_commit_handler_list); LIST_INITHEAD(&private_output->layer_commit_handler_list); LIST_INITHEAD(&private_output->pending_commit_handler_list); - LIST_INITHEAD(&private_output->change_handler_list_main); - LIST_INITHEAD(&private_output->change_handler_list_sub); + LIST_INITHEAD(&private_output->change_handler_list); if (func_output->output_set_status_handler) { func_output->output_set_status_handler(private_output->output_backend, @@ -976,6 +975,10 @@ tdm_display_init(tdm_error *error) TDM_INFO("event loop init time: %.3f ms", (stamp2 - stamp1) * 1000.0); stamp1 = stamp2; + ret = tdm_output_init(private_display); + if (ret != TDM_ERROR_NONE) + goto failed_load; + ret = tdm_pp_init(private_display); if (ret != TDM_ERROR_NONE) goto failed_load; @@ -1100,11 +1103,16 @@ tdm_display_deinit(tdm_display *dpy) */ _pthread_mutex_lock(&private_display->lock); tdm_event_loop_stop(private_display); + tdm_event_loop_deinit(private_display); + _pthread_mutex_unlock(&private_display->lock); + + /* when private_output is destroyed, all vblank resources of client and server + * are destroyed. Then we can call tdm_vblank_deinit. After destroying display, + * we can unload backend modulues. + */ _tdm_display_destroy_private_display(private_display); _tdm_display_unload_module(private_display); - _pthread_mutex_unlock(&private_display->lock); - tdm_event_loop_deinit(private_display); tdm_vblank_deinit(private_display); #ifdef INIT_BUFMGR diff --git a/src/tdm_macro.h b/src/tdm_macro.h index 77538a3..98f25b4 100644 --- a/src/tdm_macro.h +++ b/src/tdm_macro.h @@ -236,8 +236,7 @@ static struct tdm_type_name tdm_cb_type_names[] = { { TDM_THREAD_CB_NONE, "none" }, { TDM_THREAD_CB_OUTPUT_COMMIT, "output-commit" }, { TDM_THREAD_CB_OUTPUT_VBLANK, "output-vblank" }, - { TDM_THREAD_CB_OUTPUT_STATUS, "output-status" }, - { TDM_THREAD_CB_OUTPUT_DPMS, "output-dpms" }, + { TDM_THREAD_CB_OUTPUT_CHANGE, "output-change" }, { TDM_THREAD_CB_PP_DONE, "pp-done" }, { TDM_THREAD_CB_CAPTURE_DONE, "capture-done" }, { TDM_THREAD_CB_VBLANK_SW, "vblank-sw" }, diff --git a/src/tdm_output.c b/src/tdm_output.c index 1edf7fc..accdfa3 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -64,7 +64,7 @@ static tdm_error _tdm_output_vblank_timeout_cb(void *user_data) { tdm_private_output *private_output = user_data; - tdm_private_vblank_handler *v = NULL; + tdm_private_output_vblank_handler *v = NULL; TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OPERATION_FAILED); @@ -81,7 +81,7 @@ _tdm_output_vblank_timeout_cb(void *user_data) INTERN void tdm_output_vblank_print_wait_information(tdm_private_output *private_output, void *user_data) { - tdm_private_vblank_handler *v = NULL; + tdm_private_output_vblank_handler *v = NULL; TDM_RETURN_IF_FAIL(private_output != NULL); TDM_RETURN_IF_FAIL(user_data != NULL); @@ -135,6 +135,16 @@ _tdm_output_find_private_hwc_window(tdm_private_output *private_output, return NULL; } +INTERN tdm_error +tdm_output_init(tdm_private_display *private_display) +{ + tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_COMMIT, tdm_display_find_output_stamp); + tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_VBLANK, tdm_display_find_output_stamp); + tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_CHANGE, tdm_display_find_output_stamp); + + return TDM_ERROR_NONE; +} + EXTERN tdm_error tdm_output_get_model_info(tdm_output *output, const char **maker, const char **model, const char **name) @@ -202,59 +212,80 @@ _tdm_output_update(tdm_output *output_backend, void *user_data) ret = tdm_display_update_output(private_display, output_backend, private_output->pipe); TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); } +/* LCOV_EXCL_STOP */ INTERN void -tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, - void *user_data) +tdm_output_thread_cb_change(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) { - tdm_private_display *private_display; - tdm_private_output *private_output = user_data; - tdm_value value; + tdm_private_output *private_output = object; + tdm_thread_cb_output_change *output_change = (tdm_thread_cb_output_change *)cb_base; + tdm_private_output_change_handler *change_handler = user_data; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - TDM_RETURN_IF_FAIL(private_output); - - private_display = private_output->private_display; - if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) { - tdm_thread_cb_output_status output_status; - tdm_error ret; + assert(change_handler->owner_tid == syscall(SYS_gettid)); - TDM_INFO("output(%d) sub %s", private_output->pipe, tdm_status_str(status)); + _pthread_mutex_unlock(&private_display->lock); + change_handler->func(private_output, output_change->type, output_change->value, change_handler->user_data); + _pthread_mutex_lock(&private_display->lock); +} - _tdm_output_update(output_backend, user_data); +static tdm_error +_tdm_output_call_thread_cb_change(tdm_private_output *private_output, tdm_output_change_type type, tdm_value value) +{ + tdm_thread_cb_output_change output_change; + tdm_error ret; - output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS; - output_status.base.length = sizeof output_status; - output_status.output_stamp = private_output->stamp; - output_status.status = status; - output_status.user_data = user_data; + memset(&output_change, 0, sizeof output_change); + output_change.base.type = TDM_THREAD_CB_OUTPUT_CHANGE; + output_change.base.length = sizeof output_change; + output_change.base.object_stamp = private_output->stamp; + output_change.base.data = NULL; + output_change.base.sync = 1; + output_change.type = type; + output_change.value = value; - value.u32 = status; - tdm_output_call_change_handler_internal(private_output, - &private_output->change_handler_list_sub, - TDM_OUTPUT_CHANGE_CONNECTION, - value); + ret = tdm_thread_cb_call(private_output, &output_change.base); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - ret = tdm_thread_send_cb(private_display->private_loop, &output_status.base); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); + return TDM_ERROR_NONE; +} - return; - } +INTERN void +tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, void *user_data) +{ + tdm_private_output *private_output = user_data; + tdm_value value; + tdm_error ret; TDM_INFO("output(%d) main %s", private_output->pipe, tdm_status_str(status)); - if (!tdm_thread_is_running()) - _tdm_output_update(output_backend, user_data); - private_output->caps.status = status; + _tdm_output_update(output_backend, user_data); value.u32 = status; - tdm_output_call_change_handler_internal(private_output, - &private_output->change_handler_list_main, - TDM_OUTPUT_CHANGE_CONNECTION, - value); + + ret = _tdm_output_call_thread_cb_change(private_output, TDM_OUTPUT_CHANGE_CONNECTION, value); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); +} + +INTERN void +tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data) +{ + tdm_private_output *private_output = user_data; + tdm_value value; + tdm_error ret; + + TDM_INFO("output(%d) %s", private_output->pipe, tdm_status_str(dpms)); + + private_output->current_dpms_value = dpms; + private_output->waiting_dpms_change = 0; + TDM_INFO("output(%d) dpms async '%s' done", private_output->pipe, tdm_dpms_str(dpms)); + + value.u32 = dpms; + + ret = _tdm_output_call_thread_cb_change(private_output, TDM_OUTPUT_CHANGE_DPMS, value); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); } -/* LCOV_EXCL_STOP */ EXTERN tdm_error tdm_output_add_change_handler(tdm_output *output, @@ -277,15 +308,22 @@ tdm_output_add_change_handler(tdm_output *output, /* LCOV_EXCL_STOP */ } + ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_CHANGE, NULL, tdm_output_thread_cb_change, change_handler); + if (ret != TDM_ERROR_NONE) { + /* LCOV_EXCL_START */ + TDM_ERR("tdm_thread_cb_add failed"); + free(change_handler); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_OPERATION_FAILED; + /* LCOV_EXCL_STOP */ + } + change_handler->private_output = private_output; change_handler->func = func; change_handler->user_data = user_data; change_handler->owner_tid = syscall(SYS_gettid); - if (!tdm_thread_in_display_thread(change_handler->owner_tid)) - LIST_ADDTAIL(&change_handler->link, &private_output->change_handler_list_sub); - else - LIST_ADDTAIL(&change_handler->link, &private_output->change_handler_list_main); + LIST_ADDTAIL(&change_handler->link, &private_output->change_handler_list); _pthread_mutex_unlock(&private_display->lock); @@ -299,7 +337,7 @@ tdm_output_remove_change_handler(tdm_output *output, { tdm_private_display *private_display; tdm_private_output *private_output; - tdm_private_output_change_handler *h = NULL, *hh = NULL; + tdm_private_output_change_handler *change_handler = NULL, *hh = NULL; TDM_RETURN_IF_FAIL(tdm_output_is_valid(output)); TDM_RETURN_IF_FAIL(func != NULL); @@ -309,24 +347,14 @@ tdm_output_remove_change_handler(tdm_output *output, _pthread_mutex_lock(&private_display->lock); - LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) { - if (h->func != func || h->user_data != user_data) + LIST_FOR_EACH_ENTRY_SAFE(change_handler, hh, &private_output->change_handler_list, link) { + if (change_handler->func != func || change_handler->user_data != user_data) continue; - LIST_DEL(&h->link); - free(h); - - _pthread_mutex_unlock(&private_display->lock); - - return; - } - - LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) { - if (h->func != func || h->user_data != user_data) - continue; + tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_CHANGE, NULL, tdm_output_thread_cb_change, change_handler); - LIST_DEL(&h->link); - free(h); + LIST_DEL(&change_handler->link); + free(change_handler); _pthread_mutex_unlock(&private_display->lock); @@ -644,50 +672,26 @@ tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value) return ret; } -INTERN void -tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, void *user_data) +static void +_tdm_output_thread_cb_vblank(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) { - tdm_private_vblank_handler *vblank_handler = user_data; - tdm_private_vblank_handler *v = NULL, *vv = NULL; - tdm_private_output *private_output; - tdm_private_display *private_display; + tdm_thread_cb_output_vblank *output_vblank = (tdm_thread_cb_output_vblank *)cb_base; + tdm_private_output_vblank_handler *vblank_handler = output_vblank->base.data; + tdm_private_output_vblank_handler *v = NULL, *vv = NULL; + tdm_private_output *private_output = object; struct list_head clone_list; int interval, sync; pid_t tid = syscall(SYS_gettid); TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - TDM_RETURN_IF_FAIL(vblank_handler); - - private_output = vblank_handler->private_output; - private_display = private_output->private_display; - - if (vblank_handler->owner_tid != tid) { - tdm_thread_cb_output_vblank output_vblank; - tdm_error ret; - vblank_handler->sent_to_frontend = 1; - - output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK; - output_vblank.base.length = sizeof output_vblank; - output_vblank.output_stamp = vblank_handler->private_output->stamp; - output_vblank.sequence = sequence; - output_vblank.tv_sec = tv_sec; - output_vblank.tv_usec = tv_usec; - output_vblank.user_data = user_data; - - ret = tdm_thread_send_cb(private_display->private_loop, &output_vblank.base); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - - return; - } + assert(vblank_handler->owner_tid == tid); vblank_handler->sent_to_frontend = 0; _tdm_output_vblank_timeout_update(private_output, 0); - if (vblank_handler->owner_tid != tid) - TDM_NEVER_GET_HERE(); + tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_VBLANK, vblank_handler, _tdm_output_thread_cb_vblank, NULL); interval = vblank_handler->interval; sync = vblank_handler->sync; @@ -713,7 +717,11 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, LIST_DEL(&v->link); if (v->func) - v->func(v->private_output, sequence, tv_sec, tv_usec, v->user_data); + v->func(v->private_output, + output_vblank->sequence, + output_vblank->tv_sec, + output_vblank->tv_usec, + v->user_data); free(v); } @@ -723,13 +731,36 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, TDM_INFO("-----------------------------------------..."); } -INTERN void -tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, void *user_data) +static void +_tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) { - tdm_private_output_commit_handler *output_commit_handler = user_data; - tdm_private_display *private_display; - tdm_private_output *private_output; + tdm_private_output_vblank_handler *vblank_handler = user_data; + tdm_thread_cb_output_vblank output_vblank; + tdm_error ret; + + memset(&output_vblank, 0, sizeof output_vblank); + output_vblank.base.type = TDM_THREAD_CB_OUTPUT_VBLANK; + output_vblank.base.length = sizeof output_vblank; + output_vblank.base.object_stamp = vblank_handler->private_output->stamp; + output_vblank.base.data = vblank_handler; + output_vblank.base.sync = 0; + output_vblank.sequence = sequence; + output_vblank.tv_sec = tv_sec; + output_vblank.tv_usec = tv_usec; + + vblank_handler->sent_to_frontend = 1; + + ret = tdm_thread_cb_call(vblank_handler->private_output, &output_vblank.base); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); +} + +static void +_tdm_output_thread_cb_commit(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) +{ + tdm_thread_cb_output_commit *output_commit = (tdm_thread_cb_output_commit *)cb_base; + tdm_private_output_commit_handler *output_commit_handler = output_commit->base.data; + tdm_private_output *private_output = object; tdm_private_layer *private_layer = NULL; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); @@ -737,26 +768,9 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, if (!output_commit_handler) return; - private_output = output_commit_handler->private_output; - private_display = private_output->private_display; - - if (output_commit_handler->owner_tid != syscall(SYS_gettid)) { - tdm_thread_cb_output_commit output_commit; - tdm_error ret; - - output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT; - output_commit.base.length = sizeof output_commit; - output_commit.output_stamp = private_output->stamp; - output_commit.sequence = sequence; - output_commit.tv_sec = tv_sec; - output_commit.tv_usec = tv_usec; - output_commit.user_data = user_data; + assert(output_commit_handler->owner_tid == syscall(SYS_gettid)); - ret = tdm_thread_send_cb(private_display->private_loop, &output_commit.base); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - - return; - } + tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_COMMIT, output_commit_handler, _tdm_output_thread_cb_commit, NULL); LIST_DEL(&output_commit_handler->link); @@ -775,8 +789,11 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, if (output_commit_handler->func) { _pthread_mutex_unlock(&private_display->lock); - output_commit_handler->func(private_output, sequence, - tv_sec, tv_usec, output_commit_handler->user_data); + output_commit_handler->func(private_output, + output_commit->sequence, + output_commit->tv_sec, + output_commit->tv_usec, + output_commit_handler->user_data); _pthread_mutex_lock(&private_display->lock); } @@ -786,23 +803,50 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, TDM_INFO("-----------------------------------------..."); } +static void +_tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + tdm_private_output_commit_handler *output_commit_handler = user_data; + tdm_private_output *private_output; + tdm_thread_cb_output_commit output_commit; + tdm_error ret; + + if (output_commit_handler) + private_output = output_commit_handler->private_output; + else + private_output = tdm_display_find_private_output(tdm_display_get(), output_backend); + + memset(&output_commit, 0, sizeof output_commit); + output_commit.base.type = TDM_THREAD_CB_OUTPUT_COMMIT; + output_commit.base.length = sizeof output_commit; + output_commit.base.object_stamp = private_output->stamp; + output_commit.base.data = output_commit_handler; + output_commit.base.sync = 0; + output_commit.sequence = sequence; + output_commit.tv_sec = tv_sec; + output_commit.tv_usec = tv_usec; + + ret = tdm_thread_cb_call(private_output, &output_commit.base); + TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); +} + /* add_front: To distinguish between the user vblank handlers and the layer * commit vblank handlers. The layer commit handlers will be called * before calling the user vblank handlers. */ static tdm_error -_tdm_output_wait_vblank(tdm_output *output, int interval, int sync, +_tdm_output_wait_vblank(tdm_private_output *private_output, int interval, int sync, tdm_output_vblank_handler func, void *user_data, unsigned int add_front) { tdm_func_output *func_output; - tdm_private_vblank_handler *vblank_handler = NULL, *v = NULL; + tdm_private_output_vblank_handler *vblank_handler = NULL, *v = NULL; unsigned int skip_request = 0; pid_t tid = syscall(SYS_gettid); + tdm_error ret = TDM_ERROR_NONE; - OUTPUT_FUNC_ENTRY(); - - func_output = &private_display->func_output; + func_output = &private_output->private_display->func_output; /* interval SHOULD be at least 1 */ if (interval <= 0) @@ -818,10 +862,10 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, if (!private_output->regist_vblank_cb) { private_output->regist_vblank_cb = 1; ret = func_output->output_set_vblank_handler(private_output->output_backend, - tdm_output_cb_vblank); + _tdm_output_cb_vblank); } - vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler)); + vblank_handler = calloc(1, sizeof(tdm_private_output_vblank_handler)); if (!vblank_handler) { /* LCOV_EXCL_START */ TDM_ERR("failed: alloc memory"); @@ -853,6 +897,12 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, /* If there is the previous request, we can skip to call output_wait_vblank() */ if (!skip_request) { + ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_VBLANK, vblank_handler, _tdm_output_thread_cb_vblank, NULL); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("tdm_thread_cb_add failed"); + goto wait_failed; + } + ret = func_output->output_wait_vblank(private_output->output_backend, interval, sync, vblank_handler); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed); @@ -868,6 +918,7 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, wait_failed: /* LCOV_EXCL_START */ if (vblank_handler) { + tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_VBLANK, vblank_handler, _tdm_output_thread_cb_vblank, NULL); LIST_DEL(&vblank_handler->link); free(vblank_handler); } @@ -890,7 +941,7 @@ tdm_output_wait_vblank(tdm_output *output, int interval, int sync, return TDM_ERROR_DPMS_OFF; } - ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 0); + ret = _tdm_output_wait_vblank(private_output, interval, sync, func, user_data, 0); _pthread_mutex_unlock(&private_display->lock); @@ -913,7 +964,7 @@ tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync, return TDM_ERROR_DPMS_OFF; } - ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 1); + ret = _tdm_output_wait_vblank(private_output, interval, sync, func, user_data, 1); _pthread_mutex_unlock(&private_display->lock); @@ -925,7 +976,7 @@ INTERN void tdm_output_remove_vblank_handler_internal(tdm_output *output, tdm_output_vblank_handler func, void *user_data) { tdm_private_output *private_output = (tdm_private_output*)output; - tdm_private_vblank_handler *v = NULL; + tdm_private_output_vblank_handler *v = NULL; TDM_RETURN_IF_FAIL(private_output != NULL); TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); @@ -1013,8 +1064,7 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl if (func) { if (!private_output->regist_commit_cb) { private_output->regist_commit_cb = 1; - ret = func_output->output_set_commit_handler(private_output->output_backend, - tdm_output_cb_commit); + ret = func_output->output_set_commit_handler(private_output->output_backend, _tdm_output_cb_commit); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); } @@ -1026,6 +1076,13 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl /* LCOV_EXCL_STOP */ } + ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_COMMIT, output_commit_handler, _tdm_output_thread_cb_commit, NULL); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("tdm_thread_cb_add failed"); + free(output_commit_handler); + return ret; + } + LIST_ADDTAIL(&output_commit_handler->link, &private_output->output_commit_handler_list); output_commit_handler->private_output = private_output; output_commit_handler->func = func; @@ -1068,6 +1125,7 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl commit_failed: /* LCOV_EXCL_START */ if (output_commit_handler) { + tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_COMMIT, output_commit_handler, _tdm_output_thread_cb_commit, NULL); LIST_DEL(&output_commit_handler->link); free(output_commit_handler); } @@ -1169,110 +1227,6 @@ tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode) return ret; } -static tdm_error -_tdm_output_dpms_changed_timeout(void *user_data) -{ - tdm_private_output *private_output = user_data; - tdm_value value; - - value.u32 = private_output->current_dpms_value; - tdm_output_call_change_handler_internal(private_output, - &private_output->change_handler_list_sub, - TDM_OUTPUT_CHANGE_DPMS, - value); - - return TDM_ERROR_NONE; -} - -static tdm_error -tdm_output_call_dpms_change_handler(tdm_output *output) -{ - tdm_private_output *private_output = (tdm_private_output*)output; - tdm_value value; - - /** Use timer to call the output change callback of the sub-thread. - * The output change callback of tdm_server and tdm_vblank was called - * in the main thread. And it made the multi thread issue. If we use - * the timer, we can call the sub-thread's output change callback in - * sub-thread. - */ - if (!private_output->dpms_changed_timer) { - private_output->dpms_changed_timer = - tdm_event_loop_add_timer_handler(private_output->private_display, - _tdm_output_dpms_changed_timeout, private_output, NULL); - if (!private_output->dpms_changed_timer) { - /* LCOV_EXCL_START */ - TDM_ERR("can't create dpms timer!!"); - return TDM_ERROR_OUT_OF_MEMORY; - /* LCOV_EXCL_STOP */ - } - } - - value.u32 = private_output->current_dpms_value; - tdm_output_call_change_handler_internal(private_output, - &private_output->change_handler_list_main, - TDM_OUTPUT_CHANGE_DPMS, - value); - - if (!LIST_IS_EMPTY(&private_output->change_handler_list_sub)) { - tdm_error ret = tdm_event_loop_source_timer_update(private_output->dpms_changed_timer, 1); - if (ret != TDM_ERROR_NONE) - TDM_NEVER_GET_HERE(); - } - - return TDM_ERROR_NONE; -} - -/* LCOV_EXCL_START */ -INTERN void -tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data) -{ - tdm_private_display *private_display; - tdm_private_output *private_output = user_data; - tdm_value value; - - TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - TDM_RETURN_IF_FAIL(private_output); - - private_display = private_output->private_display; - - if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) { - tdm_thread_cb_output_dpms output_dpms; - tdm_error ret; - - _tdm_output_update(output_backend, user_data); - - output_dpms.base.type = TDM_THREAD_CB_OUTPUT_DPMS; - output_dpms.base.length = sizeof output_dpms; - output_dpms.output_stamp = private_output->stamp; - output_dpms.dpms = dpms; - output_dpms.user_data = user_data; - - value.u32 = dpms; - tdm_output_call_change_handler_internal(private_output, - &private_output->change_handler_list_sub, - TDM_OUTPUT_CHANGE_DPMS, - value); - - ret = tdm_thread_send_cb(private_display->private_loop, &output_dpms.base); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - - return; - } - - private_output->current_dpms_value = dpms; - private_output->waiting_dpms_change = 0; - - TDM_INFO("output(%d) dpms async '%s' done", private_output->pipe, tdm_dpms_str(dpms)); - - value.u32 = dpms; - tdm_output_call_change_handler_internal(private_output, - &private_output->change_handler_list_main, - TDM_OUTPUT_CHANGE_DPMS, - value); -} -/* LCOV_EXCL_STOP */ - EXTERN tdm_error tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) { @@ -1317,9 +1271,11 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) done: if (ret == TDM_ERROR_NONE) { if (private_output->current_dpms_value != dpms_value) { + tdm_value value; private_output->current_dpms_value = dpms_value; + value.u32 = dpms_value; + _tdm_output_call_thread_cb_change(private_output, TDM_OUTPUT_CHANGE_DPMS, value); TDM_INFO("output(%d) dpms '%s' done", private_output->pipe, tdm_dpms_str(dpms_value)); - tdm_output_call_dpms_change_handler(output); } } else { tdm_output_dpms temp = TDM_OUTPUT_DPMS_OFF; @@ -1452,11 +1408,13 @@ tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value) /* checking with backend's value */ if (*dpms_value != private_output->current_dpms_value) { + tdm_value value; TDM_ERR("output(%d) dpms changed suddenly: %s -> %s", private_output->pipe, private_output->current_dpms_value, tdm_dpms_str(*dpms_value)); private_output->current_dpms_value = *dpms_value; - tdm_output_call_dpms_change_handler(output); + value.u32 = *dpms_value; + _tdm_output_call_thread_cb_change(private_output, TDM_OUTPUT_CHANGE_DPMS, value); } return ret; @@ -2017,42 +1975,6 @@ tdm_output_hwc_get_video_supported_formats(tdm_output *output, const tbm_format return ret; } -INTERN void -tdm_output_call_change_handler_internal(tdm_private_output *private_output, - struct list_head *change_handler_list, - tdm_output_change_type type, - tdm_value value) -{ - tdm_private_display *private_display; - tdm_private_output_change_handler *change_handler = NULL; - - TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); - TDM_RETURN_IF_FAIL(private_output); - - private_display = private_output->private_display; - if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) { - if (type & TDM_OUTPUT_CHANGE_CONNECTION) - TDM_INFO("output(%d) changed: %s (%d)", - private_output->pipe, tdm_status_str(value.u32), value.u32); - if (type & TDM_OUTPUT_CHANGE_DPMS) - TDM_INFO("output(%d) changed: dpms %s (%d)", - private_output->pipe, tdm_dpms_str(value.u32), value.u32); - } - - if (LIST_IS_EMPTY(change_handler_list)) - return; - - LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) { - if (change_handler->owner_tid != syscall(SYS_gettid)) - TDM_NEVER_GET_HERE(); - - _pthread_mutex_unlock(&private_display->lock); - change_handler->func(private_output, type, - value, change_handler->user_data); - _pthread_mutex_lock(&private_display->lock); - } -} - static int _is_hwc_output_still_existed(tdm_private_output *private_output) { @@ -2079,22 +2001,28 @@ exist: } /* gets called on behalf of the ecore-main-loop thread */ -INTERN tdm_error -tdm_output_cb_need_validate(tdm_private_output *private_output) +INTERN void +tdm_output_need_validate_handler_thread(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) { - TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER); + tdm_private_output *private_output = object; + + TDM_RETURN_IF_FAIL(private_output != NULL); + + _pthread_mutex_lock(&private_display->lock); /* as we get 'private_output' within an event, an output this 'private_output' * points to can be destroyed already */ - if (!_is_hwc_output_still_existed(private_output)) - return TDM_ERROR_NONE; + if (!_is_hwc_output_still_existed(private_output)) { + _pthread_mutex_unlock(&private_display->lock); + return; + } + + _pthread_mutex_unlock(&private_display->lock); TDM_INFO("tdm-backend asks for revalidation for the output:%p.", private_output); if (private_output->need_validate.hndl) private_output->need_validate.hndl((tdm_output*)private_output); - - return TDM_ERROR_NONE; } /* gets called on behalf of the tdm-thread */ @@ -2113,11 +2041,14 @@ _need_validate_handler(int fd, tdm_event_loop_mask mask, void *user_data) return TDM_ERROR_OPERATION_FAILED; } + memset(&ev, 0, sizeof ev); ev.base.type = TDM_THREAD_CB_NEED_VALIDATE; ev.base.length = sizeof ev; - ev.o = private_output; + ev.base.object_stamp = private_output->stamp; + ev.base.data = NULL; + ev.base.sync = 0; - ret = tdm_thread_send_cb(private_output->private_display->private_loop, &ev.base); + ret = tdm_thread_cb_call(private_output, &ev.base); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); TDM_INFO("tdm-thread: get a 'need to revalidate' event for the ouptut:%p.", private_output); diff --git a/src/tdm_private.h b/src/tdm_private.h index 44359f9..a35aea8 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -90,18 +90,18 @@ tdm_display_get(void); int tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, int abimin); -tdm_private_output * +void * tdm_display_find_output_stamp(tdm_private_display *private_display, double stamp); +tdm_private_output * +tdm_display_find_private_output(tdm_private_display *private_display, tdm_output *output_backend); +tdm_error +tdm_output_init(tdm_private_display *private_display); int tdm_output_is_valid(tdm_output *output); void -tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, void *user_data); -void -tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec, void *user_data); +tdm_output_thread_cb_change(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data); void tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, void *user_data); @@ -123,6 +123,8 @@ tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value); tdm_error tdm_output_need_validate_event_init(tdm_output *output); +void +tdm_output_need_validate_handler_thread(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data); tdm_error tdm_output_choose_commit_per_vblank_mode(tdm_private_output *private_output, int mode); @@ -161,12 +163,6 @@ tdm_vblank_set_client_vblank_fps(unsigned int pid, const char *name, unsigned in void tdm_vblank_get_vblank_list_information(tdm_display *dpy, char *reply, int *len); -void -tdm_output_call_change_handler_internal(tdm_private_output *private_output, - struct list_head *change_handler_list, - tdm_output_change_type type, - tdm_value value); - tdm_error tdm_pp_init(tdm_private_display *private_display); tdm_private_pp * diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index 4f3da84..77393f1 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -105,9 +105,9 @@ typedef struct _tdm_private_capture tdm_private_capture; typedef struct _tdm_private_loop tdm_private_loop; typedef struct _tdm_private_server tdm_private_server; typedef struct _tdm_private_thread tdm_private_thread; -typedef struct _tdm_private_vblank_handler tdm_private_vblank_handler; typedef struct _tdm_private_output_change_handler tdm_private_output_change_handler; typedef struct _tdm_private_output_commit_handler tdm_private_output_commit_handler; +typedef struct _tdm_private_output_vblank_handler tdm_private_output_vblank_handler; typedef struct _tdm_private_layer_commit_handler tdm_private_layer_commit_handler; typedef struct _tdm_private_hwc_window_commit_handler tdm_private_hwc_window_commit_handler; typedef struct _tdm_private_output_hwc_target_buffer_window_commit_handler tdm_private_output_hwc_target_buffer_commit_handler; @@ -194,15 +194,10 @@ struct _tdm_private_output { tdm_event_loop_source *vblank_timeout_timer; - /* seperate list for multi-thread*/ - struct list_head change_handler_list_main; - struct list_head change_handler_list_sub; + struct list_head change_handler_list; void **layers_ptr; - /* TODO: temp solution for handling DPMS things in sub-htread */ - tdm_event_loop_source *dpms_changed_timer; - struct { /* look at the tdm_output_set_need_revalidate_handler() declaration for the details */ tdm_output_need_validate_handler hndl; @@ -344,7 +339,7 @@ struct _tdm_private_loop { tdm_private_thread *private_thread; }; -struct _tdm_private_vblank_handler { +struct _tdm_private_output_vblank_handler { struct list_head link; tdm_private_output *private_output; @@ -435,8 +430,7 @@ typedef enum { TDM_THREAD_CB_NONE, TDM_THREAD_CB_OUTPUT_COMMIT, TDM_THREAD_CB_OUTPUT_VBLANK, - TDM_THREAD_CB_OUTPUT_STATUS, - TDM_THREAD_CB_OUTPUT_DPMS, + TDM_THREAD_CB_OUTPUT_CHANGE, TDM_THREAD_CB_PP_DONE, TDM_THREAD_CB_CAPTURE_DONE, TDM_THREAD_CB_VBLANK_SW, @@ -448,8 +442,7 @@ typedef enum { typedef struct _tdm_thread_cb_base tdm_thread_cb_base; typedef struct _tdm_thread_cb_output_vblank tdm_thread_cb_output_commit; typedef struct _tdm_thread_cb_output_vblank tdm_thread_cb_output_vblank; -typedef struct _tdm_thread_cb_output_status tdm_thread_cb_output_status; -typedef struct _tdm_thread_cb_output_dpms tdm_thread_cb_output_dpms; +typedef struct _tdm_thread_cb_output_change tdm_thread_cb_output_change; typedef struct _tdm_thread_cb_pp_done tdm_thread_cb_pp_done; typedef struct _tdm_thread_cb_capture_done tdm_thread_cb_capture_done; typedef struct _tdm_thread_cb_vblank_sw tdm_thread_cb_vblank_sw; @@ -466,25 +459,15 @@ struct _tdm_thread_cb_base { struct _tdm_thread_cb_output_vblank { tdm_thread_cb_base base; - double output_stamp; unsigned int sequence; unsigned int tv_sec; unsigned int tv_usec; - void *user_data; }; -struct _tdm_thread_cb_output_status { +struct _tdm_thread_cb_output_change { tdm_thread_cb_base base; - double output_stamp; - tdm_output_conn_status status; - void *user_data; -}; - -struct _tdm_thread_cb_output_dpms { - tdm_thread_cb_base base; - double output_stamp; - tdm_output_dpms dpms; - void *user_data; + tdm_output_change_type type; + tdm_value value; }; struct _tdm_thread_cb_pp_done { @@ -509,7 +492,6 @@ struct _tdm_thread_cb_vblank_create { struct _tdm_thread_cb_need_validate { tdm_thread_cb_base base; - tdm_private_output *o; }; struct argument_details { diff --git a/src/tdm_thread.c b/src/tdm_thread.c index e9fec48..cf76c82 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -418,70 +418,16 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) if (tdm_debug_module & TDM_DEBUG_THREAD) TDM_INFO("type(%d), length(%d)", base->type, base->length); switch (base->type) { - case TDM_THREAD_CB_OUTPUT_COMMIT: { - tdm_thread_cb_output_commit *output_commit = (tdm_thread_cb_output_commit*)base; - tdm_output *output_backend = - tdm_display_find_output_stamp(private_loop->dpy, output_commit->output_stamp); - if (!output_backend) { - TDM_WRN("no output(%f)", output_commit->output_stamp); - break; - } - tdm_output_cb_commit(output_backend, output_commit->sequence, - output_commit->tv_sec, output_commit->tv_usec, - output_commit->user_data); - break; - } - case TDM_THREAD_CB_OUTPUT_VBLANK: { - tdm_thread_cb_output_vblank *output_vblank = (tdm_thread_cb_output_vblank*)base; - tdm_output *output_backend = - tdm_display_find_output_stamp(private_loop->dpy, output_vblank->output_stamp); - if (!output_backend) { - TDM_WRN("no output(%f)", output_vblank->output_stamp); - break; - } - tdm_output_cb_vblank(output_backend, output_vblank->sequence, - output_vblank->tv_sec, output_vblank->tv_usec, - output_vblank->user_data); - break; - } - case TDM_THREAD_CB_OUTPUT_STATUS: { - /* LCOV_EXCL_START */ - tdm_thread_cb_output_status *output_status = (tdm_thread_cb_output_status*)base; - tdm_output *output_backend = - tdm_display_find_output_stamp(private_loop->dpy, output_status->output_stamp); - if (!output_backend) { - TDM_WRN("no output(%f)", output_status->output_stamp); - break; - } - tdm_output_cb_status(output_backend, output_status->status, - output_status->user_data); - break; - /* LCOV_EXCL_STOP */ - } - case TDM_THREAD_CB_OUTPUT_DPMS: { - /* LCOV_EXCL_START */ - tdm_thread_cb_output_dpms *output_dpms = (tdm_thread_cb_output_dpms*)base; - tdm_output *output_backend = - tdm_display_find_output_stamp(private_loop->dpy, output_dpms->output_stamp); - if (!output_backend) { - TDM_WRN("no output(%f)", output_dpms->output_stamp); - break; - } - tdm_output_cb_dpms(output_backend, output_dpms->dpms, output_dpms->user_data); - break; - /* LCOV_EXCL_STOP */ - } + case TDM_THREAD_CB_OUTPUT_COMMIT: + case TDM_THREAD_CB_OUTPUT_VBLANK: + case TDM_THREAD_CB_OUTPUT_CHANGE: case TDM_THREAD_CB_PP_DONE: case TDM_THREAD_CB_CAPTURE_DONE: case TDM_THREAD_CB_VBLANK_SW: case TDM_THREAD_CB_VBLANK_CREATE: + case TDM_THREAD_CB_NEED_VALIDATE: tdm_thread_cb_call(NULL, base); break; - case TDM_THREAD_CB_NEED_VALIDATE: { - tdm_thread_cb_need_validate *ev = (tdm_thread_cb_need_validate*)base; - tdm_output_cb_need_validate(ev->o); - break; - } default: break; } -- 2.7.4 From ddaded5fa255c078568e7f92311c335151dc1b99 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 21 Feb 2018 14:36:26 +0900 Subject: [PATCH 06/16] log: no need to use ifdef Change-Id: I2f1b03b99b6925511410d87b0649db1c19580ba5 --- common/tdm_log.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/common/tdm_log.c b/common/tdm_log.c index b77e765..3ddcda1 100644 --- a/common/tdm_log.c +++ b/common/tdm_log.c @@ -184,10 +184,7 @@ tdm_log_print(int level, const char *fmt, ...) pthread_mutex_unlock(&log_lock); } -#ifdef TDM_CONFIG_ASSERT - if (level <= assert_level) - assert(0); -#endif + assert(level > assert_level); } EXTERN void -- 2.7.4 From 1b73cea10c215e7640a0a7a94da2fde7d7120760 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 21 Feb 2018 14:36:52 +0900 Subject: [PATCH 07/16] thread: reset find_funcs table when init, deinit Change-Id: I20f572f7dd6014daf0ee02a656f188c3d89d5900 --- src/tdm_thread.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/tdm_thread.c b/src/tdm_thread.c index cf76c82..30966b4 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -185,7 +185,7 @@ tdm_thread_init(tdm_private_loop *private_loop) { tdm_private_display *private_display; tdm_private_thread *private_thread; - int thread; + int thread, i; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(private_loop->dpy, TDM_ERROR_OPERATION_FAILED); @@ -193,6 +193,9 @@ tdm_thread_init(tdm_private_loop *private_loop) private_display = private_loop->dpy; TDM_RETURN_VAL_IF_FAIL(private_display->private_loop, TDM_ERROR_OPERATION_FAILED); + for (i = 0; i < TDM_THREAD_CB_MAX; i++) + find_funcs[i] = NULL; + LIST_INITHEAD(&cb_list); if (private_loop->private_thread) @@ -267,6 +270,9 @@ tdm_thread_deinit(tdm_private_loop *private_loop) TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + for (i = 0; i < TDM_THREAD_CB_MAX; i++) + find_funcs[i] = NULL; + if (!private_loop->private_thread) return; @@ -305,9 +311,6 @@ tdm_thread_deinit(tdm_private_loop *private_loop) private_loop->private_thread = NULL; keep_private_thread = NULL; - for (i = 0; i < TDM_THREAD_CB_MAX; i++) - find_funcs[i] = NULL; - TDM_INFO("Finish a TDM event thread"); } -- 2.7.4 From 342aaf80ca0d017f1dad08e16d1460d8abfdb674 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 21 Feb 2018 14:37:35 +0900 Subject: [PATCH 08/16] config: remove unuseful codes Change-Id: If5b99cb203fcb7e58fc3e9c40e45f64bd3d84a3a --- src/tdm_config.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/tdm_config.c b/src/tdm_config.c index 4c66e07..703ae0a 100644 --- a/src/tdm_config.c +++ b/src/tdm_config.c @@ -254,8 +254,6 @@ tdm_config_set_int(const char *key, int value) ret = iniparser_set(g_dic, key, (const char*)temp); - _tdm_config_check_logs(); - pthread_mutex_unlock(&g_dic_lock); TDM_RETURN_VAL_IF_FAIL(ret == 0, TDM_ERROR_OPERATION_FAILED); @@ -282,8 +280,6 @@ tdm_config_set_string(const char *key, const char *value) ret = iniparser_set(g_dic, key, value); - _tdm_config_check_logs(); - pthread_mutex_unlock(&g_dic_lock); TDM_RETURN_VAL_IF_FAIL(ret == 0, TDM_ERROR_OPERATION_FAILED); -- 2.7.4 From d53c7f30fde17401402cdac430c936c4aa4c0110 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 21 Feb 2018 14:39:28 +0900 Subject: [PATCH 09/16] should init event_loop before vblank when initing event_loop, thread's find_funcs table is also inited. This should be done before initing others. Change-Id: Iae6c0e44b3f00c0b6a5aa77bbdbee158ce74baa0 --- src/tdm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tdm.c b/src/tdm.c index 7fabc4a..b0d1f40 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -963,10 +963,6 @@ tdm_display_init(tdm_error *error) TDM_DBG("prepare init time: %.3f ms", (stamp2 - stamp1) * 1000.0); stamp1 = stamp2; - ret = tdm_vblank_init(private_display); - if (ret != TDM_ERROR_NONE) - goto failed_vblank; - ret = tdm_event_loop_init(private_display); if (ret != TDM_ERROR_NONE) goto failed_event; @@ -975,6 +971,10 @@ tdm_display_init(tdm_error *error) TDM_INFO("event loop init time: %.3f ms", (stamp2 - stamp1) * 1000.0); stamp1 = stamp2; + ret = tdm_vblank_init(private_display); + if (ret != TDM_ERROR_NONE) + goto failed_vblank; + ret = tdm_output_init(private_display); if (ret != TDM_ERROR_NONE) goto failed_load; -- 2.7.4 From a03f1283751930597b6c9f2fe43bffef288d6ead Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 31 Jan 2018 12:04:51 +0900 Subject: [PATCH 10/16] support multi backend Change-Id: I6e6d24256e1eb84dd6180bac35b33c55b076b3bb --- 0001-save.patch | 31 ++++ include/tdm.h | 55 +++---- include/tdm_backend.h | 4 +- include/tdm_deprecated.h | 95 ++++++++++++ include/tdm_helper.h | 10 -- include/tdm_log.h | 9 ++ include/tdm_types.h | 5 + src/tdm.c | 391 +++++++++++++++++++++++++++-------------------- src/tdm_backend.c | 75 +++++---- src/tdm_capture.c | 61 +++++--- src/tdm_display.c | 160 +++++++++++++------ src/tdm_event_loop.c | 77 +++++----- src/tdm_helper.c | 123 ++++++++------- src/tdm_hwc_window.c | 83 ++++++---- src/tdm_layer.c | 52 ++++--- src/tdm_macro.h | 8 +- src/tdm_monitor_server.c | 2 - src/tdm_output.c | 137 +++++++++++------ src/tdm_pp.c | 47 +++--- src/tdm_private.h | 6 +- src/tdm_private_types.h | 48 ++++-- src/tdm_vblank.c | 2 +- 22 files changed, 950 insertions(+), 531 deletions(-) create mode 100644 0001-save.patch create mode 100644 include/tdm_deprecated.h diff --git a/0001-save.patch b/0001-save.patch new file mode 100644 index 0000000..25ad8f0 --- /dev/null +++ b/0001-save.patch @@ -0,0 +1,31 @@ +From 60fa1ef61f143eb5310588bba987bdfce5d33ad1 Mon Sep 17 00:00:00 2001 +From: Boram Park +Date: Wed, 21 Feb 2018 15:26:17 +0900 +Subject: [PATCH] save + +Change-Id: I5e33d25ad3678f4a77c5ec4396af2b1b45a32488 +--- + include/tdm.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/tdm.h b/include/tdm.h +index f4aa8d8..3cae42f 100644 +--- a/include/tdm.h ++++ b/include/tdm.h +@@ -222,10 +222,10 @@ tdm_backend_get_info(tdm_backend *backend, const char **name, + const char **vendor, int *major, int *minor); + + /** +- * @brief Get the capabilities of a output object. ++ * @brief Get a backend object of the given output. + * @param[in] output A output object +- * @param[out] capabilities The capabilities of a output object +- * @return #TDM_ERROR_NONE if success. Otherwise, error value. ++ * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. ++ * @return A backend object if success. Otherwise, NULL. + */ + tdm_backend * + tdm_output_get_backend(tdm_output *output, tdm_error *error); +-- +1.9.1 + diff --git a/include/tdm.h b/include/tdm.h index 7ee3edc..3cae42f 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -43,6 +43,7 @@ #include #include "tdm_types.h" +#include "tdm_deprecated.h" #ifdef __cplusplus extern "C" { @@ -75,17 +76,6 @@ void tdm_display_deinit(tdm_display *dpy); /** - * @brief Update a display object - * @details - * When new output is connected, a frontend user need to call this function. - * And a frontend user can the new output information with tdm_output_get_xxx functions. - * @param[in] dpy A display object - * @return #TDM_ERROR_NONE if success. Otherwise, error value. - */ -tdm_error -tdm_display_update(tdm_display *dpy); - -/** * @brief Get the file descriptor * @details TDM handles the events of fd with #tdm_display_handle_events. * @param[in] dpy A display object @@ -106,18 +96,6 @@ tdm_error tdm_display_handle_events(tdm_display *dpy); /** - * @brief Get the information of the TDM backend module. - * @param[in] dpy A display object - * @param[out] name The name of the TDM backend module - * @param[out] vendor The vendor of the TDM backend module - * @param[out] version The version of the TDM backend module - * @return #TDM_ERROR_NONE if success. Otherwise, error value. - */ -tdm_error -tdm_display_get_backend_info(tdm_display *dpy, const char **name, - const char **vendor, int *major, int *minor); - -/** * @brief Get the capabilities of a display object. * @details A frontend user can get whether TDM supports pp/capture functionality with this function. * @param[in] dpy A display object @@ -201,16 +179,6 @@ tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h, int *max_w, int *max_h, int *preferred_align); /** - * @brief Get the max layer counts which a display object can show on screen. - * @details -1 means that a TDM backend module doesn't define the value. - * @param[in] dpy A display object - * @param[out] count The max count of layers - * @return #TDM_ERROR_NONE if success. Otherwise, error value. - */ -tdm_error -tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count); - -/** * @brief Get the output counts which a display object has. * @param[in] dpy A display object * @param[out] count The count of outputs @@ -242,6 +210,27 @@ tdm_pp * tdm_display_create_pp(tdm_display *dpy, tdm_error *error); /** + * @brief Get the information of the TDM backend module. + * @param[in] backend A backend object + * @param[out] name The name of the TDM backend module + * @param[out] vendor The vendor of the TDM backend module + * @param[out] version The version of the TDM backend module + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error +tdm_backend_get_info(tdm_backend *backend, const char **name, + const char **vendor, int *major, int *minor); + +/** + * @brief Get a backend object of the given output. + * @param[in] output A output object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A backend object if success. Otherwise, NULL. + */ +tdm_backend * +tdm_output_get_backend(tdm_output *output, tdm_error *error); + +/** * @brief Get the capabilities of a output object. * @param[in] output A output object * @param[out] capabilities The capabilities of a output object diff --git a/include/tdm_backend.h b/include/tdm_backend.h index de6fb24..4e8aee3 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -103,8 +103,7 @@ typedef struct _tdm_caps_output { unsigned int type_id; /**< The connection type id */ unsigned int mode_count; /**< The count of available modes */ - tdm_output_mode - *modes; /**< The @b newly-allocated array of modes. will be freed in frontend. */ + tdm_output_mode *modes; /**< The @b newly-allocated array of modes. will be freed in frontend. */ unsigned int prop_count; /**< The count of available properties */ tdm_prop *props; /**< The @b newly-allocated array of properties. will be freed in frontend. */ @@ -477,7 +476,6 @@ typedef struct _tdm_func_output { /** * @brief Get the mode of a output object - * @deprecated * @param[in] output A output object * @param[out] mode A output mode * @return #TDM_ERROR_NONE if success. Otherwise, error value. diff --git a/include/tdm_deprecated.h b/include/tdm_deprecated.h new file mode 100644 index 0000000..06a3d24 --- /dev/null +++ b/include/tdm_deprecated.h @@ -0,0 +1,95 @@ +/************************************************************************** + * + * libtdm + * + * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Eunchul Kim , + * JinYoung Jeon , + * Taeheon Kim , + * YoungJun Cho , + * SooChan Lim , + * Boram Park + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * +**************************************************************************/ + +#ifndef _TDM_DEPRECATED_H_ +#define _TDM_DEPRECATED_H_ + +#include "tdm_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @deprecated + * @brief Update a display object + * @details + * When new output is connected, a frontend user need to call this function. + * And a frontend user can the new output information with tdm_output_get_xxx functions. + * @param[in] dpy A display object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error +tdm_display_update(tdm_display *dpy); + +/** + * @deprecated + * @brief Get the information of the TDM backend module. + * @param[in] dpy A display object + * @param[out] name The name of the TDM backend module + * @param[out] vendor The vendor of the TDM backend module + * @param[out] version The version of the TDM backend module + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see #tdm_output_get_backend, #tdm_backend_get_info + */ +tdm_error +tdm_display_get_backend_info(tdm_display *dpy, const char **name, + const char **vendor, int *major, int *minor); + +/** + * @deprecated + * @brief Get the max layer counts which a display object can show on screen. + * @details -1 means that a TDM backend module doesn't define the value. + * @param[in] dpy A display object + * @param[out] count The max count of layers + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error +tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count); + +/** + * @deprecated use @c tdm_helper_output_commit_per_vblank_enabled instead + * @brief Get whether the commit-per-vblank functionality is enabled or not. + * @param[in] dpy A display object + * @return 1 if enabled. Otherwise, 0. + */ +int +tdm_helper_commit_per_vblank_enabled(tdm_display *dpy); + +#ifdef __cplusplus +} +#endif + +#endif /* _TDM_DEPRECATED_H_ */ diff --git a/include/tdm_helper.h b/include/tdm_helper.h index d5d8d6e..fa82602 100644 --- a/include/tdm_helper.h +++ b/include/tdm_helper.h @@ -229,16 +229,6 @@ void tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len); /** - * @brief Get whether the commit-per-vblank functionality is enabled or not. - * @param[in] dpy A display object - * @return 1 if enabled. Otherwise, 0. - * - * @deprecated use @c tdm_helper_output_commit_per_vblank_enabled instead - */ -int -tdm_helper_commit_per_vblank_enabled(tdm_display *dpy); - -/** * @brief Get whether the commit-per-vblank functionality is enabled or not for the output. * @param[in] output An output the functionality has to be checked for * @return -1 if error occurred, 1 if enabled, 0 if disabled. diff --git a/include/tdm_log.h b/include/tdm_log.h index 02e8b0c..880ffe8 100644 --- a/include/tdm_log.h +++ b/include/tdm_log.h @@ -116,6 +116,15 @@ extern unsigned int tdm_log_debug_level; } \ } while (0) +#define TDM_NEVER_GET_HERE() TDM_WRN("** NEVER GET HERE **") +#define TDM_DEPRECATED(str) \ + do { \ + if (str) \ + TDM_WRN("** DEPRECATED: %s **", str); \ + else \ + TDM_WRN("** DEPRECATED **"); \ + } while(0) + #ifdef __cplusplus } #endif diff --git a/include/tdm_types.h b/include/tdm_types.h index 055005f..d5e6b18 100644 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -221,6 +221,11 @@ typedef enum { typedef void tdm_display; /** + * @brief The tdm backend object + */ +typedef void tdm_backend; + +/** * @brief The tdm output object */ typedef void tdm_output; diff --git a/src/tdm.c b/src/tdm.c index b0d1f40..d744875 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -64,11 +64,14 @@ _tdm_display_find_private_layer(tdm_private_output *private_output, INTERN tdm_private_output * tdm_display_find_private_output(tdm_private_display *private_display, tdm_output *output_backend) { + tdm_private_backend *private_backend = NULL; tdm_private_output *private_output = NULL; - LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) { - if (private_output->output_backend == output_backend) - return private_output; + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(private_output, &private_backend->output_list, link) { + if (private_output->output_backend == output_backend) + return private_output; + } } return NULL; @@ -77,11 +80,14 @@ tdm_display_find_private_output(tdm_private_display *private_display, tdm_output INTERN void * tdm_display_find_output_stamp(tdm_private_display *private_display, double stamp) { + tdm_private_backend *private_backend = NULL; tdm_private_output *private_output = NULL; - LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) { - if (private_output->stamp == stamp) - return private_output; + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(private_output, &private_backend->output_list, link) { + if (private_output->stamp == stamp) + return private_output; + } } return NULL; @@ -234,46 +240,48 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output) static void _tdm_display_destroy_private_display(tdm_private_display *private_display) { + tdm_private_backend *private_backend = NULL, *bb = NULL; tdm_private_output *o = NULL, *oo = NULL; tdm_private_pp *p = NULL, *pp = NULL; - free(private_display->outputs_ptr); - if (private_display->outputs) { - free(private_display->outputs); - private_display->outputs = NULL; - } + LIST_FOR_EACH_ENTRY_SAFE(private_backend, bb, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY_SAFE(p, pp, &private_backend->pp_list, link) { + tdm_pp_destroy_internal(p); + } - LIST_FOR_EACH_ENTRY_SAFE(p, pp, &private_display->pp_list, link) - tdm_pp_destroy_internal(p); + LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_backend->output_list, link) { + _tdm_display_destroy_private_output(o); + } - LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_display->output_list, link) - _tdm_display_destroy_private_output(o); + _tdm_display_destroy_caps_pp(&private_backend->caps_pp); + _tdm_display_destroy_caps_capture(&private_backend->caps_capture); - _tdm_display_destroy_caps_pp(&private_display->caps_pp); - _tdm_display_destroy_caps_capture(&private_display->caps_capture); + private_backend->capabilities = 0; + private_backend->caps_display.max_layer_count = 0; - private_display->capabilities = 0; - private_display->caps_display.max_layer_count = 0; + if (private_backend->outputs) { + free(private_backend->outputs); + private_backend->outputs = NULL; + } + } } static tdm_error -_tdm_display_update_caps_pp(tdm_private_display *private_display, - tdm_caps_pp *caps) +_tdm_display_update_caps_pp(tdm_private_backend *private_backend, tdm_caps_pp *caps) { - tdm_func_display *func_display = &private_display->func_display; + tdm_func_display *func_display; tdm_error ret; - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) - return TDM_ERROR_NONE; + func_display = &private_backend->func_display; if (!func_display->display_get_pp_capability) { - TDM_ERR("no display_get_pp_capability()"); + TDM_ERR("backend(%s) no display_get_pp_capability()", private_backend->module_data->name); return TDM_ERROR_BAD_MODULE; } - ret = func_display->display_get_pp_capability(private_display->bdata, caps); + ret = func_display->display_get_pp_capability(private_backend->bdata, caps); if (ret != TDM_ERROR_NONE) { - TDM_ERR("display_get_pp_capability() failed"); + TDM_ERR("backend(%s) display_get_pp_capability() failed", private_backend->module_data->name); return TDM_ERROR_BAD_MODULE; } @@ -281,23 +289,21 @@ _tdm_display_update_caps_pp(tdm_private_display *private_display, } static tdm_error -_tdm_display_update_caps_capture(tdm_private_display *private_display, - tdm_caps_capture *caps) +_tdm_display_update_caps_capture(tdm_private_backend *private_backend, tdm_caps_capture *caps) { - tdm_func_display *func_display = &private_display->func_display; + tdm_func_display *func_display; tdm_error ret; - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) - return TDM_ERROR_NONE; + func_display = &private_backend->func_display; if (!func_display->display_get_capture_capability) { - TDM_ERR("no display_get_capture_capability()"); + TDM_ERR("backend(%s) no display_get_capture_capability()", private_backend->module_data->name); return TDM_ERROR_BAD_MODULE; } - ret = func_display->display_get_capture_capability(private_display->bdata, caps); + ret = func_display->display_get_capture_capability(private_backend->bdata, caps); if (ret != TDM_ERROR_NONE) { - TDM_ERR("display_get_capture_capability() failed"); + TDM_ERR("backend(%s) display_get_capture_capability() failed", private_backend->module_data->name); return TDM_ERROR_BAD_MODULE; } @@ -305,20 +311,20 @@ _tdm_display_update_caps_capture(tdm_private_display *private_display, } static tdm_error -_tdm_display_update_caps_layer(tdm_private_display *private_display, +_tdm_display_update_caps_layer(tdm_private_backend *private_backend, tdm_layer *layer_backend, tdm_caps_layer *caps) { - tdm_func_layer *func_layer = &private_display->func_layer; + tdm_func_layer *func_layer = &private_backend->func_layer; tdm_error ret; if (!func_layer->layer_get_capability) { - TDM_ERR("no layer_get_capability()"); + TDM_ERR("backend(%s) no layer_get_capability()", private_backend->module_data->name); return TDM_ERROR_BAD_MODULE; } ret = func_layer->layer_get_capability(layer_backend, caps); if (ret != TDM_ERROR_NONE) { - TDM_ERR("layer_get_capability() failed"); + TDM_ERR("backend(%s) layer_get_capability() failed", private_backend->module_data->name); return TDM_ERROR_BAD_MODULE; } @@ -326,25 +332,26 @@ _tdm_display_update_caps_layer(tdm_private_display *private_display, } static tdm_error -_tdm_display_update_caps_output(tdm_private_display *private_display, int pipe, +_tdm_display_update_caps_output(tdm_private_backend *private_backend, int pipe, tdm_output *output_backend, tdm_caps_output *caps) { - tdm_func_output *func_output = &private_display->func_output; + tdm_func_output *func_output = &private_backend->func_output; char temp[TDM_NAME_LEN]; tdm_error ret; double stamp; if (!func_output->output_get_capability) { - TDM_ERR("no output_get_capability()"); + TDM_ERR("backend(%s) no output_get_capability()", private_backend->module_data->name); return TDM_ERROR_BAD_MODULE; } stamp = tdm_helper_get_time(); ret = func_output->output_get_capability(output_backend, caps); - TDM_DBG("backend output_get_capability() time: %.3f ms", (tdm_helper_get_time() - stamp) * 1000.0); + TDM_DBG("backend(%s) backend output_get_capability() time: %.3f ms", + private_backend->module_data->name, (tdm_helper_get_time() - stamp) * 1000.0); if (ret != TDM_ERROR_NONE) { - TDM_ERR("output_get_capability() failed"); + TDM_ERR("backend(%s) output_get_capability() failed", private_backend->module_data->name); return TDM_ERROR_BAD_MODULE; } @@ -356,8 +363,7 @@ _tdm_display_update_caps_output(tdm_private_display *private_display, int pipe, } static tdm_error -_tdm_display_update_layer(tdm_private_display *private_display, - tdm_private_output *private_output, +_tdm_display_update_layer(tdm_private_output *private_output, tdm_layer *layer_backend, int index) { tdm_private_layer *private_layer; @@ -370,7 +376,8 @@ _tdm_display_update_layer(tdm_private_display *private_display, LIST_ADDTAIL(&private_layer->link, &private_output->layer_list); private_layer->index = index; - private_layer->private_display = private_display; + private_layer->private_backend = private_output->private_backend; + private_layer->private_display = private_output->private_display; private_layer->private_output = private_output; private_layer->layer_backend = layer_backend; @@ -380,7 +387,7 @@ _tdm_display_update_layer(tdm_private_display *private_display, } else _tdm_display_destroy_caps_layer(&private_layer->caps); - ret = _tdm_display_update_caps_layer(private_display, layer_backend, + ret = _tdm_display_update_caps_layer(private_layer->private_backend, layer_backend, &private_layer->caps); if (ret != TDM_ERROR_NONE) goto failed_update; @@ -392,27 +399,28 @@ failed_update: } INTERN tdm_error -tdm_display_update_output(tdm_private_display *private_display, +tdm_display_update_output(tdm_private_backend *private_backend, tdm_output *output_backend, int pipe) { - tdm_func_output *func_output = &private_display->func_output; + tdm_func_output *func_output = &private_backend->func_output; tdm_private_output *private_output = NULL; tdm_layer **layers = NULL; int layer_count = 0, i; tdm_error ret; - private_output = tdm_display_find_private_output(private_display, output_backend); + private_output = tdm_display_find_private_output(private_backend->private_display, output_backend); if (!private_output) { private_output = calloc(1, sizeof(tdm_private_output)); TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY); private_output->stamp = tdm_helper_get_time(); - while (tdm_display_find_output_stamp(private_display, private_output->stamp)) + while (tdm_display_find_output_stamp(private_backend->private_display, private_output->stamp)) private_output->stamp++; - LIST_ADDTAIL(&private_output->link, &private_display->output_list); + LIST_ADDTAIL(&private_output->link, &private_backend->output_list); - private_output->private_display = private_display; + private_output->private_backend = private_backend; + private_output->private_display = private_backend->private_display; private_output->current_dpms_value = TDM_OUTPUT_DPMS_OFF; private_output->output_backend = output_backend; private_output->pipe = pipe; @@ -434,14 +442,14 @@ tdm_display_update_output(tdm_private_display *private_display, private_output->regist_change_cb = 1; } - ret = _tdm_display_update_caps_output(private_display, pipe, output_backend, + ret = _tdm_display_update_caps_output(private_backend, pipe, output_backend, &private_output->caps); if (ret != TDM_ERROR_NONE) return ret; } else { tdm_caps_output new_caps; - ret = _tdm_display_update_caps_output(private_display, pipe, output_backend, + ret = _tdm_display_update_caps_output(private_backend, pipe, output_backend, &new_caps); if (ret != TDM_ERROR_NONE) return ret; @@ -469,7 +477,7 @@ tdm_display_update_output(tdm_private_display *private_display, goto failed_update; for (i = 0; i < layer_count; i++) { - ret = _tdm_display_update_layer(private_display, private_output, layers[i], i); + ret = _tdm_display_update_layer(private_output, layers[i], i); if (ret != TDM_ERROR_NONE) goto failed_update; } @@ -499,9 +507,9 @@ _tdm_display_set_main_first(tdm_output **outputs, int index) } static tdm_output ** -_tdm_display_get_ordered_outputs(tdm_private_display *private_display, int *count) +_tdm_display_get_ordered_outputs(tdm_private_backend *private_backend, int *count) { - tdm_func_display *func_display = &private_display->func_display; + tdm_func_display *func_display = &private_backend->func_display; tdm_output **outputs = NULL; tdm_output **new_outputs = NULL; tdm_output *output_dsi = NULL; @@ -513,10 +521,12 @@ _tdm_display_get_ordered_outputs(tdm_private_display *private_display, int *coun tdm_error ret; /* don't change list order if not init time */ - if (private_display->outputs) - return private_display->outputs; + if (private_backend->outputs) { + TDM_ERR("can't change output order"); + return private_backend->outputs; + } - outputs = func_display->display_get_outputs(private_display->bdata, &output_count, &ret); + outputs = func_display->display_get_outputs(private_backend->bdata, &output_count, &ret); if (ret != TDM_ERROR_NONE) goto failed_get_outputs; @@ -525,13 +535,13 @@ _tdm_display_get_ordered_outputs(tdm_private_display *private_display, int *coun if (output_count == 0) goto failed_get_outputs; else if (output_count == 1) { - private_display->outputs = outputs; + private_backend->outputs = outputs; return outputs; } /* count connected outputs */ for (i = 0; i < output_count; i++) { - tdm_func_output *func_output = &private_display->func_output; + tdm_func_output *func_output = &private_backend->func_output; tdm_caps_output caps; memset(&caps, 0, sizeof(tdm_caps_output)); @@ -607,7 +617,7 @@ _tdm_display_get_ordered_outputs(tdm_private_display *private_display, int *coun new_outputs = outputs; } - private_display->outputs = new_outputs; + private_backend->outputs = new_outputs; return new_outputs; @@ -618,36 +628,39 @@ failed_get_outputs: } static tdm_error -_tdm_display_update_internal(tdm_private_display *private_display, - int only_display) +_tdm_display_update(tdm_private_display *private_display) { - tdm_output **outputs = NULL; - int output_count = 0, i; + tdm_private_backend *private_backend = NULL; tdm_error ret = TDM_ERROR_NONE; + int index = 0; - LIST_INITHEAD(&private_display->output_list); - LIST_INITHEAD(&private_display->pp_list); - LIST_INITHEAD(&private_display->capture_list); - - if (!only_display) { - ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp); + if (private_display->pp_backend) { + ret = _tdm_display_update_caps_pp(private_display->pp_backend, + &private_display->pp_backend->caps_pp); if (ret != TDM_ERROR_NONE) goto failed_update; + } - ret = _tdm_display_update_caps_capture(private_display, - &private_display->caps_capture); + if (private_display->capture_backend) { + ret = _tdm_display_update_caps_capture(private_display->capture_backend, + &private_display->capture_backend->caps_capture); if (ret != TDM_ERROR_NONE) goto failed_update; } - outputs = _tdm_display_get_ordered_outputs(private_display, &output_count); - if (!outputs) - goto failed_update; + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + tdm_output **outputs; + int output_count = 0, i; - for (i = 0; i < output_count; i++) { - ret = tdm_display_update_output(private_display, outputs[i], i); - if (ret != TDM_ERROR_NONE) + outputs = _tdm_display_get_ordered_outputs(private_backend, &output_count); + if (!outputs) goto failed_update; + + for (i = 0; i < output_count; i++) { + ret = tdm_display_update_output(private_backend, outputs[i], index++); + if (ret != TDM_ERROR_NONE) + goto failed_update; + } } return TDM_ERROR_NONE; @@ -661,20 +674,12 @@ failed_update: EXTERN tdm_error tdm_display_update(tdm_display *dpy) { - tdm_private_display *private_display; - tdm_error ret; - TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(tdm_display_is_valid(dpy), TDM_ERROR_INVALID_PARAMETER); - private_display = dpy; - _pthread_mutex_lock(&private_display->lock); - - ret = _tdm_display_update_internal(private_display, 1); + TDM_DEPRECATED(NULL); - _pthread_mutex_unlock(&private_display->lock); - - return ret; + return TDM_ERROR_NONE; } #define SUFFIX_MODULE ".so" @@ -741,11 +746,11 @@ _tdm_display_check_module(tdm_backend_module *module) } static tdm_error -_tdm_display_check_backend_functions(tdm_private_display *private_display) +_tdm_display_check_backend_functions(tdm_private_backend *private_backend) { - tdm_func_display *func_display = &private_display->func_display; - tdm_func_output *func_output = &private_display->func_output; - tdm_func_layer *func_layer = &private_display->func_layer; + tdm_func_display *func_display = &private_backend->func_display; + tdm_func_output *func_output = &private_backend->func_output; + tdm_func_layer *func_layer = &private_backend->func_layer; tdm_error ret; /* below functions should be implemented in backend side */ @@ -756,14 +761,14 @@ _tdm_display_check_backend_functions(tdm_private_display *private_display) TDM_RETURN_VAL_IF_FAIL(func_output->output_get_layers, TDM_ERROR_BAD_MODULE); TDM_RETURN_VAL_IF_FAIL(func_layer->layer_get_capability, TDM_ERROR_BAD_MODULE); - ret = func_display->display_get_capability(private_display->bdata, &private_display->caps_display); + ret = func_display->display_get_capability(private_backend->bdata, &private_backend->caps_display); if (ret != TDM_ERROR_NONE) { TDM_ERR("display_get_capability() failed"); return TDM_ERROR_BAD_MODULE; } - if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP) { - tdm_func_pp *func_pp = &private_display->func_pp; + if (private_backend->capabilities & TDM_DISPLAY_CAPABILITY_PP) { + tdm_func_pp *func_pp = &private_backend->func_pp; TDM_RETURN_VAL_IF_FAIL(func_display->display_get_pp_capability, TDM_ERROR_BAD_MODULE); TDM_RETURN_VAL_IF_FAIL(func_display->display_create_pp, TDM_ERROR_BAD_MODULE); TDM_RETURN_VAL_IF_FAIL(func_pp->pp_destroy, TDM_ERROR_BAD_MODULE); @@ -771,12 +776,12 @@ _tdm_display_check_backend_functions(tdm_private_display *private_display) TDM_RETURN_VAL_IF_FAIL(func_pp->pp_set_done_handler, TDM_ERROR_BAD_MODULE); } - if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) { - tdm_func_capture *func_capture = &private_display->func_capture; + if (private_backend->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) { + tdm_func_capture *func_capture = &private_backend->func_capture; TDM_RETURN_VAL_IF_FAIL(func_display->display_get_capture_capability, TDM_ERROR_BAD_MODULE); - if (private_display->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_OUTPUT) + if (private_backend->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_OUTPUT) TDM_RETURN_VAL_IF_FAIL(func_output->output_create_capture, TDM_ERROR_BAD_MODULE); - if (private_display->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_LAYER) + if (private_backend->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_LAYER) TDM_RETURN_VAL_IF_FAIL(func_layer->layer_create_capture, TDM_ERROR_BAD_MODULE); TDM_RETURN_VAL_IF_FAIL(func_capture->capture_destroy, TDM_ERROR_BAD_MODULE); TDM_RETURN_VAL_IF_FAIL(func_capture->capture_commit, TDM_ERROR_BAD_MODULE); @@ -791,8 +796,10 @@ _tdm_display_load_module_with_file(tdm_private_display *private_display, const char *file) { char path[TDM_PATH_LEN] = {0,}; + void *module = NULL; tdm_backend_module *module_data; - void *module; + tdm_backend_data *bdata = NULL; + tdm_private_backend *private_backend = NULL; tdm_error ret; double stamp; int size; @@ -803,6 +810,15 @@ _tdm_display_load_module_with_file(tdm_private_display *private_display, return TDM_ERROR_BAD_MODULE; }; + private_backend = calloc(1, sizeof *private_backend); + if (!private_backend) { + TDM_ERR("alloc failed: %m"); + ret = TDM_ERROR_OUT_OF_MEMORY; + goto failed_load; + } + + private_backend->private_display = private_display; + stamp = tdm_helper_get_time(); TDM_TRACE_BEGIN("TDM_Load_Backend"); @@ -810,9 +826,12 @@ _tdm_display_load_module_with_file(tdm_private_display *private_display, if (!module) { TDM_ERR("failed to load module: %s(%s)", dlerror(), file); TDM_TRACE_END(); - return TDM_ERROR_BAD_MODULE; + ret = TDM_ERROR_BAD_MODULE; + goto failed_load; } + private_backend->module = module; + module_data = dlsym(module, "tdm_backend_module_data"); if (!module_data) { TDM_ERR("'%s' doesn't have data object", file); @@ -822,47 +841,61 @@ _tdm_display_load_module_with_file(tdm_private_display *private_display, } TDM_TRACE_END(); - TDM_DBG("dlopen, dlsym time: %.3f ms", (tdm_helper_get_time() - stamp) * 1000.0); + private_backend->module_data = module_data; - private_display->module_data = module_data; - private_display->module = module; + TDM_DBG("dlopen, dlsym time: %.3f ms", (tdm_helper_get_time() - stamp) * 1000.0); /* check if version, init() and deinit() are valid or not */ ret = _tdm_display_check_module(module_data); - if (ret != TDM_ERROR_NONE) + if (ret != TDM_ERROR_NONE) { + TDM_ERR("backend(%s) load failed: check module error", module_data->name); goto failed_load; + } + + private_display->current_backend = private_backend; /* We don't care if backend_data is NULL or not. It's up to backend. */ TDM_TRACE_BEGIN("TDM_Init_Backend"); stamp = tdm_helper_get_time(); - private_display->bdata = module_data->init((tdm_display *)private_display, &ret); + bdata = module_data->init((tdm_display *)private_display, &ret); TDM_DBG("backend init() time: %.3f ms", (tdm_helper_get_time() - stamp) * 1000.0); TDM_TRACE_END(); + private_display->current_backend = NULL; + + private_backend->bdata = bdata; + if (ret != TDM_ERROR_NONE) { - TDM_ERR("failed to init '%s' module", module_data->name); + TDM_ERR("backend(%s) load failed: init error", module_data->name); goto failed_load; } - ret = _tdm_display_check_backend_functions(private_display); + ret = _tdm_display_check_backend_functions(private_backend); if (ret != TDM_ERROR_NONE) { - module_data->deinit(private_display->bdata); - private_display->bdata = NULL; + TDM_ERR("backend(%s) load failed: check functions error", module_data->name); goto failed_load; } + LIST_INITHEAD(&private_backend->output_list); + LIST_INITHEAD(&private_backend->pp_list); + LIST_INITHEAD(&private_backend->capture_list); + + LIST_ADDTAIL(&private_backend->link, &private_display->backend_list); + TDM_INFO("Success to load '%s' module", module_data->name); return TDM_ERROR_NONE; failed_load: + if (bdata) + module_data->deinit(bdata); dlclose(module); - private_display->module_data = NULL; - private_display->module = NULL; + if (private_backend) + free(private_backend); return ret; } static tdm_error -_tdm_display_load_module(tdm_private_display *private_display) +_tdm_display_load_modules(tdm_private_display *private_display) { const char *module_names; tdm_error ret = 0; @@ -870,38 +903,51 @@ _tdm_display_load_module(tdm_private_display *private_display) char *arg; char *end; + LIST_INITHEAD(&private_display->backend_list); + module_names = tdm_config_get_string(TDM_CONFIG_KEY_GENERAL_BACKENDS, TDM_DEFAULT_MODULE); snprintf(temp, TDM_PATH_LEN, "%s", module_names); arg = strtok_r(temp, TDM_CONFIG_DELIM, &end); while (arg) { + TDM_INFO("loading a %s backend", arg); ret = _tdm_display_load_module_with_file(private_display, arg); if (ret == TDM_ERROR_NONE) - return TDM_ERROR_NONE; - + TDM_INFO("%s backend loading success", arg); + else + TDM_INFO("%s backend loading failed", arg); arg = strtok_r(NULL, TDM_CONFIG_DELIM, &end); } /* load bufmgr priv from dummy lib */ - ret = _tdm_display_load_module_with_file(private_display, TDM_DUMMY_MODULE); - if (ret == TDM_ERROR_NONE) - return TDM_ERROR_NONE; + if (LIST_IS_EMPTY(&private_display->backend_list)) { + TDM_WRN("No backend. loading a %s backend", TDM_DUMMY_MODULE); + ret = _tdm_display_load_module_with_file(private_display, TDM_DUMMY_MODULE); + if (ret == TDM_ERROR_NONE) + TDM_INFO("%s backend loading success", TDM_DUMMY_MODULE); + else + TDM_INFO("%s backend loading failed", TDM_DUMMY_MODULE); + } return ret; } static void -_tdm_display_unload_module(tdm_private_display *private_display) +_tdm_display_unload_modules(tdm_private_display *private_display) { - if (private_display->module_data) - private_display->module_data->deinit(private_display->bdata); - if (private_display->module) - dlclose(private_display->module); - - private_display->bdata = NULL; - private_display->module_data = NULL; - private_display->module = NULL; + tdm_private_backend *private_backend = NULL, *bb = NULL; + + LIST_FOR_EACH_ENTRY_SAFE(private_backend, bb, &private_display->backend_list, link) { + LIST_DEL(&private_backend->link); + + if (private_backend->module_data) + private_backend->module_data->deinit(private_backend->bdata); + if (private_backend->module) + dlclose(private_backend->module); + + free(private_backend); + } } /* LCOV_EXCL_STOP */ @@ -987,7 +1033,7 @@ tdm_display_init(tdm_error *error) if (ret != TDM_ERROR_NONE) goto failed_load; - ret = _tdm_display_load_module(private_display); + ret = _tdm_display_load_modules(private_display); if (ret != TDM_ERROR_NONE) goto failed_load; @@ -1014,7 +1060,7 @@ tdm_display_init(tdm_error *error) #endif TDM_TRACE_BEGIN("TDM_Update_Display"); - ret = _tdm_display_update_internal(private_display, 0); + ret = _tdm_display_update(private_display); TDM_TRACE_END(); if (ret != TDM_ERROR_NONE) goto failed_update; @@ -1028,10 +1074,13 @@ tdm_display_init(tdm_error *error) private_display->init_count = 1; g_private_display = private_display; + tdm_private_backend *b = NULL; tdm_private_output *o = NULL; - LIST_FOR_EACH_ENTRY(o, &private_display->output_list, link) { - if (o->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC) - tdm_output_need_validate_event_init(o); + LIST_FOR_EACH_ENTRY(b, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(o, &b->output_list, link) { + if (o->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC) + tdm_output_need_validate_event_init(o); + } } /* the COMMIT_PER_VBLANK functionality is ability of an output to support @@ -1039,13 +1088,17 @@ tdm_display_init(tdm_error *error) * this functionality can be turned off which means a default mode */ mode = tdm_config_get_int(TDM_CONFIG_KEY_GENERAL_COMMIT_PER_VBLANK, 0); if (mode > 0) { + tdm_private_backend *b = NULL; tdm_private_output *o = NULL; /* outputs which support hwc capability can work only * if commit_per_vblank mode is '0' (default mode) */ - LIST_FOR_EACH_ENTRY(o, &private_display->output_list, link) - if (!(o->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC)) - tdm_output_choose_commit_per_vblank_mode(o, mode); + LIST_FOR_EACH_ENTRY(b, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(o, &b->output_list, link) { + if (!(o->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC)) + tdm_output_choose_commit_per_vblank_mode(o, mode); + } + } } if (error) @@ -1060,7 +1113,7 @@ tdm_display_init(tdm_error *error) /* LCOV_EXCL_START */ failed_update: - _tdm_display_unload_module(private_display); + _tdm_display_unload_modules(private_display); failed_load: tdm_event_loop_stop(private_display); tdm_event_loop_deinit(private_display); @@ -1111,7 +1164,7 @@ tdm_display_deinit(tdm_display *dpy) * we can unload backend modulues. */ _tdm_display_destroy_private_display(private_display); - _tdm_display_unload_module(private_display); + _tdm_display_unload_modules(private_display); tdm_vblank_deinit(private_display); @@ -1155,19 +1208,26 @@ tdm_display_is_valid(tdm_display *dpy) INTERN int tdm_output_is_valid(tdm_output *output) { - tdm_private_output *o = NULL, *private_output = output; - if (output && g_private_display) - LIST_FOR_EACH_ENTRY(o, &g_private_display->output_list, link) - if (o == private_output) + tdm_private_backend *b = NULL; + tdm_private_output *o = NULL; + + if (!output || !g_private_display) + return 0; + + LIST_FOR_EACH_ENTRY(b, &g_private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(o, &b->output_list, link) + if (o == output) return 1; + } + return 0; } /* LCOV_EXCL_START */ INTERN int -tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, int abimin) +tdm_backend_check_module_abi(tdm_private_backend *private_backend, int abimaj, int abimin) { - tdm_backend_module *module = private_display->module_data; + tdm_backend_module *module = private_backend->module_data; if (TDM_BACKEND_GET_ABI_MAJOR(module->abi_version) < abimaj) return 0; @@ -1255,22 +1315,26 @@ tdm_display_enable_dump(tdm_private_display *private_display, const char *dump_s TDM_GOTO_IF_FAIL(path != NULL, done); if (!strncmp(arg, "current", 7)) { + tdm_private_backend *b = NULL; tdm_private_output *o = NULL; + if (!private_display) { TDM_WRN("no private_display"); goto done; } - LIST_FOR_EACH_ENTRY(o, &private_display->output_list, link) { - tdm_private_layer *l = NULL; - LIST_FOR_EACH_ENTRY(l, &o->layer_list, link) { - char str[TDM_PATH_LEN]; - if (l->usable || l->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO) - continue; - if (!l->showing_buffer) - continue; - snprintf(str, TDM_PATH_LEN, "layer_%d_%d", o->index, l->index); - tdm_helper_dump_buffer_str(l->showing_buffer->buffer, path, str); + LIST_FOR_EACH_ENTRY(b, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(o, &b->output_list, link) { + tdm_private_layer *l = NULL; + LIST_FOR_EACH_ENTRY(l, &o->layer_list, link) { + char str[TDM_PATH_LEN]; + if (l->usable || l->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO) + continue; + if (!l->showing_buffer) + continue; + snprintf(str, TDM_PATH_LEN, "layer_%d_%d", o->index, l->index); + tdm_helper_dump_buffer_str(l->showing_buffer->buffer, path, str); + } } } @@ -1328,16 +1392,19 @@ INTERN tdm_error tdm_display_enable_ttrace_vblank(tdm_display *dpy, tdm_output *output, int enable) { tdm_private_display *private_display = dpy; + tdm_private_backend *private_backend = NULL; tdm_private_output *private_output = NULL; const tdm_output_mode *mode = NULL; tdm_vblank *vblank = NULL; tdm_error ret = TDM_ERROR_NONE; if (!enable) { - LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) { - if (private_output->ttrace_vblank) - tdm_vblank_destroy(private_output->ttrace_vblank); - private_output->ttrace_vblank = NULL; + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(private_output, &private_backend->output_list, link) { + if (private_output->ttrace_vblank) + tdm_vblank_destroy(private_output->ttrace_vblank); + private_output->ttrace_vblank = NULL; + } } return TDM_ERROR_NONE; } diff --git a/src/tdm_backend.c b/src/tdm_backend.c index e6463bc..ed57b34 100644 --- a/src/tdm_backend.c +++ b/src/tdm_backend.c @@ -73,12 +73,14 @@ tdm_backend_register_func_display(tdm_display *dpy, TDM_RETURN_VAL_IF_FAIL(func_display != NULL, TDM_ERROR_INVALID_PARAMETER); + assert(private_display->current_backend); + /* the ABI version of backend module should be more than 1.1 */ - module = private_display->module_data; + module = private_display->current_backend->module_data; if (_check_abi_version(module, 1, 1) < 0) return TDM_ERROR_BAD_MODULE; - private_display->func_display = *func_display; + private_display->current_backend->func_display = *func_display; return TDM_ERROR_NONE; } @@ -94,12 +96,14 @@ tdm_backend_register_func_output(tdm_display *dpy, tdm_func_output *func_output) TDM_RETURN_VAL_IF_FAIL(func_output != NULL, TDM_ERROR_INVALID_PARAMETER); + assert(private_display->current_backend); + /* the ABI version of backend module should be more than 1.1 */ - module = private_display->module_data; + module = private_display->current_backend->module_data; if (_check_abi_version(module, 1, 1) < 0) return TDM_ERROR_BAD_MODULE; - private_display->func_output = *func_output; + private_display->current_backend->func_output = *func_output; return TDM_ERROR_NONE; } @@ -115,12 +119,14 @@ tdm_backend_register_func_layer(tdm_display *dpy, tdm_func_layer *func_layer) TDM_RETURN_VAL_IF_FAIL(func_layer != NULL, TDM_ERROR_INVALID_PARAMETER); + assert(private_display->current_backend); + /* the ABI version of backend module should be more than 1.1 */ - module = private_display->module_data; + module = private_display->current_backend->module_data; if (_check_abi_version(module, 1, 1) < 0) return TDM_ERROR_BAD_MODULE; - private_display->func_layer = *func_layer; + private_display->current_backend->func_layer = *func_layer; return TDM_ERROR_NONE; } @@ -136,14 +142,16 @@ tdm_backend_register_func_hwc_window(tdm_display *dpy, tdm_func_hwc_window *func TDM_RETURN_VAL_IF_FAIL(func_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER); - module = private_display->module_data; + assert(private_display->current_backend); + + module = private_display->current_backend->module_data; /* FIX ME: Temporarily, we set the version of hwc window to 1.1 for the development. Originally the hwc window version is 2.0. */ if (_check_abi_version(module, 1, 1) < 0) return TDM_ERROR_BAD_MODULE; - private_display->func_hwc_window = *func_hwc_window; + private_display->current_backend->func_hwc_window = *func_hwc_window; return TDM_ERROR_NONE; } @@ -158,8 +166,15 @@ tdm_backend_register_func_pp(tdm_display *dpy, tdm_func_pp *func_pp) if (!func_pp) return TDM_ERROR_NONE; - private_display->capabilities |= TDM_DISPLAY_CAPABILITY_PP; - private_display->func_pp = *func_pp; + assert(private_display->current_backend); + + private_display->current_backend->capabilities |= TDM_DISPLAY_CAPABILITY_PP; + private_display->current_backend->func_pp = *func_pp; + + if (!private_display->pp_backend) + private_display->pp_backend = private_display->current_backend; + else + TDM_ERR("already has pp backend(%s)", private_display->pp_backend->module_data->name); return TDM_ERROR_NONE; } @@ -175,8 +190,16 @@ tdm_backend_register_func_capture(tdm_display *dpy, if (!func_capture) return TDM_ERROR_NONE; - private_display->capabilities |= TDM_DISPLAY_CAPABILITY_CAPTURE; - private_display->func_capture = *func_capture; + assert(private_display->current_backend); + + private_display->current_backend->capabilities |= TDM_DISPLAY_CAPABILITY_CAPTURE; + private_display->current_backend->func_capture = *func_capture; + + //TODO: remove later + if (!private_display->capture_backend) + private_display->capture_backend = private_display->current_backend; + else + TDM_ERR("already has capture backend(%s)", private_display->capture_backend->module_data->name); return TDM_ERROR_NONE; } @@ -186,24 +209,22 @@ static tdm_private_output* _look_for_frontend_hwc_output(tdm_output *backend_output) { tdm_private_output *frontend_output = NULL, *o = NULL; - tdm_private_display *dpy; - - dpy = tdm_display_init(NULL); - TDM_RETURN_VAL_IF_FAIL(dpy != NULL, NULL); - - LIST_FOR_EACH_ENTRY(o, &dpy->output_list, link) { - if (!(o->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC)) - continue; - - if (o->output_backend == backend_output) { - frontend_output = o; - break; + tdm_private_display *private_display = tdm_display_get(); + tdm_private_backend *private_backend = NULL; + + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(o, &private_backend->output_list, link) { + if (!(o->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC)) + continue; + + if (o->output_backend == backend_output) { + frontend_output = o; + return frontend_output; + } } } - tdm_display_deinit(dpy); - - return frontend_output; + return NULL; } EXTERN tdm_error diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 869e31f..b7b8631 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -42,12 +42,14 @@ #define CAPTURE_FUNC_ENTRY() \ tdm_func_capture *func_capture; \ tdm_private_display *private_display; \ + tdm_private_backend *private_backend; \ tdm_private_capture *private_capture; \ tdm_error ret = TDM_ERROR_NONE; \ TDM_RETURN_VAL_IF_FAIL(capture != NULL, TDM_ERROR_INVALID_PARAMETER); \ private_capture = (tdm_private_capture*)capture; \ private_display = private_capture->private_display; \ - func_capture = &private_display->func_capture + private_backend = private_capture->private_backend; \ + func_capture = &private_backend->func_capture static void _tdm_capture_print_list(struct list_head *list) @@ -174,13 +176,16 @@ _tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, void *u static void * _tdm_capture_find_object(tdm_private_display *private_display, double stamp) { + tdm_private_backend *private_backend = NULL; tdm_private_capture *private_capture = NULL; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); - LIST_FOR_EACH_ENTRY(private_capture, &private_display->capture_list, display_link) { - if (private_capture->stamp == stamp) - return private_capture; + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(private_capture, &private_backend->capture_list, display_link) { + if (private_capture->stamp == stamp) + return private_capture; + } } return NULL; @@ -199,26 +204,27 @@ tdm_capture_create_output_internal(tdm_private_output *private_output, tdm_error *error) { tdm_private_display *private_display = private_output->private_display; - tdm_func_output *func_output = &private_display->func_output; - tdm_func_capture *func_capture = &private_display->func_capture; + tdm_private_backend *private_backend = private_output->private_backend; + tdm_func_output *func_output = &private_backend->func_output; + tdm_func_capture *func_capture = &private_backend->func_capture; tdm_private_capture *private_capture = NULL; tdm_capture *capture_backend = NULL; tdm_error ret = TDM_ERROR_NONE; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) { + if (!(private_backend->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) { /* LCOV_EXCL_START */ - TDM_ERR("no capture capability"); + TDM_ERR("backend(%s) no capture capability", private_backend->module_data->name); if (error) *error = TDM_ERROR_NO_CAPABILITY; return NULL; /* LCOV_EXCL_STOP */ } - if (!(private_display->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_OUTPUT)) { + if (!(private_backend->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_OUTPUT)) { /* LCOV_EXCL_START */ - TDM_ERR("no output capture capability"); + TDM_ERR("backend(%s) no output capture capability", private_backend->module_data->name); if (error) *error = TDM_ERROR_NO_CAPABILITY; return NULL; @@ -273,7 +279,9 @@ tdm_capture_create_output_internal(tdm_private_output *private_output, private_capture->stamp++; LIST_ADD(&private_capture->link, &private_output->capture_list); - LIST_ADD(&private_capture->display_link, &private_display->capture_list); + LIST_ADD(&private_capture->display_link, &private_backend->capture_list); + + private_capture->private_backend = private_backend; private_capture->target = TDM_CAPTURE_TARGET_OUTPUT; private_capture->private_display = private_display; @@ -299,24 +307,25 @@ tdm_capture_create_layer_internal(tdm_private_layer *private_layer, tdm_error *error) { tdm_private_output *private_output = private_layer->private_output; + tdm_private_backend *private_backend = private_layer->private_backend; tdm_private_display *private_display = private_output->private_display; - tdm_func_layer *func_layer = &private_display->func_layer; - tdm_func_capture *func_capture = &private_display->func_capture; + tdm_func_layer *func_layer = &private_backend->func_layer; + tdm_func_capture *func_capture = &private_backend->func_capture; tdm_private_capture *private_capture = NULL; tdm_capture *capture_backend = NULL; tdm_error ret = TDM_ERROR_NONE; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) { - TDM_ERR("no capture capability"); + if (!(private_backend->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) { + TDM_ERR("backend(%s) no capture capability", private_backend->module_data->name); if (error) *error = TDM_ERROR_NO_CAPABILITY; return NULL; } - if (!(private_display->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_LAYER)) { - TDM_ERR("no layer capture capability"); + if (!(private_backend->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_LAYER)) { + TDM_ERR("backend(%s) no layer capture capability", private_backend->module_data->name); if (error) *error = TDM_ERROR_NO_CAPABILITY; return NULL; @@ -341,7 +350,9 @@ tdm_capture_create_layer_internal(tdm_private_layer *private_layer, private_capture->stamp++; LIST_ADD(&private_capture->link, &private_layer->capture_list); - LIST_ADD(&private_capture->display_link, &private_display->capture_list); + LIST_ADD(&private_capture->display_link, &private_backend->capture_list); + + private_capture->private_backend = private_backend; private_capture->target = TDM_CAPTURE_TARGET_LAYER; private_capture->private_display = private_display; @@ -366,6 +377,7 @@ INTERN void tdm_capture_destroy_internal(tdm_private_capture *private_capture) { tdm_private_display *private_display; + tdm_private_backend *private_backend; tdm_func_capture *func_capture; tdm_capture_private_buffer *b = NULL, *bb = NULL; struct list_head clone_list; @@ -382,7 +394,8 @@ tdm_capture_destroy_internal(tdm_private_capture *private_capture) LIST_DEL(&private_capture->link); LIST_DEL(&private_capture->display_link); - func_capture = &private_capture->private_display->func_capture; + private_backend = private_capture->private_backend; + func_capture = &private_backend->func_capture; func_capture->capture_destroy(private_capture->capture_backend); if (!LIST_IS_EMPTY(&private_capture->pending_buffer_list)) { @@ -541,15 +554,15 @@ tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer) /* LCOV_EXCL_STOP */ } - if (tdm_display_check_module_abi(private_display, 1, 2) && - private_display->caps_capture.max_attach_count > 0) { + if (tdm_backend_check_module_abi(private_backend, 1, 2) && + private_backend->caps_capture.max_attach_count > 0) { /* LCOV_EXCL_START */ int length = LIST_LENGTH(&private_capture->pending_buffer_list) + LIST_LENGTH(&private_capture->buffer_list); - if (length >= private_display->caps_capture.max_attach_count) { + if (length >= private_backend->caps_capture.max_attach_count) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: too many attached!! max_attach_count(%d)", - private_display->caps_capture.max_attach_count); + TDM_DBG("failed: backend(%s) too many attached!! max_attach_count(%d)", + private_backend->module_data->name, private_backend->caps_capture.max_attach_count); return TDM_ERROR_BAD_REQUEST; } /* LCOV_EXCL_STOP */ diff --git a/src/tdm_display.c b/src/tdm_display.c index abf4374..a7e880e 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -55,17 +55,31 @@ TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(tdm_display_is_valid(dpy), TDM_ERROR_INVALID_PARAMETER, NULL); \ private_display = (tdm_private_display*)dpy; +#define BACKEND_FUNC_ENTRY() \ + tdm_private_backend *private_backend; \ + tdm_private_display *private_display; \ + tdm_error ret = TDM_ERROR_NONE; /* default TDM_ERROR_NONE */\ + TDM_RETURN_VAL_IF_FAIL(backend != NULL, TDM_ERROR_INVALID_PARAMETER); \ + private_backend = (tdm_private_backend*)backend; \ + private_display = private_backend->private_display; + EXTERN tdm_error tdm_display_get_capabilities(tdm_display *dpy, tdm_display_capability *capabilities) { + tdm_private_backend *private_backend = NULL; + DISPLAY_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER); _pthread_mutex_lock(&private_display->lock); - *capabilities = private_display->capabilities; + *capabilities = 0; + + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + *capabilities |= private_backend->capabilities; + } _pthread_mutex_unlock(&private_display->lock); @@ -76,13 +90,15 @@ EXTERN tdm_error tdm_display_get_pp_capabilities(tdm_display *dpy, tdm_pp_capability *capabilities) { + tdm_private_backend *pp_backend; + DISPLAY_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER); _pthread_mutex_lock(&private_display->lock); - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) { + if (!private_display->pp_backend) { /* LCOV_EXCL_START */ TDM_ERR("no pp capability"); _pthread_mutex_unlock(&private_display->lock); @@ -90,7 +106,9 @@ tdm_display_get_pp_capabilities(tdm_display *dpy, /* LCOV_EXCL_STOP */ } - *capabilities = private_display->caps_pp.capabilities; + pp_backend = private_display->pp_backend; + + *capabilities = pp_backend->caps_pp.capabilities; _pthread_mutex_unlock(&private_display->lock); @@ -101,6 +119,8 @@ EXTERN tdm_error tdm_display_get_pp_available_formats(tdm_display *dpy, const tbm_format **formats, int *count) { + tdm_private_backend *pp_backend; + DISPLAY_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -108,7 +128,7 @@ tdm_display_get_pp_available_formats(tdm_display *dpy, _pthread_mutex_lock(&private_display->lock); - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) { + if (!private_display->pp_backend) { /* LCOV_EXCL_START */ TDM_ERR("no pp capability"); _pthread_mutex_unlock(&private_display->lock); @@ -116,8 +136,10 @@ tdm_display_get_pp_available_formats(tdm_display *dpy, /* LCOV_EXCL_STOP */ } - *formats = (const tbm_format *)private_display->caps_pp.formats; - *count = private_display->caps_pp.format_count; + pp_backend = private_display->pp_backend; + + *formats = (const tbm_format *)pp_backend->caps_pp.formats; + *count = pp_backend->caps_pp.format_count; _pthread_mutex_unlock(&private_display->lock); @@ -128,11 +150,13 @@ EXTERN tdm_error tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h, int *max_w, int *max_h, int *preferred_align) { + tdm_private_backend *pp_backend; + DISPLAY_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) { + if (!private_display->pp_backend) { /* LCOV_EXCL_START */ TDM_ERR("no pp capability"); _pthread_mutex_unlock(&private_display->lock); @@ -140,16 +164,18 @@ tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h, /* LCOV_EXCL_STOP */ } + pp_backend = private_display->pp_backend; + if (min_w) - *min_w = TDM_FRONT_VALUE(private_display->caps_pp.min_w); + *min_w = TDM_FRONT_VALUE(pp_backend->caps_pp.min_w); if (min_h) - *min_h = TDM_FRONT_VALUE(private_display->caps_pp.min_h); + *min_h = TDM_FRONT_VALUE(pp_backend->caps_pp.min_h); if (max_w) - *max_w = TDM_FRONT_VALUE(private_display->caps_pp.max_w); + *max_w = TDM_FRONT_VALUE(pp_backend->caps_pp.max_w); if (max_h) - *max_h = TDM_FRONT_VALUE(private_display->caps_pp.max_h); + *max_h = TDM_FRONT_VALUE(pp_backend->caps_pp.max_h); if (preferred_align) - *preferred_align = TDM_FRONT_VALUE(private_display->caps_pp.preferred_align); + *preferred_align = TDM_FRONT_VALUE(pp_backend->caps_pp.preferred_align); _pthread_mutex_unlock(&private_display->lock); @@ -160,13 +186,15 @@ EXTERN tdm_error tdm_display_get_capture_capabilities(tdm_display *dpy, tdm_capture_capability *capabilities) { + tdm_private_backend *capture_backend; + DISPLAY_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER); _pthread_mutex_lock(&private_display->lock); - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) { + if (!private_display->capture_backend) { /* LCOV_EXCL_START */ TDM_ERR("no capture capability"); _pthread_mutex_unlock(&private_display->lock); @@ -174,7 +202,9 @@ tdm_display_get_capture_capabilities(tdm_display *dpy, /* LCOV_EXCL_STOP */ } - *capabilities = private_display->caps_capture.capabilities; + capture_backend = private_display->capture_backend; + + *capabilities = capture_backend->caps_capture.capabilities; _pthread_mutex_unlock(&private_display->lock); @@ -185,6 +215,8 @@ EXTERN tdm_error tdm_display_get_capture_available_formats(tdm_display *dpy, const tbm_format **formats, int *count) { + tdm_private_backend *capture_backend; + DISPLAY_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -192,7 +224,7 @@ tdm_display_get_capture_available_formats(tdm_display *dpy, _pthread_mutex_lock(&private_display->lock); - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) { + if (!private_display->capture_backend) { /* LCOV_EXCL_START */ TDM_ERR("no capture capability"); _pthread_mutex_unlock(&private_display->lock); @@ -200,8 +232,10 @@ tdm_display_get_capture_available_formats(tdm_display *dpy, /* LCOV_EXCL_STOP */ } - *formats = (const tbm_format *)private_display->caps_capture.formats; - *count = private_display->caps_capture.format_count; + capture_backend = private_display->capture_backend; + + *formats = (const tbm_format *)capture_backend->caps_capture.formats; + *count = capture_backend->caps_capture.format_count; _pthread_mutex_unlock(&private_display->lock); @@ -212,11 +246,13 @@ EXTERN tdm_error tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h, int *max_w, int *max_h, int *preferred_align) { + tdm_private_backend *capture_backend; + DISPLAY_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) { + if (!private_display->capture_backend) { /* LCOV_EXCL_START */ TDM_ERR("no capture capability"); _pthread_mutex_unlock(&private_display->lock); @@ -224,16 +260,18 @@ tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h, /* LCOV_EXCL_STOP */ } + capture_backend = private_display->capture_backend; + if (min_w) - *min_w = TDM_FRONT_VALUE(private_display->caps_capture.min_w); + *min_w = TDM_FRONT_VALUE(capture_backend->caps_capture.min_w); if (min_h) - *min_h = TDM_FRONT_VALUE(private_display->caps_capture.min_h); + *min_h = TDM_FRONT_VALUE(capture_backend->caps_capture.min_h); if (max_w) - *max_w = TDM_FRONT_VALUE(private_display->caps_capture.max_w); + *max_w = TDM_FRONT_VALUE(capture_backend->caps_capture.max_w); if (max_h) - *max_h = TDM_FRONT_VALUE(private_display->caps_capture.max_h); + *max_h = TDM_FRONT_VALUE(capture_backend->caps_capture.max_h); if (preferred_align) - *preferred_align = TDM_FRONT_VALUE(private_display->caps_capture.preferred_align); + *preferred_align = TDM_FRONT_VALUE(capture_backend->caps_capture.preferred_align); _pthread_mutex_unlock(&private_display->lock); @@ -243,22 +281,20 @@ tdm_display_get_capture_available_size(tdm_display *dpy, int *min_w, int *min_h, EXTERN tdm_error tdm_display_get_max_layer_count(tdm_display *dpy, int *max_count) { - DISPLAY_FUNC_ENTRY(); - + TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(max_count != NULL, TDM_ERROR_INVALID_PARAMETER); - _pthread_mutex_lock(&private_display->lock); - - *max_count = TDM_FRONT_VALUE(private_display->caps_display.max_layer_count); + TDM_DEPRECATED(NULL); - _pthread_mutex_unlock(&private_display->lock); + *max_count = -1; - return ret; + return TDM_ERROR_NONE; } EXTERN tdm_error tdm_display_get_output_count(tdm_display *dpy, int *count) { + tdm_private_backend *private_backend = NULL; tdm_private_output *private_output = NULL; DISPLAY_FUNC_ENTRY(); @@ -268,14 +304,10 @@ tdm_display_get_output_count(tdm_display *dpy, int *count) _pthread_mutex_lock(&private_display->lock); *count = 0; - LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) - (*count)++; - - if (*count == 0) { - /* LCOV_EXCL_START */ - _pthread_mutex_unlock(&private_display->lock); - return TDM_ERROR_NONE; - /* LCOV_EXCL_STOP */ + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(private_output, &private_backend->output_list, link) { + (*count)++; + } } _pthread_mutex_unlock(&private_display->lock); @@ -287,6 +319,7 @@ tdm_display_get_output_count(tdm_display *dpy, int *count) EXTERN tdm_output * tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error) { + tdm_private_backend *private_backend = NULL; tdm_private_output *private_output = NULL; DISPLAY_FUNC_ENTRY_ERROR(); @@ -296,10 +329,12 @@ tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error) if (error) *error = TDM_ERROR_NONE; - LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) { - if (private_output->index == index) { - _pthread_mutex_unlock(&private_display->lock); - return private_output; + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(private_output, &private_backend->output_list, link) { + if (private_output->index == index) { + _pthread_mutex_unlock(&private_display->lock); + return private_output; + } } } @@ -374,13 +409,48 @@ EXTERN tdm_error tdm_display_get_backend_info(tdm_display *dpy, const char **name, const char **vendor, int *major, int *minor) { - tdm_backend_module *module_data; + tdm_private_backend *private_backend; + tdm_backend_module *module_data = NULL; DISPLAY_FUNC_ENTRY(); + TDM_DEPRECATED("Use tdm_backend_get_info"); + + _pthread_mutex_lock(&private_display->lock); + + /* use first backend */ + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + module_data = private_backend->module_data; + break; + } + + assert(module_data != NULL); + + if (name) + *name = module_data->name; + if (vendor) + *vendor = module_data->vendor; + if (major) + *major = TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version); + if (minor) + *minor = TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version); + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +EXTERN tdm_error +tdm_backend_get_info(tdm_backend *backend, const char **name, + const char **vendor, int *major, int *minor) +{ + tdm_backend_module *module_data; + + BACKEND_FUNC_ENTRY(); + _pthread_mutex_lock(&private_display->lock); - module_data = private_display->module_data; + module_data = private_backend->module_data; if (name) *name = module_data->name; @@ -405,7 +475,7 @@ tdm_display_create_pp(tdm_display *dpy, tdm_error *error) _pthread_mutex_lock(&private_display->lock); - pp = (tdm_pp *)tdm_pp_create_internal(private_display, error); + pp = (tdm_pp *)tdm_pp_create_internal(private_display->pp_backend, error); _pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_event_loop.c b/src/tdm_event_loop.c index 1745d8e..157c8e8 100644 --- a/src/tdm_event_loop.c +++ b/src/tdm_event_loop.c @@ -60,25 +60,21 @@ typedef struct _tdm_event_loop_source_timer { static tdm_error _tdm_event_loop_main_fd_handler(int fd, tdm_event_loop_mask mask, void *user_data) { - tdm_private_display *private_display = (tdm_private_display*)user_data; - tdm_private_loop *private_loop; + tdm_private_backend *private_backend = (tdm_private_backend*)user_data; tdm_func_display *func_display; tdm_error ret; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); - TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED); - TDM_RETURN_VAL_IF_FAIL(private_display->private_loop != NULL, TDM_ERROR_OPERATION_FAILED); - - private_loop = private_display->private_loop; + TDM_RETURN_VAL_IF_FAIL(private_backend != NULL, TDM_ERROR_OPERATION_FAILED); if (tdm_debug_module & TDM_DEBUG_EVENT) - TDM_INFO("backend fd(%d) event happens", private_loop->backend_fd); + TDM_INFO("backend fd(%d) event happens", private_backend->fd); - func_display = &private_display->func_display; + func_display = &private_backend->func_display; if (!func_display->display_handle_events) return TDM_ERROR_NONE; - ret = func_display->display_handle_events(private_display->bdata); + ret = func_display->display_handle_events(private_backend->bdata); return ret; } @@ -100,8 +96,6 @@ tdm_event_loop_init(tdm_private_display *private_display) return TDM_ERROR_OUT_OF_MEMORY; } - private_loop->backend_fd = -1; - private_loop->wl_display = wl_display_create(); if (!private_loop->wl_display) { TDM_ERR("creating a wayland display failed"); @@ -138,6 +132,8 @@ tdm_event_loop_init(tdm_private_display *private_display) INTERN void tdm_event_loop_deinit(tdm_private_display *private_display) { + tdm_private_backend *private_backend = NULL; + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); if (!private_display->private_loop) @@ -148,8 +144,12 @@ tdm_event_loop_deinit(tdm_private_display *private_display) tdm_server_deinit(private_display->private_loop); - if (private_display->private_loop->backend_source) - tdm_event_loop_source_remove(private_display->private_loop->backend_source); + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + if (private_backend->event_source) + tdm_event_loop_source_remove(private_backend->event_source); + private_backend->event_source = NULL; + private_backend->fd = -1; + } if (private_display->private_loop->wl_display) wl_display_destroy(private_display->private_loop->wl_display); @@ -171,43 +171,42 @@ INTERN void tdm_event_loop_create_backend_source(tdm_private_display *private_display) { tdm_private_loop *private_loop = private_display->private_loop; - tdm_func_display *func_display; + tdm_private_backend *private_backend = NULL; tdm_error ret; int fd = -1; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); TDM_RETURN_IF_FAIL(private_loop != NULL); - func_display = &private_display->func_display; - if (!func_display->display_get_fd) { - TDM_INFO("TDM backend module won't offer a display fd"); - return; - } + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + tdm_func_display *func_display = &private_backend->func_display; - ret = func_display->display_get_fd(private_display->bdata, &fd); - if (fd < 0) { - TDM_ERR("TDM backend module returns fd(%d)", fd); - return; - } + if (!func_display->display_get_fd) { + TDM_INFO("TDM backend module won't offer a display fd"); + private_backend->event_source = NULL; + private_backend->fd = -1; + continue; + } - if (!func_display->display_handle_events) { - TDM_ERR("no display_handle_events function"); - return; - } + ret = func_display->display_get_fd(private_backend->bdata, &fd); - private_loop->backend_source = - tdm_event_loop_add_fd_handler(private_display, fd, - TDM_EVENT_LOOP_READABLE, - _tdm_event_loop_main_fd_handler, - private_display, &ret); - if (!private_loop->backend_source) { - TDM_ERR("no backend fd(%d) source", fd); - return; - } + assert(ret == TDM_ERROR_NONE && fd >= 0); + assert(func_display->display_handle_events); - private_loop->backend_fd = fd; + private_backend->event_source = + tdm_event_loop_add_fd_handler(private_display, fd, + TDM_EVENT_LOOP_READABLE, + _tdm_event_loop_main_fd_handler, + private_backend, &ret); + if (!private_backend->event_source) { + TDM_ERR("no backend fd(%d) source", fd); + return; + } - TDM_INFO("backend fd(%d) source created", private_loop->backend_fd); + private_backend->fd = fd; + + TDM_INFO("backend fd(%d) source created", private_backend->fd); + } } INTERN int diff --git a/src/tdm_helper.c b/src/tdm_helper.c index e3d5f3f..6e2c5cf 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -753,10 +753,9 @@ tdm_helper_capture_output(tdm_output *output, tbm_surface_h dst_buffer, return TDM_ERROR_NONE; } -EXTERN void -tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) +static char * +_tdm_helper_get_backend_information(tdm_private_backend *private_backend, char *reply, int *len) { - tdm_private_display *private_display; tdm_backend_module *module_data; tdm_func_output *func_output; tdm_func_layer *func_layer; @@ -767,27 +766,23 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) tdm_error ret; int i; - TDM_DBG_RETURN_IF_FAIL(dpy != NULL); - - private_display = dpy; - func_output = &private_display->func_output; - func_layer = &private_display->func_layer; + func_output = &private_backend->func_output; + func_layer = &private_backend->func_layer; /* module information */ - module_data = private_display->module_data; - TDM_SNPRINTF(reply, len, "[TDM backend information]\n"); - TDM_SNPRINTF(reply, len, "name: %s\n", module_data->name); + module_data = private_backend->module_data; + TDM_SNPRINTF(reply, len, "['%s' backend information]\n", module_data->name); TDM_SNPRINTF(reply, len, "vendor: %s\n", module_data->vendor); TDM_SNPRINTF(reply, len, "version: %d.%d\n\n", (int)TDM_BACKEND_GET_ABI_MAJOR(module_data->abi_version), (int)TDM_BACKEND_GET_ABI_MINOR(module_data->abi_version)); /* output information */ - TDM_SNPRINTF(reply, len, "[Output information]\n"); + TDM_SNPRINTF(reply, len, "['%s' backend output information]\n", module_data->name); TDM_SNPRINTF(reply, len, "--------------------------------------------------------------------------------------------\n"); TDM_SNPRINTF(reply, len, "idx maker model name type status dpms subpixel align_w min max phy(mm)\n"); TDM_SNPRINTF(reply, len, "--------------------------------------------------------------------------------------------\n"); - LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) { + LIST_FOR_EACH_ENTRY(private_output, &private_backend->output_list, link) { TDM_SNPRINTF(reply, len, "%d %s %s %s %s %s %s %u %d %dx%d %dx%d %ux%u\n", private_output->index, private_output->caps.maker, private_output->caps.model, private_output->caps.name, @@ -805,15 +800,9 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) TDM_SNPRINTF(reply, len, "\t%u modes:\n", private_output->caps.mode_count); if (private_output->caps.mode_count > 0) { - const tdm_output_mode *current_mode = NULL; - - TDM_DBG_RETURN_IF_FAIL(func_output->output_get_mode); - ret = func_output->output_get_mode(private_output->output_backend, ¤t_mode); - TDM_DBG_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); - TDM_SNPRINTF(reply, len, "\t\t name refresh (Hz) clk hdisp hss hse htot vdisp vss vse vtot vscan\n"); for (i = 0; i < private_output->caps.mode_count; i++) { - char *current = (current_mode == private_output->caps.modes + i) ? "*" : " "; + char *current = (private_output->current_mode == private_output->caps.modes + i) ? "*" : " "; TDM_SNPRINTF(reply, len, "\t\t%s%s %u %u %u %u %u %u %u %u %u %u %u ", current, private_output->caps.modes[i].name, @@ -840,11 +829,11 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) TDM_SNPRINTF(reply, len, "\t\tname\ttype\tidx\tvalue\n"); for (i = 0; i < private_output->caps.prop_count; i++) { tdm_value value; - TDM_DBG_RETURN_IF_FAIL(func_output->output_get_property); + TDM_DBG_RETURN_VAL_IF_FAIL(func_output->output_get_property, reply); ret = func_output->output_get_property(private_output->output_backend, private_output->caps.props[i].id, &value); - TDM_DBG_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + TDM_DBG_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, reply); TDM_SNPRINTF(reply, len, "\t\t%s\t%s\t%u\t", private_output->caps.props[i].name, tdm_value_type_str(private_output->caps.props[i].type), @@ -873,11 +862,11 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) TDM_SNPRINTF(reply, len, "\n"); /* layer information */ - TDM_SNPRINTF(reply, len, "[Layer information]\n"); + TDM_SNPRINTF(reply, len, "['%s' backend layer information]\n", module_data->name); TDM_SNPRINTF(reply, len, "-----------------------------------------------------------------------\n"); TDM_SNPRINTF(reply, len, "idx output zpos buf format size crop geometry transform\n"); TDM_SNPRINTF(reply, len, "-----------------------------------------------------------------------\n"); - LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) { + LIST_FOR_EACH_ENTRY(private_output, &private_backend->output_list, link) { LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { if (!private_layer->usable) { tdm_info_layer info; @@ -885,10 +874,10 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) tdm_size size; tbm_surface_info_s buf_info; - TDM_DBG_RETURN_IF_FAIL(func_layer->layer_get_info); + TDM_DBG_RETURN_VAL_IF_FAIL(func_layer->layer_get_info, reply); memset(&info, 0, sizeof info); ret = func_layer->layer_get_info(private_layer->layer_backend, &info); - TDM_DBG_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + TDM_DBG_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, reply); if (!private_layer->showing_buffer) continue; @@ -941,11 +930,11 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) TDM_SNPRINTF(reply, len, "\t\tname\ttype\tidx\tvalue\n"); for (i = 0; i < private_layer->caps.prop_count; i++) { tdm_value value; - TDM_DBG_RETURN_IF_FAIL(func_layer->layer_get_property); + TDM_DBG_RETURN_VAL_IF_FAIL(func_layer->layer_get_property, reply); ret = func_layer->layer_get_property(private_layer->layer_backend, private_layer->caps.props[i].id, &value); - TDM_DBG_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + TDM_DBG_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, reply); TDM_SNPRINTF(reply, len, "\t\t%s\t%s\t%u\t", private_layer->caps.props[i].name, tdm_value_type_str(private_output->caps.props[i].type), @@ -974,31 +963,31 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) } TDM_SNPRINTF(reply, len, "\n"); - if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP) { + if (private_backend->capabilities & TDM_DISPLAY_CAPABILITY_PP) { const char *sep = ""; - TDM_SNPRINTF(reply, len, "[PP information]\n"); + TDM_SNPRINTF(reply, len, "['%s' backend PP information]\n", module_data->name); TDM_SNPRINTF(reply, len, "caps\t: "); - tdm_pp_caps_str(private_display->caps_pp.capabilities, &reply, len); + tdm_pp_caps_str(private_backend->caps_pp.capabilities, &reply, len); TDM_SNPRINTF(reply, len, "\n"); TDM_SNPRINTF(reply, len, "formats\t: "); - for (i = 0; i < private_display->caps_pp.format_count; i++) { - if (private_display->caps_pp.formats[i] == 0) + for (i = 0; i < private_backend->caps_pp.format_count; i++) { + if (private_backend->caps_pp.formats[i] == 0) continue; - TDM_SNPRINTF(reply, len, "%s%c%c%c%c", sep, FOURCC_STR(private_display->caps_pp.formats[i])); + TDM_SNPRINTF(reply, len, "%s%c%c%c%c", sep, FOURCC_STR(private_backend->caps_pp.formats[i])); sep = ","; } TDM_SNPRINTF(reply, len, "\n"); TDM_SNPRINTF(reply, len, "size\t: min(%dx%d) max(%dx%d) align_w(%d)\n", - TDM_FRONT_VALUE(private_display->caps_pp.min_w), - TDM_FRONT_VALUE(private_display->caps_pp.min_h), - TDM_FRONT_VALUE(private_display->caps_pp.max_w), - TDM_FRONT_VALUE(private_display->caps_pp.max_h), - TDM_FRONT_VALUE(private_display->caps_pp.preferred_align)); - if (!LIST_IS_EMPTY(&private_display->pp_list)) { + TDM_FRONT_VALUE(private_backend->caps_pp.min_w), + TDM_FRONT_VALUE(private_backend->caps_pp.min_h), + TDM_FRONT_VALUE(private_backend->caps_pp.max_w), + TDM_FRONT_VALUE(private_backend->caps_pp.max_h), + TDM_FRONT_VALUE(private_backend->caps_pp.preferred_align)); + if (!LIST_IS_EMPTY(&private_backend->pp_list)) { TDM_SNPRINTF(reply, len, "-------------------------------------------------------------\n"); TDM_SNPRINTF(reply, len, "src(format size crop) | dst(format size crop) | transform\n"); TDM_SNPRINTF(reply, len, "-------------------------------------------------------------\n"); - LIST_FOR_EACH_ENTRY(private_pp, &private_display->pp_list, link) { + LIST_FOR_EACH_ENTRY(private_pp, &private_backend->pp_list, link) { TDM_SNPRINTF(reply, len, "%c%c%c%c %ux%u %ux%u+%u+%u | %c%c%c%c %ux%u %ux%u+%u+%u | %s\n", FOURCC_STR(private_pp->info.src_config.format), private_pp->info.src_config.size.h, @@ -1014,35 +1003,35 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) } } } else { - TDM_SNPRINTF(reply, len, "[No PP capability]\n"); + TDM_SNPRINTF(reply, len, "['%s' backend No PP capability]\n", module_data->name); } TDM_SNPRINTF(reply, len, "\n"); - if (private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) { + if (private_backend->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE) { const char *sep = ""; - TDM_SNPRINTF(reply, len, "[Capture information]\n"); + TDM_SNPRINTF(reply, len, "['%s' backend capture information]\n", module_data->name); TDM_SNPRINTF(reply, len, "caps\t: "); - tdm_capture_caps_str(private_display->caps_capture.capabilities, &reply, len); + tdm_capture_caps_str(private_backend->caps_capture.capabilities, &reply, len); TDM_SNPRINTF(reply, len, "\n"); TDM_SNPRINTF(reply, len, "formats\t: "); - for (i = 0; i < private_display->caps_capture.format_count; i++) { - if (private_display->caps_capture.formats[i] == 0) + for (i = 0; i < private_backend->caps_capture.format_count; i++) { + if (private_backend->caps_capture.formats[i] == 0) continue; - TDM_SNPRINTF(reply, len, "%s%c%c%c%c", sep, FOURCC_STR(private_display->caps_capture.formats[i])); + TDM_SNPRINTF(reply, len, "%s%c%c%c%c", sep, FOURCC_STR(private_backend->caps_capture.formats[i])); sep = ","; } TDM_SNPRINTF(reply, len, "\n"); TDM_SNPRINTF(reply, len, "size\t: min(%dx%d) max(%dx%d) align_w(%d)\n", - TDM_FRONT_VALUE(private_display->caps_capture.min_w), - TDM_FRONT_VALUE(private_display->caps_capture.min_h), - TDM_FRONT_VALUE(private_display->caps_capture.max_w), - TDM_FRONT_VALUE(private_display->caps_capture.max_h), - TDM_FRONT_VALUE(private_display->caps_capture.preferred_align)); - if (!LIST_IS_EMPTY(&private_display->capture_list)) { + TDM_FRONT_VALUE(private_backend->caps_capture.min_w), + TDM_FRONT_VALUE(private_backend->caps_capture.min_h), + TDM_FRONT_VALUE(private_backend->caps_capture.max_w), + TDM_FRONT_VALUE(private_backend->caps_capture.max_h), + TDM_FRONT_VALUE(private_backend->caps_capture.preferred_align)); + if (!LIST_IS_EMPTY(&private_backend->capture_list)) { TDM_SNPRINTF(reply, len, "-----------------------------------\n"); TDM_SNPRINTF(reply, len, "dst(format size crop) | transform\n"); TDM_SNPRINTF(reply, len, "-----------------------------------\n"); - LIST_FOR_EACH_ENTRY(private_capture, &private_display->capture_list, link) { + LIST_FOR_EACH_ENTRY(private_capture, &private_backend->capture_list, link) { TDM_SNPRINTF(reply, len, "%c%c%c%c %ux%u %ux%u+%u+%u | %s\n", FOURCC_STR(private_capture->info.dst_config.format), private_capture->info.dst_config.size.h, @@ -1053,16 +1042,36 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) } } } else { - TDM_SNPRINTF(reply, len, "[No Capture capability]\n"); + TDM_SNPRINTF(reply, len, "['%s' backend No Capture capability]\n", module_data->name); } TDM_SNPRINTF(reply, len, "\n"); + return reply; +} + +EXTERN void +tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) +{ + tdm_private_display *private_display; + tdm_private_backend *private_backend = NULL; + + TDM_DBG_RETURN_IF_FAIL(dpy != NULL); + + private_display = dpy; + + _pthread_mutex_lock(&private_display->lock); + + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + reply = _tdm_helper_get_backend_information(private_backend, reply, len); + } + + _pthread_mutex_unlock(&private_display->lock); } /* LCOV_EXCL_START */ EXTERN int tdm_helper_commit_per_vblank_enabled(tdm_display *dpy) { - TDM_ERR("the deprecated function, use 'tdm_helper_output_commit_per_vblank_enabled' instead."); + TDM_DEPRECATED("Use tdm_helper_output_commit_per_vblank_enabled"); return 0; } diff --git a/src/tdm_hwc_window.c b/src/tdm_hwc_window.c index 417fcd0..ea59e9b 100644 --- a/src/tdm_hwc_window.c +++ b/src/tdm_hwc_window.c @@ -74,6 +74,7 @@ tbm_surface_queue_h tdm_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; tbm_surface_queue_h queue = NULL; @@ -81,12 +82,13 @@ tdm_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_get_tbm_buffer_queue) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); if (error) *error = TDM_ERROR_NOT_IMPLEMENTED; return NULL; @@ -104,6 +106,7 @@ EXTERN tdm_error tdm_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, tdm_hwc_window_composition composition_type) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; HWC_WINDOW_FUNC_ENTRY(); @@ -112,12 +115,13 @@ tdm_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_set_composition_type) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -132,6 +136,7 @@ tdm_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, EXTERN tdm_error tdm_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_hwc_region damage) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; HWC_WINDOW_FUNC_ENTRY(); @@ -140,12 +145,13 @@ tdm_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_hwc_region dama _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_set_buffer_damage) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -161,6 +167,7 @@ tdm_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_hwc_region dama EXTERN tdm_error tdm_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; char fmtstr[128]; @@ -170,12 +177,13 @@ tdm_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info) _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_set_info) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -204,6 +212,7 @@ tdm_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info) EXTERN tdm_error tdm_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window; HWC_WINDOW_FUNC_ENTRY(); @@ -219,12 +228,13 @@ tdm_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer) /* LCOV_EXCL_STOP */ } - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_set_buffer) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -239,13 +249,15 @@ tdm_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h buffer) EXTERN tdm_error tdm_hwc_window_unset_buffer(tdm_hwc_window *hwc_window) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window; HWC_WINDOW_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_unset_buffer) { /* LCOV_EXCL_START */ @@ -267,7 +279,8 @@ tdm_hwc_window_create_internal(tdm_private_output *private_output, int is_video, tdm_error *error) { tdm_private_display *private_display = private_output->private_display; - tdm_func_output *func_output = &private_display->func_output; + tdm_private_backend *private_backend = private_output->private_backend; + tdm_func_output *func_output = &private_backend->func_output; tdm_private_hwc_window *private_hwc_window = NULL; tdm_hwc_window *hwc_window_backend = NULL; tdm_error ret = TDM_ERROR_NONE; @@ -336,8 +349,8 @@ tdm_hwc_window_create_internal(tdm_private_output *private_output, int is_video, INTERN tdm_error tdm_hwc_window_destroy_internal(tdm_private_hwc_window * private_hwc_window) { - tdm_private_display *private_display; tdm_private_output *private_output; + tdm_private_backend *private_backend; tdm_func_output *func_output; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); @@ -345,12 +358,12 @@ tdm_hwc_window_destroy_internal(tdm_private_hwc_window * private_hwc_window) if (!private_hwc_window) return TDM_ERROR_OPERATION_FAILED; - private_display = private_hwc_window->private_display; private_output = private_hwc_window->private_output; + private_backend = private_output->private_backend; LIST_DEL(&private_hwc_window->link); - func_output = &private_display->func_output; + func_output = &private_backend->func_output; func_output->output_hwc_destroy_window(private_output->output_backend, private_hwc_window->hwc_window_backend); free(private_hwc_window); @@ -360,18 +373,20 @@ tdm_hwc_window_destroy_internal(tdm_private_hwc_window * private_hwc_window) EXTERN tdm_error tdm_hwc_window_set_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; HWC_WINDOW_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_set_flags) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -386,18 +401,20 @@ tdm_hwc_window_set_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags) EXTERN tdm_error tdm_hwc_window_unset_flags(tdm_hwc_window *hwc_window, tdm_hwc_window_flag flags) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; HWC_WINDOW_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_unset_flags) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -427,6 +444,7 @@ _tdm_hwc_window_layer_commit_handler(tdm_layer *layer, unsigned int sequence, tdm_error tdm_hwc_window_commit(tdm_hwc_window *hwc_window, tdm_hwc_window_commit_handler func, void *user_data) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; tdm_private_hwc_window_commit_handler *hwc_window_commit_handler; tdm_layer *layer = NULL; @@ -439,7 +457,8 @@ tdm_hwc_window_commit(tdm_hwc_window *hwc_window, tdm_hwc_window_commit_handler _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_get_layer) { /* LCOV_EXCL_START */ @@ -522,6 +541,7 @@ EXTERN tdm_error tdm_hwc_window_video_get_capability(tdm_hwc_window *hwc_window, tdm_hwc_window_video_capability *video_capability) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; HWC_WINDOW_FUNC_ENTRY(); @@ -530,12 +550,13 @@ tdm_hwc_window_video_get_capability(tdm_hwc_window *hwc_window, _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_video_get_capability) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -552,6 +573,7 @@ EXTERN tdm_error tdm_hwc_window_video_get_available_properties(tdm_hwc_window *hwc_window, const tdm_prop **props, int *count) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; HWC_WINDOW_FUNC_ENTRY(); @@ -561,12 +583,13 @@ tdm_hwc_window_video_get_available_properties(tdm_hwc_window *hwc_window, _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_video_get_available_properties) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -583,6 +606,7 @@ EXTERN tdm_error tdm_hwc_window_video_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; HWC_WINDOW_FUNC_ENTRY(); @@ -591,12 +615,13 @@ tdm_hwc_window_video_get_property(tdm_hwc_window *hwc_window, _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_video_get_property) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -613,18 +638,20 @@ EXTERN tdm_error tdm_hwc_window_video_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value) { + tdm_private_backend *private_backend; tdm_func_hwc_window *func_hwc_window = NULL; HWC_WINDOW_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); - func_hwc_window = &private_display->func_hwc_window; + private_backend = private_output->private_backend; + func_hwc_window = &private_backend->func_hwc_window; if (!func_hwc_window->hwc_window_video_set_property) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } diff --git a/src/tdm_layer.c b/src/tdm_layer.c index 2d31817..3afebd1 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -170,12 +170,14 @@ tdm_layer_get_zpos(tdm_layer *layer, int *zpos) EXTERN tdm_error tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value) { + tdm_private_backend *private_backend; tdm_func_layer *func_layer; LAYER_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; if (private_layer->usable) TDM_INFO("layer(%d) not usable", private_layer->index); @@ -200,6 +202,7 @@ tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value) EXTERN tdm_error tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value) { + tdm_private_backend *private_backend; tdm_func_layer *func_layer; LAYER_FUNC_ENTRY(); @@ -207,7 +210,8 @@ tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value) _pthread_mutex_lock(&private_display->lock); - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; if (!func_layer->layer_get_property) { /* LCOV_EXCL_START */ @@ -227,12 +231,12 @@ tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value) INTERN tdm_error tdm_layer_set_info_internal(tdm_private_layer *private_layer, tdm_info_layer *info) { - tdm_private_output *private_output = private_layer->private_output; - tdm_private_display *private_display = private_output->private_display; + tdm_private_backend *private_backend; tdm_func_layer *func_layer; char fmtstr[128]; - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; if (private_layer->usable) TDM_INFO("layer(%p) not usable", private_layer); @@ -285,6 +289,7 @@ tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info) EXTERN tdm_error tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info) { + tdm_private_backend *private_backend; tdm_func_layer *func_layer; LAYER_FUNC_ENTRY(); @@ -292,7 +297,8 @@ tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info) _pthread_mutex_lock(&private_display->lock); - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; if (!func_layer->layer_get_info) { /* LCOV_EXCL_START */ @@ -437,8 +443,8 @@ _tdm_layer_free_all_buffers(tdm_private_layer *private_layer) INTERN tdm_error tdm_layer_set_buffer_internal(tdm_private_layer *private_layer, tbm_surface_h buffer) { + tdm_private_backend *private_backend; tdm_private_output *private_output = private_layer->private_output; - tdm_private_display *private_display = private_output->private_display; tdm_func_layer *func_layer; /* LCOV_EXCL_START */ @@ -456,7 +462,8 @@ tdm_layer_set_buffer_internal(tdm_private_layer *private_layer, tbm_surface_h bu } /* LCOV_EXCL_STOP */ - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; if (private_layer->usable) TDM_INFO("layer(%p) not usable", private_layer); @@ -520,12 +527,12 @@ tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) INTERN tdm_error tdm_layer_unset_buffer_internal(tdm_private_layer *private_layer) { - tdm_private_output *private_output = private_layer->private_output; - tdm_private_display *private_display = private_output->private_display; + tdm_private_backend *private_backend; tdm_func_layer *func_layer; tdm_error ret = TDM_ERROR_NONE; - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; _tdm_layer_free_all_buffers(private_layer); @@ -840,12 +847,12 @@ _tdm_layer_reset_pending_data(tdm_private_layer *private_layer) INTERN tdm_error tdm_layer_commit_pending_data(tdm_private_layer *private_layer) { - tdm_private_output *private_output = private_layer->private_output; - tdm_private_display *private_display = private_output->private_display; + tdm_private_backend *private_backend; tdm_func_layer *func_layer; tdm_error ret = TDM_ERROR_NONE; - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; if (private_layer->pending_info_changed) { ret = func_layer->layer_set_info(private_layer->layer_backend, &private_layer->pending_info); @@ -1124,6 +1131,7 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) { TDM_RETURN_IF_FAIL(data != NULL); tdm_layer *layer = data; + tdm_private_backend *private_backend; tdm_func_layer *func_layer; tbm_surface_h surface = NULL; tdm_private_layer_buffer *layer_buffer; @@ -1131,7 +1139,9 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) _pthread_mutex_lock(&private_display->lock); - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; + if (!func_layer->layer_set_buffer) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); @@ -1216,6 +1226,7 @@ _tbm_layer_queue_destroy_cb(tbm_surface_queue_h surface_queue, void *data) EXTERN tdm_error tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue) { + tdm_private_backend *private_backend; tdm_func_layer *func_layer; LAYER_FUNC_ENTRY(); @@ -1223,7 +1234,8 @@ tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue) _pthread_mutex_lock(&private_display->lock); - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; if (private_layer->usable) TDM_INFO("layer(%p) not usable", private_layer); @@ -1289,12 +1301,14 @@ tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable) EXTERN tdm_error tdm_layer_set_video_pos(tdm_layer *layer, int zpos) { + tdm_private_backend *private_backend; tdm_func_layer *func_layer; LAYER_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) { TDM_ERR("layer(%p) is not video layer", private_layer); @@ -1336,13 +1350,15 @@ tdm_layer_create_capture(tdm_layer *layer, tdm_error *error) EXTERN tdm_error tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags) { + tdm_private_backend *private_backend; tdm_func_layer *func_layer; LAYER_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(flags != NULL, TDM_ERROR_INVALID_PARAMETER); _pthread_mutex_lock(&private_display->lock); - func_layer = &private_display->func_layer; + private_backend = private_layer->private_backend; + func_layer = &private_backend->func_layer; if (!func_layer->layer_get_buffer_flags) { /* LCOV_EXCL_START */ diff --git a/src/tdm_macro.h b/src/tdm_macro.h index 98f25b4..5d41886 100644 --- a/src/tdm_macro.h +++ b/src/tdm_macro.h @@ -74,8 +74,6 @@ extern "C" { #define TDM_SWAP(a, b) ({ int t; t = a; a = b; b = t; }) #define TDM_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -#define TDM_NEVER_GET_HERE() TDM_WRN("** NEVER GET HERE **") - #define TDM_SNPRINTF(p, len, fmt, ARG...) \ do { \ if (p && len && *len > 0) { \ @@ -368,6 +366,12 @@ TDM_BIT_NAME_FB(capture_caps) return; \ } \ } +#define TDM_DBG_RETURN_VAL_IF_FAIL(cond, val) { \ + if (!(cond)) { \ + TDM_SNPRINTF(reply, len, "[%s %d] '%s' failed\n", __func__, __LINE__, #cond); \ + return val; \ + } \ +} #define TDM_DBG_GOTO_IF_FAIL(cond, dst) { \ if (!(cond)) { \ TDM_SNPRINTF(reply, len, "[%s %d] '%s' failed\n", __func__, __LINE__, #cond); \ diff --git a/src/tdm_monitor_server.c b/src/tdm_monitor_server.c index f1edee7..e566681 100644 --- a/src/tdm_monitor_server.c +++ b/src/tdm_monitor_server.c @@ -43,9 +43,7 @@ static void _tdm_monitor_server_usage(char *app_name, char *reply, int *len); static void _tdm_monitor_server_query(unsigned int pid, char *cwd, int argc, char *argv[], char *reply, int *len, tdm_display *dpy) { - tdm_display_lock(dpy); tdm_helper_get_display_information(dpy, reply, len); - tdm_display_unlock(dpy); } static void diff --git a/src/tdm_output.c b/src/tdm_output.c index accdfa3..689eed0 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -145,6 +145,25 @@ tdm_output_init(tdm_private_display *private_display) return TDM_ERROR_NONE; } +EXTERN tdm_backend * +tdm_output_get_backend(tdm_output *output, tdm_error *error) +{ + tdm_private_backend *private_backend; + + OUTPUT_FUNC_ENTRY_ERROR(); + + _pthread_mutex_lock(&private_display->lock); + + private_backend = private_output->private_backend; + + if (error) + *error = TDM_ERROR_NONE; + + _pthread_mutex_unlock(&private_display->lock); + + return private_backend; +} + EXTERN tdm_error tdm_output_get_model_info(tdm_output *output, const char **maker, const char **model, const char **name) @@ -201,15 +220,12 @@ tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status) static void _tdm_output_update(tdm_output *output_backend, void *user_data) { - tdm_private_display *private_display; tdm_private_output *private_output = user_data; tdm_error ret; TDM_RETURN_IF_FAIL(private_output); - private_display = private_output->private_display; - - ret = tdm_display_update_output(private_display, output_backend, private_output->pipe); + ret = tdm_display_update_output(private_output->private_backend, output_backend, private_output->pipe); TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); } /* LCOV_EXCL_STOP */ @@ -514,7 +530,7 @@ tdm_output_get_cursor_available_size(tdm_output *output, int *min_w, int *min_h, _pthread_mutex_lock(&private_display->lock); - if (!tdm_display_check_module_abi(private_display, 1, 5)) { + if (!tdm_backend_check_module_abi(private_output->private_backend, 1, 5)) { if (min_w) *min_w = -1; @@ -621,17 +637,19 @@ tdm_output_get_primary_index(tdm_output *output, int *index) EXTERN tdm_error tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value) { + tdm_private_backend *private_backend; tdm_func_output *func_output; OUTPUT_FUNC_ENTRY(); _pthread_mutex_lock(&private_display->lock); - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_set_property) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -647,6 +665,7 @@ tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value) EXTERN tdm_error tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value) { + tdm_private_backend *private_backend; tdm_func_output *func_output; OUTPUT_FUNC_ENTRY(); @@ -654,12 +673,13 @@ tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value) _pthread_mutex_lock(&private_display->lock); - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_get_property) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -840,13 +860,15 @@ _tdm_output_wait_vblank(tdm_private_output *private_output, int interval, int sy tdm_output_vblank_handler func, void *user_data, unsigned int add_front) { + tdm_private_backend *private_backend; tdm_func_output *func_output; tdm_private_output_vblank_handler *vblank_handler = NULL, *v = NULL; unsigned int skip_request = 0; pid_t tid = syscall(SYS_gettid); tdm_error ret = TDM_ERROR_NONE; - func_output = &private_output->private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; /* interval SHOULD be at least 1 */ if (interval <= 0) @@ -854,7 +876,7 @@ _tdm_output_wait_vblank(tdm_private_output *private_output, int interval, int sy if (!func_output->output_wait_vblank) { /* LCOV_EXCL_START */ - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -1041,18 +1063,23 @@ tdm_output_remove_commit_handler(tdm_output *output, tdm_output_commit_handler f INTERN tdm_error tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) { + tdm_private_output *private_output; + tdm_private_backend *private_backend; tdm_func_output *func_output; tdm_private_output_commit_handler *output_commit_handler = NULL; tdm_private_layer *private_layer = NULL; tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_ON; + tdm_error ret = TDM_ERROR_NONE; - OUTPUT_FUNC_ENTRY(); + TDM_RETURN_VAL_IF_FAIL(tdm_output_is_valid(output), TDM_ERROR_INVALID_PARAMETER); - func_output = &private_display->func_output; + private_output = (tdm_private_output*)output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_commit) { /* LCOV_EXCL_START */ - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -1182,6 +1209,7 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, EXTERN tdm_error tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode) { + tdm_private_backend *private_backend; tdm_func_output *func_output; OUTPUT_FUNC_ENTRY(); @@ -1189,12 +1217,13 @@ tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode) _pthread_mutex_lock(&private_display->lock); - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_set_mode) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -1230,6 +1259,7 @@ tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode) EXTERN tdm_error tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) { + tdm_private_backend *private_backend; tdm_func_output *func_output; OUTPUT_FUNC_ENTRY(); @@ -1254,7 +1284,8 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) return TDM_ERROR_BAD_REQUEST; } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; TDM_INFO("output(%d) dpms '%s'", private_output->pipe, tdm_dpms_str(dpms_value)); @@ -1295,6 +1326,7 @@ done: EXTERN tdm_error tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) { + tdm_private_backend *private_backend; tdm_func_output *func_output; OUTPUT_FUNC_ENTRY(); @@ -1324,15 +1356,16 @@ tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) return TDM_ERROR_BAD_REQUEST; } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_set_dpms_handler) { - TDM_ERR("not implemented: output_set_dpms_handler"); + TDM_WRN("not implemented: output_set_dpms_handler"); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NOT_IMPLEMENTED; } if (!func_output->output_set_dpms_async) { - TDM_ERR("not implemented: output_set_dpms_async"); + TDM_WRN("not implemented: output_set_dpms_async"); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NOT_IMPLEMENTED; } @@ -1373,10 +1406,14 @@ tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) INTERN tdm_error tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value) { + tdm_private_output *private_output; + tdm_private_backend *private_backend; tdm_func_output *func_output; - OUTPUT_FUNC_ENTRY(); + tdm_error ret = TDM_ERROR_NONE; - TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(tdm_output_is_valid(output), TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_output*)output; /* TODO: this is ugly. But before calling backend's output_get_dpms(), we have * to check if all backends's DPMS operation has no problem. In future, we'd @@ -1388,7 +1425,8 @@ tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value) return TDM_ERROR_NONE; } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_get_dpms) { /* LCOV_EXCL_START */ @@ -1520,6 +1558,7 @@ EXTERN tdm_error tdm_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types) { + tdm_private_backend *private_backend; tdm_func_output *func_output = NULL; tdm_private_hwc_window **composited_wnds_frontend = NULL; tdm_hwc_window **composited_wnds_backend = NULL; @@ -1537,12 +1576,13 @@ tdm_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds, return TDM_ERROR_BAD_REQUEST; } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_hwc_validate) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -1613,6 +1653,7 @@ tdm_output_hwc_get_changed_composition_types(tdm_output *output, tdm_hwc_window **hwc_window, tdm_hwc_window_composition *composition_types) { + tdm_private_backend *private_backend; tdm_func_output *func_output = NULL; tdm_private_hwc_window * private_hwc_window = NULL; int i = 0; @@ -1629,12 +1670,13 @@ tdm_output_hwc_get_changed_composition_types(tdm_output *output, return TDM_ERROR_BAD_REQUEST; } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_hwc_get_changed_composition_types) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -1678,6 +1720,7 @@ tdm_output_hwc_get_changed_composition_types(tdm_output *output, tdm_error tdm_output_hwc_accept_changes(tdm_output *output) { + tdm_private_backend *private_backend; tdm_func_output *func_output = NULL; OUTPUT_FUNC_ENTRY(); @@ -1690,12 +1733,13 @@ tdm_output_hwc_accept_changes(tdm_output *output) return TDM_ERROR_BAD_REQUEST; } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_hwc_validate) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -1710,6 +1754,7 @@ tdm_output_hwc_accept_changes(tdm_output *output) tbm_surface_queue_h tdm_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error) { + tdm_private_backend *private_backend; tdm_func_output *func_output = NULL; tbm_surface_queue_h queue = NULL; @@ -1725,12 +1770,13 @@ tdm_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error) return NULL; } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_hwc_get_target_buffer_queue) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return NULL; /* LCOV_EXCL_STOP */ } @@ -1745,6 +1791,7 @@ tdm_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error) EXTERN tdm_error tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target_buffer, tdm_hwc_region damage) { + tdm_private_backend *private_backend; tdm_func_output *func_output = NULL; OUTPUT_FUNC_ENTRY(); @@ -1767,12 +1814,13 @@ tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target /* LCOV_EXCL_STOP */ } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_hwc_set_client_target_buffer) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -1787,6 +1835,7 @@ tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target EXTERN tdm_error tdm_output_hwc_unset_client_target_buffer(tdm_output *output) { + tdm_private_backend *private_backend; tdm_func_output *func_output = NULL; OUTPUT_FUNC_ENTRY(); @@ -1799,7 +1848,8 @@ tdm_output_hwc_unset_client_target_buffer(tdm_output *output) return TDM_ERROR_BAD_REQUEST; } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_hwc_unset_client_target_buffer) { /* LCOV_EXCL_START */ @@ -1834,6 +1884,7 @@ _tdm_output_hwc_layer_commit_handler(tdm_layer *layer, unsigned int sequence, tdm_error tdm_output_hwc_commit_client_target_buffer(tdm_output *output, tdm_output_hwc_target_buffer_commit_handler func, void *user_data) { + tdm_private_backend *private_backend; tdm_func_output *func_output; tdm_private_output_hwc_target_buffer_commit_handler *output_hwc_target_buffer_commit_handler; tdm_layer *layer = NULL; @@ -1851,7 +1902,8 @@ tdm_output_hwc_commit_client_target_buffer(tdm_output *output, tdm_output_hwc_ta return TDM_ERROR_BAD_REQUEST; } - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_hwc_get_client_target_buffer_layer) { /* LCOV_EXCL_START */ @@ -1949,6 +2001,7 @@ tdm_error tdm_output_hwc_get_video_supported_formats(tdm_output *output, const tbm_format **formats, int *count) { + tdm_private_backend *private_backend; tdm_func_output *func_output; OUTPUT_FUNC_ENTRY(); @@ -1957,12 +2010,13 @@ tdm_output_hwc_get_video_supported_formats(tdm_output *output, const tbm_format _pthread_mutex_lock(&private_display->lock); - func_output = &private_display->func_output; + private_backend = private_output->private_backend; + func_output = &private_backend->func_output; if (!func_output->output_hwc_get_video_supported_formats) { /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); + TDM_WRN("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; /* LCOV_EXCL_STOP */ } @@ -1978,13 +2032,10 @@ tdm_output_hwc_get_video_supported_formats(tdm_output *output, const tbm_format static int _is_hwc_output_still_existed(tdm_private_output *private_output) { - tdm_private_display *dpy; + tdm_private_backend *private_backend = private_output->private_backend; tdm_private_output *o = NULL; - dpy = tdm_display_init(NULL); - TDM_RETURN_VAL_IF_FAIL(dpy != NULL, TDM_ERROR_OPERATION_FAILED); - - LIST_FOR_EACH_ENTRY(o, &dpy->output_list, link) { + LIST_FOR_EACH_ENTRY(o, &private_backend->output_list, link) { if (!(o->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC)) continue; @@ -1992,11 +2043,9 @@ _is_hwc_output_still_existed(tdm_private_output *private_output) goto exist; } - tdm_display_deinit(dpy); return 0; exist: - tdm_display_deinit(dpy); return 1; } diff --git a/src/tdm_pp.c b/src/tdm_pp.c index 8f4fd8d..cdc0bde 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -40,6 +40,7 @@ #include "tdm_private.h" #define PP_FUNC_ENTRY() \ + tdm_private_backend *private_backend; \ tdm_func_pp *func_pp; \ tdm_private_display *private_display; \ tdm_private_pp *private_pp; \ @@ -47,7 +48,8 @@ TDM_RETURN_VAL_IF_FAIL(pp != NULL, TDM_ERROR_INVALID_PARAMETER); \ private_pp = (tdm_private_pp*)pp; \ private_display = private_pp->private_display; \ - func_pp = &private_display->func_pp + private_backend = private_pp->private_backend; \ + func_pp = &private_backend->func_pp static void _tdm_pp_print_list(struct list_head *list) @@ -178,13 +180,16 @@ _tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, void * static void * _tdm_pp_find_object(tdm_private_display *private_display, double stamp) { + tdm_private_backend *private_backend = NULL; tdm_private_pp *private_pp = NULL; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); - LIST_FOR_EACH_ENTRY(private_pp, &private_display->pp_list, link) { - if (private_pp->stamp == stamp) - return private_pp; + LIST_FOR_EACH_ENTRY(private_backend, &private_display->backend_list, link) { + LIST_FOR_EACH_ENTRY(private_pp, &private_backend->pp_list, link) { + if (private_pp->stamp == stamp) + return private_pp; + } } return NULL; @@ -199,8 +204,9 @@ tdm_pp_init(tdm_private_display *private_display) } INTERN tdm_private_pp * -tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error) +tdm_pp_create_internal(tdm_private_backend *private_backend, tdm_error *error) { + tdm_private_display *private_display; tdm_func_display *func_display; tdm_func_pp *func_pp; tdm_private_pp *private_pp = NULL; @@ -208,20 +214,22 @@ tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error) tdm_error ret = TDM_ERROR_NONE; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); + TDM_RETURN_VAL_IF_FAIL(private_backend != NULL, NULL); - func_display = &private_display->func_display; - func_pp = &private_display->func_pp; + private_display = private_backend->private_display; + func_display = &private_backend->func_display; + func_pp = &private_backend->func_pp; - if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) { + if (!(private_backend->capabilities & TDM_DISPLAY_CAPABILITY_PP)) { /* LCOV_EXCL_START */ - TDM_ERR("no pp capability"); + TDM_ERR("backedn(%s) no pp capability", private_backend->module_data->name); if (error) *error = TDM_ERROR_NO_CAPABILITY; return NULL; /* LCOV_EXCL_STOP */ } - pp_backend = func_display->display_create_pp(private_display->bdata, &ret); + pp_backend = func_display->display_create_pp(private_backend->bdata, &ret); if (ret != TDM_ERROR_NONE) { /* LCOV_EXCL_START */ if (error) @@ -267,8 +275,9 @@ tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error) while (_tdm_pp_find_object(private_display, private_pp->stamp)) private_pp->stamp++; - LIST_ADD(&private_pp->link, &private_display->pp_list); - private_pp->private_display = private_display; + LIST_ADD(&private_pp->link, &private_backend->pp_list); + private_pp->private_display = private_backend->private_display; + private_pp->private_backend = private_backend; private_pp->pp_backend = pp_backend; private_pp->owner_tid = syscall(SYS_gettid); @@ -285,6 +294,7 @@ INTERN void tdm_pp_destroy_internal(tdm_private_pp *private_pp) { tdm_private_display *private_display; + tdm_private_backend *private_backend; tdm_func_pp *func_pp; tdm_pp_private_buffer *b = NULL, *bb = NULL; struct list_head clone_list; @@ -297,7 +307,8 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp) tdm_thread_cb_remove(private_pp, TDM_THREAD_CB_PP_DONE, NULL, _tdm_pp_thread_cb_done, NULL); private_display = private_pp->private_display; - func_pp = &private_display->func_pp; + private_backend = private_pp->private_backend; + func_pp = &private_backend->func_pp; LIST_DEL(&private_pp->link); @@ -457,15 +468,15 @@ tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst) /* LCOV_EXCL_STOP */ } - if (tdm_display_check_module_abi(private_display, 1, 2) && - private_display->caps_pp.max_attach_count > 0) { + if (tdm_backend_check_module_abi(private_backend, 1, 2) && + private_backend->caps_pp.max_attach_count > 0) { /* LCOV_EXCL_START */ int length = LIST_LENGTH(&private_pp->pending_buffer_list) + LIST_LENGTH(&private_pp->buffer_list); - if (length >= private_display->caps_pp.max_attach_count) { + if (length >= private_backend->caps_pp.max_attach_count) { _pthread_mutex_unlock(&private_display->lock); - TDM_DBG("failed: too many attached!! max_attach_count(%d)", - private_display->caps_pp.max_attach_count); + TDM_DBG("failed: backend(%s) too many attached!! max_attach_count(%d)", + private_backend->module_data->name, private_backend->caps_pp.max_attach_count); return TDM_ERROR_BAD_REQUEST; } /* LCOV_EXCL_STOP */ diff --git a/src/tdm_private.h b/src/tdm_private.h index a35aea8..45b1bab 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -88,7 +88,7 @@ tdm_private_display * tdm_display_get(void); int -tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, int abimin); +tdm_backend_check_module_abi(tdm_private_backend *private_backend, int abimaj, int abimin); void * tdm_display_find_output_stamp(tdm_private_display *private_display, double stamp); @@ -166,7 +166,7 @@ tdm_vblank_get_vblank_list_information(tdm_display *dpy, char *reply, int *len); tdm_error tdm_pp_init(tdm_private_display *private_display); tdm_private_pp * -tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error); +tdm_pp_create_internal(tdm_private_backend *private_backend, tdm_error *error); void tdm_pp_destroy_internal(tdm_private_pp *private_pp); @@ -228,7 +228,7 @@ extern int tdm_dump_enable; extern char *tdm_debug_dump_dir; tdm_error -tdm_display_update_output(tdm_private_display *private_display, +tdm_display_update_output(tdm_private_backend *private_backend, tdm_output *output_backend, int pipe); tdm_error tdm_display_enable_debug_module(const char*modules); diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index 77393f1..099dae1 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -96,6 +96,7 @@ typedef enum { TDM_COMMIT_TYPE_LAYER, } tdm_commit_type; +typedef struct _tdm_private_backend tdm_private_backend; typedef struct _tdm_private_display tdm_private_display; typedef struct _tdm_private_output tdm_private_output; typedef struct _tdm_private_layer tdm_private_layer; @@ -114,21 +115,16 @@ typedef struct _tdm_private_output_hwc_target_buffer_window_commit_handler tdm_p typedef struct _tdm_private_layer_buffer tdm_private_layer_buffer; -struct _tdm_private_display { - pthread_mutex_t lock; - unsigned int init_count; +struct _tdm_private_backend { + struct list_head link; - double stamp; + tdm_private_display *private_display; /* backend module info */ void *module; tdm_backend_module *module_data; tdm_backend_data *bdata; -#ifdef INIT_BUFMGR - tbm_bufmgr bufmgr; -#endif - /* backend function */ tdm_display_capability capabilities; tdm_func_display func_display; @@ -148,20 +144,39 @@ struct _tdm_private_display { struct list_head pp_list; struct list_head capture_list; - void **outputs_ptr; + /* backend output objects. allocated in backend. freed in frontend. ordered */ + tdm_output **outputs; + + int fd; + tdm_event_loop_source *event_source; +}; + +struct _tdm_private_display { + pthread_mutex_t lock; + unsigned int init_count; + + double stamp; + +#ifdef INIT_BUFMGR + tbm_bufmgr bufmgr; +#endif + + struct list_head backend_list; + tdm_private_backend *current_backend; //setted only when loading + tdm_private_backend *pp_backend; //pp-support backend + tdm_private_backend *capture_backend; //TODO: remove later /* for event handling */ tdm_private_loop *private_loop; - /* output order */ - tdm_output **outputs; - int print_fps; }; struct _tdm_private_output { struct list_head link; + tdm_private_backend *private_backend; + int index; double stamp; @@ -221,6 +236,8 @@ struct _tdm_private_output { struct _tdm_private_layer { struct list_head link; + tdm_private_backend *private_backend; + int index; tdm_private_display *private_display; @@ -267,6 +284,8 @@ struct _tdm_private_hwc_window { struct _tdm_private_pp { struct list_head link; + tdm_private_backend *private_backend; + double stamp; tdm_private_display *private_display; @@ -287,6 +306,8 @@ struct _tdm_private_capture { struct list_head link; struct list_head display_link; + tdm_private_backend *private_backend; + double stamp; tdm_capture_target target; @@ -320,9 +341,6 @@ struct _tdm_private_loop { struct wl_display *wl_display; struct wl_event_loop *wl_loop; - int backend_fd; - tdm_event_loop_source *backend_source; - /* In event loop, all resources are accessed by this dpy. * CAUTION: * - DO NOT include other private structure in this structure because this diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 12b760d..d0839ba 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -350,7 +350,7 @@ _tdm_vblank_free_HW_wait(tdm_private_vblank *private_vblank, tdm_error error, un pid_t pid; const char *proc_name; _tdm_vblank_get_client_information(private_vblank, &pid, &proc_name); - VER("TDM HW vblank destroyed forcely!! (pid: %u, name: %s)", pid, proc_name); + VWR("TDM HW vblank destroyed forcely!! (pid: %u, name: %s)", pid, proc_name); } LIST_FOR_EACH_ENTRY_SAFE(w, ww, &private_vblank->HW_wait_list, link) { -- 2.7.4 From 9c7adf6d4fe394be239b1b134159c15a5c614bee Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 21 Feb 2018 15:28:25 +0900 Subject: [PATCH 11/16] remove unused file Change-Id: I8c4e786bd29a33d5dad356d517fa137798dfac66 --- 0001-save.patch | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 0001-save.patch diff --git a/0001-save.patch b/0001-save.patch deleted file mode 100644 index 25ad8f0..0000000 --- a/0001-save.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 60fa1ef61f143eb5310588bba987bdfce5d33ad1 Mon Sep 17 00:00:00 2001 -From: Boram Park -Date: Wed, 21 Feb 2018 15:26:17 +0900 -Subject: [PATCH] save - -Change-Id: I5e33d25ad3678f4a77c5ec4396af2b1b45a32488 ---- - include/tdm.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/include/tdm.h b/include/tdm.h -index f4aa8d8..3cae42f 100644 ---- a/include/tdm.h -+++ b/include/tdm.h -@@ -222,10 +222,10 @@ tdm_backend_get_info(tdm_backend *backend, const char **name, - const char **vendor, int *major, int *minor); - - /** -- * @brief Get the capabilities of a output object. -+ * @brief Get a backend object of the given output. - * @param[in] output A output object -- * @param[out] capabilities The capabilities of a output object -- * @return #TDM_ERROR_NONE if success. Otherwise, error value. -+ * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. -+ * @return A backend object if success. Otherwise, NULL. - */ - tdm_backend * - tdm_output_get_backend(tdm_output *output, tdm_error *error); --- -1.9.1 - -- 2.7.4 From d7cab3249db011494da88586a9488de357194b15 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 21 Feb 2018 16:09:04 +0900 Subject: [PATCH 12/16] log: restore stdout when set NULL. Change-Id: I25934b33f8468e55fdd063068f868fafab81f948 --- common/tdm_log.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/common/tdm_log.c b/common/tdm_log.c index 3ddcda1..1befbfb 100644 --- a/common/tdm_log.c +++ b/common/tdm_log.c @@ -69,6 +69,8 @@ static pthread_mutex_t log_lock; unsigned int tdm_log_debug_level = TDM_LOG_LEVEL_INFO; +static int stdout_fd = -1; + EXTERN void tdm_log_enable_color(unsigned int enable) { @@ -105,26 +107,40 @@ tdm_log_set_assert_level(int level) EXTERN void tdm_log_set_path(const char *path) { - char fd_name[TDM_PATH_LEN]; - int log_fd = -1; - FILE *log_fl; + if (!path) { + if (stdout_fd != -1) { + fflush(stdout); + close(STDOUT_FILENO); + dup2(stdout_fd, STDOUT_FILENO); + close(stdout_fd); + stdout_fd = -1; + } + } else { + char fd_name[TDM_PATH_LEN]; + int log_fd = -1; + FILE *log_fl; - snprintf(fd_name, TDM_PATH_LEN, "%s", path); + snprintf(fd_name, TDM_PATH_LEN, "%s", path); - log_fl = fopen(fd_name, "a"); - if (!log_fl) { - TDM_ERR("failed: open file(%s)\n", fd_name); - return; - } + log_fl = fopen(fd_name, "a"); + if (!log_fl) { + TDM_ERR("failed: open file(%s)\n", fd_name); + return; + } - fflush(stdout); - close(STDOUT_FILENO); + if (stdout_fd == -1) { + fflush(stdout); + stdout_fd = dup(STDOUT_FILENO); + TDM_RETURN_IF_FAIL(stdout_fd != -1); + } - setvbuf(log_fl, NULL, _IOLBF, 512); - log_fd = fileno(log_fl); + setvbuf(log_fl, NULL, _IOLBF, 512); + log_fd = fileno(log_fl); - dup2(log_fd, STDOUT_FILENO); - fclose(log_fl); + close(STDOUT_FILENO); + dup2(log_fd, STDOUT_FILENO); + fclose(log_fl); + } } EXTERN void -- 2.7.4 From 65b89e98b7f61add110439f250cceab0e106c4af Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 22 Feb 2018 08:38:55 +0900 Subject: [PATCH 13/16] macro: move backend's name definition Change-Id: I53d086d54b8a9b13f686f91d93d6d543ffe0059e --- src/tdm.c | 4 ---- src/tdm_macro.h | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tdm.c b/src/tdm.c index d744875..3a0ecad 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -682,10 +682,6 @@ tdm_display_update(tdm_display *dpy) return TDM_ERROR_NONE; } -#define SUFFIX_MODULE ".so" -#define TDM_DEFAULT_MODULE "libtdm-default"SUFFIX_MODULE -#define TDM_DUMMY_MODULE "libtdm-dummy"SUFFIX_MODULE - int tdm_debug_module; int tdm_debug_dump; int tdm_ttrace_module; diff --git a/src/tdm_macro.h b/src/tdm_macro.h index 5d41886..88dc034 100644 --- a/src/tdm_macro.h +++ b/src/tdm_macro.h @@ -83,6 +83,10 @@ extern "C" { } \ } while (0) +/* common backend names *****************************************************/ +#define TDM_DEFAULT_MODULE "libtdm-default.so" +#define TDM_DUMMY_MODULE "libtdm-dummy.so" + /* dump directory ***********************************************************/ #define TDM_DUMP_DIR "/tmp" -- 2.7.4 From 3e00a0eecd370289ff30426836f50c1e7874566e Mon Sep 17 00:00:00 2001 From: Boram Park Date: Thu, 22 Feb 2018 14:02:51 +0900 Subject: [PATCH 14/16] thread: use two lists for each thread When tdm_thread_call_cb is called in both threads at the same time, the 'called' variable makes a thread issue. 1) Calling tdm_thread_call_cb in display-thread makes the 'called' variable as 1 2) Calling tdm_thread_call_cb in tdm-thread at the same time checks cb->called. 3) Because cb->called is 1 by display-thread, tdm_thread_call_cb in tdm-thread does nothing. Change-Id: I009e3a17b40d32502f3567b8ecd712fa7c8dc349 --- src/tdm_thread.c | 119 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 82 insertions(+), 37 deletions(-) diff --git a/src/tdm_thread.c b/src/tdm_thread.c index 30966b4..6058bb3 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -69,11 +69,13 @@ typedef struct _tdm_private_thread_cb { void *user_data; pid_t owner_tid; - unsigned int called; } tdm_private_thread_cb; static tdm_thread_find_object find_funcs[TDM_THREAD_CB_MAX] = {0, }; -static struct list_head cb_list; + +/* 0: for display thread, 1: for tdm thread */ +static struct list_head cb_list[2]; +static pthread_mutex_t cb_list_lock; static void _tdm_thread_free_cb(tdm_private_thread_cb *cb); @@ -193,13 +195,19 @@ tdm_thread_init(tdm_private_loop *private_loop) private_display = private_loop->dpy; TDM_RETURN_VAL_IF_FAIL(private_display->private_loop, TDM_ERROR_OPERATION_FAILED); + if (private_loop->private_thread) + return TDM_ERROR_NONE; + for (i = 0; i < TDM_THREAD_CB_MAX; i++) find_funcs[i] = NULL; - LIST_INITHEAD(&cb_list); + if (pthread_mutex_init(&cb_list_lock, NULL)) { + TDM_ERR("mutex init failed: %m"); + return TDM_ERROR_OUT_OF_MEMORY; + } - if (private_loop->private_thread) - return TDM_ERROR_NONE; + LIST_INITHEAD(&cb_list[0]); + LIST_INITHEAD(&cb_list[1]); /* enable as default */ thread = tdm_config_get_int(TDM_CONFIG_KEY_GENERAL_THREAD, 1); @@ -291,7 +299,12 @@ tdm_thread_deinit(tdm_private_loop *private_loop) tdm_log_reset(); - LIST_FOR_EACH_ENTRY_SAFE(cb, hh, &cb_list, link) { + pthread_mutex_destroy(&cb_list_lock); + + LIST_FOR_EACH_ENTRY_SAFE(cb, hh, &cb_list[0], link) { + _tdm_thread_free_cb(cb); + } + LIST_FOR_EACH_ENTRY_SAFE(cb, hh, &cb_list[1], link) { _tdm_thread_free_cb(cb); } @@ -358,7 +371,7 @@ tdm_thread_send_cb(tdm_private_loop *private_loop, tdm_thread_cb_base *base) pipe = private_thread->pipe[1]; if (tdm_debug_module & TDM_DEBUG_THREAD) - TDM_INFO("fd(%d) type(%d), length(%d)", pipe, base->type, base->length); + TDM_INFO("fd(%d) type(%s), length(%d)", pipe, tdm_cb_type_str(base->type), base->length); len = write(pipe, base, base->length); if (len != base->length) { @@ -419,7 +432,7 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) while (i < len) { base = (tdm_thread_cb_base*)&buffer[i]; if (tdm_debug_module & TDM_DEBUG_THREAD) - TDM_INFO("type(%d), length(%d)", base->type, base->length); + TDM_INFO("type(%s), length(%d)", tdm_cb_type_str(base->type), base->length); switch (base->type) { case TDM_THREAD_CB_OUTPUT_COMMIT: case TDM_THREAD_CB_OUTPUT_VBLANK: @@ -472,34 +485,24 @@ _tdm_thread_free_cb(tdm_private_thread_cb *cb) } static tdm_private_thread_cb * -_tdm_thread_find_cb(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_thread_cb func, void *user_data, pid_t owner_tid) +_tdm_thread_find_cb(struct list_head *list, void *object, tdm_thread_cb_type cb_type, + void *cb_data, tdm_thread_cb func, void *user_data, pid_t caller_tid) { tdm_private_thread_cb *cb = NULL; - LIST_FOR_EACH_ENTRY(cb, &cb_list, link) { + LIST_FOR_EACH_ENTRY(cb, list, link) { if (cb->object == object && cb->cb_type == cb_type && cb->cb_data == cb_data && cb->func == func && cb->user_data == user_data && - cb->owner_tid == owner_tid) + cb->owner_tid == caller_tid) return cb; } return NULL; } -static void -_tdm_thread_reset_cb(tdm_thread_cb_type cb_type) -{ - tdm_private_thread_cb *cb = NULL; - - LIST_FOR_EACH_ENTRY(cb, &cb_list, link) { - if (cb->cb_type == cb_type) - cb->called = 0; - } -} - INTERN void tdm_thread_cb_set_find_func(tdm_thread_cb_type cb_type, tdm_thread_find_object func) { @@ -516,6 +519,7 @@ tdm_thread_cb_add(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_t { tdm_private_thread_cb *cb = NULL; pid_t caller_tid; + struct list_head *list; TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(object != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -524,8 +528,16 @@ tdm_thread_cb_add(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_t caller_tid = syscall(SYS_gettid); - cb = _tdm_thread_find_cb(object, cb_type, cb_data, func, user_data, caller_tid); + pthread_mutex_lock(&cb_list_lock); + + if (tdm_thread_in_display_thread(caller_tid)) + list = &cb_list[0]; + else + list = &cb_list[1]; + + cb = _tdm_thread_find_cb(list, object, cb_type, cb_data, func, user_data, caller_tid); if (cb) { + pthread_mutex_unlock(&cb_list_lock); TDM_ERR("can't be added twice with same data"); #if 1 assert(0); @@ -535,11 +547,12 @@ tdm_thread_cb_add(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_t cb = calloc(1, sizeof *cb); if (!cb) { + pthread_mutex_unlock(&cb_list_lock); TDM_ERR("calloc failed"); return TDM_ERROR_OUT_OF_MEMORY; } - LIST_ADDTAIL(&cb->link, &cb_list); + LIST_ADDTAIL(&cb->link, list); LIST_INITHEAD(&cb->call_link); cb->object = object; @@ -550,7 +563,9 @@ tdm_thread_cb_add(void *object, tdm_thread_cb_type cb_type, void *cb_data, tdm_t cb->owner_tid = caller_tid; if (tdm_debug_module & TDM_DEBUG_THREAD) - TDM_INFO("cb_type(%d) cb(%p) added", cb_type, cb); + TDM_INFO("cb_type(%s) cb(%p) added", tdm_cb_type_str(cb_type), cb); + + pthread_mutex_unlock(&cb_list_lock); return TDM_ERROR_NONE; } @@ -560,6 +575,7 @@ tdm_thread_cb_remove(void *object, tdm_thread_cb_type cb_type, void *cb_data, td { tdm_private_thread_cb *cb; pid_t caller_tid; + struct list_head *list; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); TDM_RETURN_IF_FAIL(object != NULL); @@ -568,11 +584,21 @@ tdm_thread_cb_remove(void *object, tdm_thread_cb_type cb_type, void *cb_data, td caller_tid = syscall(SYS_gettid); - cb = _tdm_thread_find_cb(object, cb_type, cb_data, func, user_data, caller_tid); - if (!cb) + pthread_mutex_lock(&cb_list_lock); + + if (tdm_thread_in_display_thread(caller_tid)) + list = &cb_list[0]; + else + list = &cb_list[1]; + + cb = _tdm_thread_find_cb(list, object, cb_type, cb_data, func, user_data, caller_tid); + if (!cb) { + pthread_mutex_unlock(&cb_list_lock); return; + } _tdm_thread_free_cb(cb); + pthread_mutex_unlock(&cb_list_lock); } /* when call a callback, we check both cb_base's type and cb_base's data, @@ -585,6 +611,7 @@ tdm_thread_cb_call(void *object, tdm_thread_cb_base *cb_base) tdm_private_thread_cb *cb = NULL, *hh = NULL; int handler_in_other_thread = 0; pid_t caller_tid; + struct list_head *list, *other_list; struct list_head call_list; tdm_error ret; @@ -607,35 +634,53 @@ tdm_thread_cb_call(void *object, tdm_thread_cb_base *cb_base) } } + pthread_mutex_lock(&cb_list_lock); + + if (tdm_thread_in_display_thread(caller_tid)) { + list = &cb_list[0]; + other_list = &cb_list[1]; + } else { + other_list = &cb_list[0]; + list = &cb_list[1]; + } + LIST_INITHEAD(&call_list); - LIST_FOR_EACH_ENTRY_SAFE(cb, hh, &cb_list, link) { - if (cb->called || - cb->object != object || + LIST_FOR_EACH_ENTRY_SAFE(cb, hh, list, link) { + if (cb->object != object || cb->cb_type != cb_base->type || cb->cb_data != cb_base->data) continue; - if (cb->owner_tid == caller_tid) - LIST_ADDTAIL(&cb->call_link, &call_list); - else - handler_in_other_thread = 1; + LIST_ADDTAIL(&cb->call_link, &call_list); } if (!LIST_IS_EMPTY(&call_list)) { LIST_FOR_EACH_ENTRY_SAFE(cb, hh, &call_list, call_link) { LIST_DELINIT(&cb->call_link); - cb->called = 1; if (tdm_debug_module & TDM_DEBUG_THREAD) - TDM_INFO("cb_type(%d) cb(%p) called", cb->cb_type, cb); + TDM_INFO("cb_type(%s) cb(%p) calling", tdm_cb_type_str(cb->cb_type), cb); + pthread_mutex_unlock(&cb_list_lock); cb->func(private_display, cb->object, cb_base, cb->user_data); + pthread_mutex_lock(&cb_list_lock); } } + pthread_mutex_unlock(&cb_list_lock); + assert(LIST_IS_EMPTY(&call_list)); + LIST_FOR_EACH_ENTRY_SAFE(cb, hh, other_list, link) { + if (cb->object != object || + cb->cb_type != cb_base->type || + cb->cb_data != cb_base->data) + continue; + + handler_in_other_thread = 1; + break; + } + if (!handler_in_other_thread) { - _tdm_thread_reset_cb(cb_base->type); if (keep_private_thread) { if (cb_base->sync) { pthread_cond_signal(&keep_private_thread->event_cond); -- 2.7.4 From db5780af098f675d9c7105ce26ebcb8cedb38937 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 23 Feb 2018 07:50:21 +0900 Subject: [PATCH 15/16] layer: correct error type Change-Id: I6bc89d04588ac3f94ed129943a0be12b94fd6fb0 --- src/tdm_layer.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tdm_layer.c b/src/tdm_layer.c index 3afebd1..1f757ee 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -1115,8 +1115,6 @@ tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error) if (private_layer->showing_buffer) { buffer = private_layer->showing_buffer->buffer; } else { - if (error) - *error = TDM_ERROR_OPERATION_FAILED; _pthread_mutex_unlock(&private_display->lock); TDM_DBG("layer(%p) showing_buffer is null", private_layer); return NULL; @@ -1313,7 +1311,7 @@ tdm_layer_set_video_pos(tdm_layer *layer, int zpos) if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) { TDM_ERR("layer(%p) is not video layer", private_layer); _pthread_mutex_unlock(&private_display->lock); - return TDM_ERROR_INVALID_PARAMETER; + return TDM_ERROR_BAD_REQUEST; } if (!func_layer->layer_set_video_pos) { -- 2.7.4 From fa0b43c5a0a3a5a81b27e8e36fb6ccc29159214c Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 23 Feb 2018 07:51:29 +0900 Subject: [PATCH 16/16] layer: correct set_buffer_queue behavior Change-Id: I7d72456f54ed91b392799918727886d8520e6b9f --- src/tdm_layer.c | 51 ++++++++++++++++----------------------------------- 1 file changed, 16 insertions(+), 35 deletions(-) diff --git a/src/tdm_layer.c b/src/tdm_layer.c index 1f757ee..79c7c2f 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -1131,7 +1131,7 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) tdm_layer *layer = data; tdm_private_backend *private_backend; tdm_func_layer *func_layer; - tbm_surface_h surface = NULL; + tbm_surface_h buffer = NULL; tdm_private_layer_buffer *layer_buffer; LAYER_FUNC_ENTRY_VOID_RETURN(); @@ -1157,49 +1157,30 @@ _tbm_layer_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data) } LIST_INITHEAD(&layer_buffer->link); - if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &surface) || - surface == NULL) { + if (TBM_SURFACE_QUEUE_ERROR_NONE != tbm_surface_queue_acquire(private_layer->buffer_queue, &buffer) || + buffer == NULL) { /* LCOV_EXCL_START */ TDM_ERR("layer(%p) tbm_surface_queue_acquire() failed surface:%p", - private_layer, surface); + private_layer, buffer); _pthread_mutex_unlock(&private_display->lock); free(layer_buffer); return; /* LCOV_EXCL_STOP */ } - /* we don't need to handle pending data here because the changes in this function - * should be applied immediately. we can't expect calling tdm_layer_commit. - */ - ret = func_layer->layer_set_buffer(private_layer->layer_backend, surface); - TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - - if (ret == TDM_ERROR_NONE) { - if (private_layer->waiting_buffer) { - TDM_DBG("layer(%p) drop waiting_buffer(%p)", private_layer, private_layer->waiting_buffer->buffer); - _tdm_layer_free_buffer(private_layer, private_layer->waiting_buffer); - } - - private_layer->waiting_buffer = layer_buffer; - private_layer->waiting_buffer->buffer = tdm_buffer_ref_backend(surface); - - if (tdm_debug_module & TDM_DEBUG_BUFFER) - TDM_INFO("layer(%p) waiting_buffer(%p)", - private_layer, private_layer->waiting_buffer->buffer); + ret = tdm_layer_set_buffer_internal(private_layer, buffer); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("tdm_layer_set_buffer_internal failed"); + _pthread_mutex_unlock(&private_display->lock); + return; + } - if (private_output->commit_type == TDM_COMMIT_TYPE_OUTPUT) { - ret = tdm_output_commit_internal(private_layer->private_output, 0, NULL, NULL); - if (ret != TDM_ERROR_NONE) - TDM_ERR("tdm_output_commit_internal() is fail"); - } else if (private_output->commit_type == TDM_COMMIT_TYPE_LAYER) { - ret = _tdm_layer_commit(private_layer, NULL, NULL); - if (ret != TDM_ERROR_NONE) - TDM_ERR("layer(%p) _tdm_layer_commit() is fail", private_layer); - } else { - TDM_NEVER_GET_HERE(); - } - } else - _tdm_layer_free_buffer(private_layer, layer_buffer); + ret = tdm_layer_commit_internal(private_layer, NULL, NULL); + if (ret != TDM_ERROR_NONE) { + TDM_ERR("tdm_layer_commit_internal failed"); + _pthread_mutex_unlock(&private_display->lock); + return; + } _pthread_mutex_unlock(&private_display->lock); } -- 2.7.4