From 805e6f0b8f83dabebb8eb0ee21bad9e131dd33bb Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 23 Feb 2018 15:39:09 +0900 Subject: [PATCH 01/16] vblank: add tdm_vblank_get_output Change-Id: Ibad717742bb0ebe8ad7b92926c1b48bdc3fc37ac --- include/tdm.h | 10 ++++++++++ src/tdm_vblank.c | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/tdm.h b/include/tdm.h index 6bc822f..9ae31a3 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -1350,6 +1350,16 @@ void tdm_vblank_destroy(tdm_vblank *vblank); /** + * @brief Get a output object of a vblank object + * @param[in] vblank A vblank object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A TDM output object if success. Otherwise, NULL. + * @see #tdm_vblank_create + */ +tdm_output * +tdm_vblank_get_output(tdm_vblank *vblank, tdm_error *error); + +/** * @brief Get the client PID for a vblank object * @param[in] vblank A vblank object * @param[out] pid PID of vblank's client diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index d0839ba..e1ba393 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -827,6 +827,20 @@ tdm_vblank_destroy(tdm_vblank *vblank) free(private_vblank); } +EXTERN tdm_output * +tdm_vblank_get_output(tdm_vblank *vblank, tdm_error *error) +{ + tdm_private_vblank *private_vblank = vblank; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(tdm_vblank_is_valid(vblank), TDM_ERROR_INVALID_PARAMETER, NULL); + + if (error) + *error = TDM_ERROR_NONE; + + return private_vblank->output; +} + EXTERN tdm_error tdm_vblank_get_client_pid(tdm_vblank *vblank, pid_t *pid) { -- 2.7.4 From 32e7f092e18e34a5ff3d3b716757b3de57b6cb02 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 23 Feb 2018 15:40:24 +0900 Subject: [PATCH 02/16] vblank: correct printf format Change-Id: I088fd0ce9acef399f8f0ff03de80da76f4fbe3a3 --- src/tdm_vblank.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index e1ba393..7a5ea17 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -906,7 +906,7 @@ tdm_vblank_set_fps(tdm_vblank *vblank, unsigned int fps) TDM_RETURN_VAL_IF_FAIL(fps > 0, TDM_ERROR_INVALID_PARAMETER); if (private_vblank->fps_fixed) { - VIN("fps(%d) can't be changed", private_vblank->fps); + VIN("fps(%u) can't be changed", private_vblank->fps); return TDM_ERROR_NONE; } @@ -918,7 +918,7 @@ tdm_vblank_set_fps(tdm_vblank *vblank, unsigned int fps) private_vblank->fps = fps; private_vblank->check_HW_or_SW = 1; - VIN("fps(%d) changed", fps); + VIN("fps(%u) changed", fps); return TDM_ERROR_NONE; } @@ -953,7 +953,7 @@ tdm_vblank_set_fixed_fps(tdm_vblank *vblank, unsigned int fps) private_vblank->fps = fps; private_vblank->check_HW_or_SW = 1; - VIN("fps(%d) fixed", fps); + VIN("fps(%u) fixed", fps); return TDM_ERROR_NONE; } @@ -971,7 +971,7 @@ tdm_vblank_ignore_global_fps(tdm_vblank *vblank, unsigned int ignore) private_vblank->ignore_global_fps = ignore; private_vblank->check_HW_or_SW = 1; - VIN("ignore_global_fps(%d)", private_vblank->ignore_global_fps); + VIN("ignore_global_fps(%u)", private_vblank->ignore_global_fps); return TDM_ERROR_NONE; } @@ -989,7 +989,7 @@ tdm_vblank_set_offset(tdm_vblank *vblank, int offset) private_vblank->offset = offset; private_vblank->check_HW_or_SW = 1; - VIN("offset(%d)", private_vblank->offset); + VIN("offset(%u)", private_vblank->offset); return TDM_ERROR_NONE; } @@ -1019,7 +1019,7 @@ tdm_vblank_set_enable_fake(tdm_vblank *vblank, unsigned int enable_fake) private_vblank->enable_fake = enable_fake; - VIN("enable_fake(%d)", private_vblank->enable_fake); + VIN("enable_fake(%u)", private_vblank->enable_fake); return TDM_ERROR_NONE; } -- 2.7.4 From 560cea62117a61fc76b9b3c2efe1293390f4447e Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 23 Feb 2018 15:43:18 +0900 Subject: [PATCH 03/16] protect a handler list with mutex Change-Id: I120a0fbf28cdf64f81318dc7f6c544b994c4662a --- src/tdm_vblank.c | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 7a5ea17..19c8024 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -158,10 +158,10 @@ typedef struct _tdm_vblank_create_handler_info { void *user_data; } tdm_vblank_create_handler_info; -/* valid_vblank_list and valid_wait_list should be protected by valid_list_lock because - * tdm_vblank can be used in multi-thread. +/* valid_vblank_list, valid_wait_list and create_handler_list should be protected + * by valid_list_lock because tdm_vblank can be used in multi-thread. */ -static pthread_mutex_t valid_list_lock; +static pthread_mutex_t valid_list_lock = PTHREAD_MUTEX_INITIALIZER; static struct list_head valid_vblank_list; static struct list_head valid_wait_list; static struct list_head create_handler_list; @@ -576,9 +576,10 @@ _tdm_vblank_thread_cb_create(tdm_private_display *private_display, void *object, return; } - /* use in_create_handler instead of mutext unlock/lock */ private_vblank->in_create_handler = 1; + tdm_display_unlock(private_display); ch_info->func(private_vblank, ch_info->user_data); + tdm_display_lock(private_display); private_vblank->in_create_handler = 0; } @@ -608,18 +609,25 @@ tdm_vblank_add_create_handler(tdm_display *dpy, tdm_vblank_create_handler func, 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(dpy != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + pthread_mutex_lock(&valid_list_lock); + 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"); + pthread_mutex_unlock(&valid_list_lock); 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); + if (!ch_info) { + TDM_ERR("alloc failed: %m"); + pthread_mutex_unlock(&valid_list_lock); + return 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); @@ -628,6 +636,7 @@ tdm_vblank_add_create_handler(tdm_display *dpy, tdm_vblank_create_handler func, if (ret != TDM_ERROR_NONE) { TDM_ERR("tdm_thread_cb_add failed"); free(ch_info); + pthread_mutex_unlock(&valid_list_lock); return ret; } @@ -635,6 +644,9 @@ tdm_vblank_add_create_handler(tdm_display *dpy, tdm_vblank_create_handler func, ch_info->user_data = user_data; LIST_ADDTAIL(&ch_info->link, &create_handler_list); + + pthread_mutex_unlock(&valid_list_lock); + return TDM_ERROR_NONE; } @@ -643,31 +655,24 @@ 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. - */ - if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) { - TDM_ERR("remove_create_handler should be called in main thread"); - return; - } + TDM_RETURN_IF_FAIL(dpy != NULL); + TDM_RETURN_IF_FAIL(func != NULL); tdm_display_lock(dpy); - + pthread_mutex_lock(&valid_list_lock); LIST_FOR_EACH_ENTRY_SAFE(ch_info, hh, &create_handler_list, link) { - if (ch_info->func != func && ch_info->user_data != user_data) + 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); + pthread_mutex_unlock(&valid_list_lock); tdm_display_unlock(dpy); return; } - + pthread_mutex_unlock(&valid_list_lock); tdm_display_unlock(dpy); } @@ -683,11 +688,6 @@ tdm_vblank_init(tdm_display *dpy) if (vblank_list_inited) return TDM_ERROR_NONE; - if (pthread_mutex_init(&valid_list_lock, NULL)) { - TDM_ERR("mutex init failed: %m"); - return TDM_ERROR_OUT_OF_MEMORY; - } - LIST_INITHEAD(&valid_vblank_list); LIST_INITHEAD(&valid_wait_list); LIST_INITHEAD(&create_handler_list); @@ -719,8 +719,6 @@ tdm_vblank_deinit(tdm_display *dpy) free(ch_info); } - pthread_mutex_destroy(&valid_list_lock); - vblank_list_inited = 0; } -- 2.7.4 From cab550f4c6f7ec04ab467c4f4eb3748ca76516fb Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 07:53:13 +0900 Subject: [PATCH 04/16] layer: correct return type TDM_ERROR_NONE seems right because flags is set to 0 as default Change-Id: I351454370b6e001ec1ba3ee1cccd514e1d6df908 --- src/tdm_layer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tdm_layer.c b/src/tdm_layer.c index d22a1de..97e2a09 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -1343,8 +1343,8 @@ tdm_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags) /* LCOV_EXCL_START */ *flags = 0; _pthread_mutex_unlock(&private_display->lock); - TDM_ERR("not implemented!!"); - return TDM_ERROR_NOT_IMPLEMENTED; + TDM_INFO("not implemented!!"); + return TDM_ERROR_NONE; /* LCOV_EXCL_STOP */ } -- 2.7.4 From ef18118167edd6af1e63f4c60cea17eba73d23e9 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 07:53:47 +0900 Subject: [PATCH 05/16] log: add return char only in case of stdout Change-Id: Ia87ae3a1fdceec67d93280f3e238092f544bc851 --- common/tdm_log.c | 2 +- include/tdm_log.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/tdm_log.c b/common/tdm_log.c index aa68703..6e4c517 100644 --- a/common/tdm_log.c +++ b/common/tdm_log.c @@ -192,7 +192,7 @@ tdm_log_print(int level, const char *fmt, ...) va_start(arg, fmt); vprintf(fmt, arg); va_end(arg); - + printf("\n"); pthread_mutex_unlock(&log_lock); } diff --git a/include/tdm_log.h b/include/tdm_log.h index 880ffe8..b653aa2 100644 --- a/include/tdm_log.h +++ b/include/tdm_log.h @@ -80,7 +80,7 @@ extern unsigned int tdm_log_debug_level; if (tdm_log_debug_level >= TDM_LOG_LEVEL_DBG) { \ struct timespec ts; \ clock_gettime(CLOCK_MONOTONIC, &ts); \ - tdm_log_print(TDM_LOG_LEVEL_DBG, "[%5d.%06d][%d][%s %d]"fmt"\n", \ + tdm_log_print(TDM_LOG_LEVEL_DBG, "[%5d.%06d][%d][%s %d]"fmt, \ (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ } \ @@ -90,7 +90,7 @@ extern unsigned int tdm_log_debug_level; if (tdm_log_debug_level >= TDM_LOG_LEVEL_INFO) { \ struct timespec ts; \ clock_gettime(CLOCK_MONOTONIC, &ts); \ - tdm_log_print(TDM_LOG_LEVEL_INFO, "[%5d.%06d][%d][%s %d]"fmt"\n", \ + tdm_log_print(TDM_LOG_LEVEL_INFO, "[%5d.%06d][%d][%s %d]"fmt, \ (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ } \ @@ -100,7 +100,7 @@ extern unsigned int tdm_log_debug_level; if (tdm_log_debug_level >= TDM_LOG_LEVEL_WRN) { \ struct timespec ts; \ clock_gettime(CLOCK_MONOTONIC, &ts); \ - tdm_log_print(TDM_LOG_LEVEL_WRN, "[%5d.%06d][%d][%s %d]"fmt"\n", \ + tdm_log_print(TDM_LOG_LEVEL_WRN, "[%5d.%06d][%d][%s %d]"fmt, \ (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ } \ @@ -110,7 +110,7 @@ extern unsigned int tdm_log_debug_level; if (tdm_log_debug_level >= TDM_LOG_LEVEL_ERR) { \ struct timespec ts; \ clock_gettime(CLOCK_MONOTONIC, &ts); \ - tdm_log_print(TDM_LOG_LEVEL_ERR, "[%5d.%06d][%d][%s %d]"fmt"\n", \ + tdm_log_print(TDM_LOG_LEVEL_ERR, "[%5d.%06d][%d][%s %d]"fmt, \ (int)ts.tv_sec, (int)ts.tv_nsec / 1000, \ (int)syscall(SYS_gettid), __FUNCTION__, __LINE__, ##args); \ } \ -- 2.7.4 From 032f074f78e191b2b29156cd4eddd90ce6f8dc36 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 07:53:57 +0900 Subject: [PATCH 06/16] log: TDM_DEBUG env for debugging Change-Id: I820e71c3dbb27fd6d7b5677f4c295c55367711e3 --- common/tdm_log.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/tdm_log.c b/common/tdm_log.c index 6e4c517..996618d 100644 --- a/common/tdm_log.c +++ b/common/tdm_log.c @@ -157,6 +157,9 @@ tdm_log_print(int level, const char *fmt, ...) if (level > tdm_log_debug_level) return; + if (getenv("TDM_DEBUG")) + dlog_enable = 0; + if (dlog_enable) { log_priority dlog_prio; switch (level) { -- 2.7.4 From f20eb3ddc99ffb1e7ce4540b44cd7796149d3569 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 07:54:12 +0900 Subject: [PATCH 07/16] macro: add tdm_capture_type_str Change-Id: Ie5674d055852a98e95306c1573432162704f2191 --- src/tdm_macro.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tdm_macro.h b/src/tdm_macro.h index 88dc034..e681337 100644 --- a/src/tdm_macro.h +++ b/src/tdm_macro.h @@ -212,6 +212,12 @@ static struct tdm_type_name tdm_conn_names[] = { }; TDM_TYPE_NAME_FN(conn) +static struct tdm_type_name tdm_capture_type_names[] = { + { TDM_CAPTURE_TYPE_ONESHOT, "none" }, + { TDM_CAPTURE_TYPE_STREAM, "90" }, +}; +TDM_TYPE_NAME_FN(capture_type) + static struct tdm_type_name tdm_transform_names[] = { { TDM_TRANSFORM_NORMAL, "none" }, { TDM_TRANSFORM_90, "90" }, -- 2.7.4 From 55b52e7511e2c626e7d4845d4954477ba01314ad Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 07:54:28 +0900 Subject: [PATCH 08/16] vblank: interval should be greater than 0 Change-Id: I69108d7b81fd14f22d6e9f5d7fecfcf28dd3623e --- src/tdm_vblank.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 19c8024..0362d4e 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -1482,6 +1482,7 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, TDM_RETURN_VAL_IF_FAIL(tdm_vblank_is_valid(vblank), TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(interval > 0, TDM_ERROR_INVALID_PARAMETER); if (private_vblank->in_create_handler) { TDM_ERR("NOT allowed to be called in a create handler"); -- 2.7.4 From 45a49594922e43688725291a2812bc85d8eacf1d Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 08:30:24 +0900 Subject: [PATCH 09/16] vblank: offset should be greater than 0 Change-Id: Iee03c0b17b51f8a35c844b5d4f6581ada167d8eb --- src/tdm_vblank.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 0362d4e..bdcad07 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -980,6 +980,7 @@ tdm_vblank_set_offset(tdm_vblank *vblank, int offset) tdm_private_vblank *private_vblank = vblank; TDM_RETURN_VAL_IF_FAIL(tdm_vblank_is_valid(vblank), TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(offset >= 0, TDM_ERROR_INVALID_PARAMETER); if (private_vblank->offset == offset) return TDM_ERROR_NONE; -- 2.7.4 From e35043ff090352d36288507768d0b981e42c2b49 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 07:55:23 +0900 Subject: [PATCH 10/16] output: update caps only in case of changing status between connection and disconnection Change-Id: I63126a368331b494b3a4aa9c17a7e2abbc75a058 --- src/tdm.c | 74 +++++++++++++++++++------------------------------------ src/tdm_output.c | 27 +++++++++----------- src/tdm_private.h | 2 +- 3 files changed, 37 insertions(+), 66 deletions(-) diff --git a/src/tdm.c b/src/tdm.c index 3a0ecad..6b796ea 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -375,32 +375,27 @@ _tdm_display_update_layer(tdm_private_output *private_output, TDM_RETURN_VAL_IF_FAIL(private_layer != NULL, TDM_ERROR_OUT_OF_MEMORY); LIST_ADDTAIL(&private_layer->link, &private_output->layer_list); + LIST_INITHEAD(&private_layer->capture_list); + private_layer->index = index; 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; - - LIST_INITHEAD(&private_layer->capture_list); - private_layer->usable = 1; - } else - _tdm_display_destroy_caps_layer(&private_layer->caps); + } - ret = _tdm_display_update_caps_layer(private_layer->private_backend, layer_backend, - &private_layer->caps); - if (ret != TDM_ERROR_NONE) - goto failed_update; + _tdm_display_destroy_caps_layer(&private_layer->caps); + + ret = _tdm_display_update_caps_layer(private_output->private_backend, layer_backend, &private_layer->caps); + TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); return TDM_ERROR_NONE; -failed_update: - _tdm_display_destroy_private_layer(private_layer); - return ret; } INTERN tdm_error tdm_display_update_output(tdm_private_backend *private_backend, - tdm_output *output_backend, int pipe) + tdm_output *output_backend, int pipe, unsigned int need_new_caps) { tdm_func_output *func_output = &private_backend->func_output; tdm_private_output *private_output = NULL; @@ -441,54 +436,35 @@ tdm_display_update_output(tdm_private_backend *private_backend, private_output); private_output->regist_change_cb = 1; } + } - 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_backend, pipe, output_backend, - &new_caps); - if (ret != TDM_ERROR_NONE) - return ret; + /* need_new_caps will be true only in case of "disconnected -> connected" and "connected -> disconnected" + * because we have to get new modes. + */ + if (need_new_caps) { + _tdm_display_destroy_caps_output(&private_output->caps); - /* FIXME: This is very ugly. need to fix after the TDM ABI is changed. */ - if (private_output->caps.status != new_caps.status) { - _tdm_display_destroy_caps_output(&private_output->caps); - private_output->caps = new_caps; - private_output->current_mode = NULL; - } else { - tdm_output_mode *old_modes = private_output->caps.modes; - unsigned int old_mode_count = private_output->caps.mode_count; - if (new_caps.modes) - free(new_caps.modes); - new_caps.modes = old_modes; - new_caps.mode_count = old_mode_count; - if (private_output->caps.props) - free(private_output->caps.props); - private_output->caps = new_caps; - } + ret = _tdm_display_update_caps_output(private_backend, pipe, output_backend, &private_output->caps); + TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret); } layers = func_output->output_get_layers(output_backend, &layer_count, &ret); - if (ret != TDM_ERROR_NONE) - goto failed_update; + if (ret != TDM_ERROR_NONE) { + free(layers); + return ret; + } for (i = 0; i < layer_count; i++) { ret = _tdm_display_update_layer(private_output, layers[i], i); - if (ret != TDM_ERROR_NONE) - goto failed_update; + if (ret != TDM_ERROR_NONE) { + free(layers); + return ret; + } } free(layers); return TDM_ERROR_NONE; -failed_update: - _tdm_display_destroy_private_output(private_output); - free(layers); - return ret; } static tdm_output ** @@ -657,7 +633,7 @@ _tdm_display_update(tdm_private_display *private_display) goto failed_update; for (i = 0; i < output_count; i++) { - ret = tdm_display_update_output(private_backend, outputs[i], index++); + ret = tdm_display_update_output(private_backend, outputs[i], index++, 1); if (ret != TDM_ERROR_NONE) goto failed_update; } diff --git a/src/tdm_output.c b/src/tdm_output.c index ed860d3..115cb9d 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -222,20 +222,6 @@ tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status) return ret; } -/* LCOV_EXCL_START */ -static void -_tdm_output_update(tdm_output *output_backend, void *user_data) -{ - tdm_private_output *private_output = user_data; - tdm_error ret; - - TDM_RETURN_IF_FAIL(private_output); - - 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 */ - INTERN void tdm_output_thread_cb_change(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data) { @@ -280,9 +266,17 @@ tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, tdm_value value; tdm_error ret; - TDM_INFO("output(%d) main %s", private_output->pipe, tdm_status_str(status)); + TDM_RETURN_IF_FAIL(private_output); - _tdm_output_update(output_backend, user_data); + TDM_INFO("output(%d) %s", private_output->pipe, tdm_status_str(status)); + + if ((private_output->caps.status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) || + (private_output->caps.status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)) { + ret = tdm_display_update_output(private_output->private_backend, output_backend, private_output->pipe, 1); + TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + } else { + private_output->caps.status = status; + } value.u32 = status; @@ -954,6 +948,7 @@ tdm_output_wait_vblank(tdm_output *output, int interval, int sync, tdm_output_vblank_handler func, void *user_data) { OUTPUT_FUNC_ENTRY(); + TDM_RETURN_VAL_IF_FAIL(interval > 0, TDM_ERROR_INVALID_PARAMETER); _pthread_mutex_lock(&private_display->lock); diff --git a/src/tdm_private.h b/src/tdm_private.h index 45b1bab..458ae3c 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -229,7 +229,7 @@ extern char *tdm_debug_dump_dir; tdm_error tdm_display_update_output(tdm_private_backend *private_backend, - tdm_output *output_backend, int pipe); + tdm_output *output_backend, int pipe, unsigned int need_new_caps); tdm_error tdm_display_enable_debug_module(const char*modules); tdm_error -- 2.7.4 From ddc5e40bc89957ccc2badfdc20d09149999418c2 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 09:16:53 +0900 Subject: [PATCH 11/16] client: fix deadlock issue tdmp_vblank shouldn't be protected by mutex. Change-Id: I9bf718402774d3109b0482c2e8f80c4baeee8c54 --- client/tdm_client.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 9d00023..41a5fe2 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -487,8 +487,11 @@ tdm_client_destroy(tdm_client *client) pthread_mutex_lock(&private_client->lock); - if (private_client->temp_vblank) + if (private_client->temp_vblank) { + pthread_mutex_unlock(&private_client->lock); tdm_client_vblank_destroy(private_client->temp_vblank); + pthread_mutex_lock(&private_client->lock); + } LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_client->output_list, link) { _tdm_client_output_destroy(o); @@ -578,20 +581,12 @@ _tdm_client_vblank_handler_temp(tdm_client_vblank *vblank, tdm_error error, unsi unsigned int tv_sec, unsigned int tv_usec, void *user_data) { tdm_client_vblank_temp *vblank_temp = user_data; - tdm_private_client_vblank *private_vblank; - tdm_private_client *private_client; TDM_RETURN_IF_FAIL(vblank_temp != NULL); TDM_RETURN_IF_FAIL(vblank != NULL); - private_vblank = vblank; - private_client = private_vblank->private_output->private_client; - - if (vblank_temp->func) { - pthread_mutex_unlock(&private_client->lock); + if (vblank_temp->func) vblank_temp->func(sequence, tv_sec, tv_usec, vblank_temp->user_data); - pthread_mutex_lock(&private_client->lock); - } free(vblank_temp); } -- 2.7.4 From 28a7370459ed94026c4bf8e5315deda192aac089 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 11:15:24 +0900 Subject: [PATCH 12/16] client: not allow adding handler twicenot allow Change-Id: Ibc42a95295638ccc87aba5eb6999ef73664be7b2 --- client/tdm_client.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/tdm_client.c b/client/tdm_client.c index 41a5fe2..468d984 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -751,6 +751,13 @@ tdm_client_output_add_change_handler(tdm_client_output *output, private_output = (tdm_private_client_output*)output; private_client = private_output->private_client; + LIST_FOR_EACH_ENTRY(h, &private_output->change_handler_list, link) { + if (h->func == func && h->user_data == user_data) { + TDM_ERR("can't add twice"); + return TDM_ERROR_BAD_REQUEST; + } + } + h = calloc(1, sizeof *h); TDM_RETURN_VAL_IF_FAIL(h != NULL, TDM_ERROR_OUT_OF_MEMORY); -- 2.7.4 From 44cf1ade9010917c2ec4ead3a950988f269d4478 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 11:15:38 +0900 Subject: [PATCH 13/16] client: check invalid params Change-Id: I637a30bb799589d359c8e9bfdafdec539a062717 --- client/tdm_client.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 468d984..a665eb1 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -659,8 +659,14 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) return NULL; } - if (!name) + if (!name) { name = "primary"; + } else if (strncmp(name, "primary", 7) && strncmp(name, "default", 7)) { + if (error) + *error = TDM_ERROR_INVALID_PARAMETER; + pthread_mutex_unlock(&private_client->lock); + return NULL; + } LIST_FOR_EACH_ENTRY(private_output, &private_client->output_list, link) { if (!strncmp(private_output->name, name, TDM_NAME_LEN)) { -- 2.7.4 From 30ec37847bd0e9090f8f2e21f8980bebed4d5ee9 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 15:31:36 +0900 Subject: [PATCH 14/16] client: no need to check watch_output_changes 1) If watch_output_changes == true, private_output->dpms has been already updated in _tdm_client_output_cb_dpms. 2) If watch_output_changes == false, server will return TDM_ERROR_DPMS_OFF. The dpms value in client side is not important. If a client calls tdm_client_output_get_dpms, private_output->dpms will be updated. Change-Id: I6d6ea1df74955c44ce02c2d7a39aa589d38ba516 --- client/tdm_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index a665eb1..a257939 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -1270,7 +1270,7 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli if (!private_vblank->started) private_vblank->started = 1; - if (private_output->watch_output_changes && !private_vblank->enable_fake) { + if (!private_vblank->enable_fake) { if (private_output->connection == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { TDM_ERR("output disconnected"); pthread_mutex_unlock(&private_client->lock); @@ -1382,7 +1382,7 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, if (!private_vblank->started) private_vblank->started = 1; - if (private_output->watch_output_changes && !private_vblank->enable_fake) { + if (!private_vblank->enable_fake) { if (private_output->connection == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { TDM_ERR("output disconnected"); pthread_mutex_unlock(&private_client->lock); -- 2.7.4 From 2d31ca4382bc1bf50e8ecfbf657a26762609f010 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 15:32:49 +0900 Subject: [PATCH 15/16] client: let a server know the watch status Change-Id: I25652d7f92bb47909ef3d3873ee0df2620261d1f --- client/tdm_client.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index a257939..460cda4 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -777,6 +777,7 @@ tdm_client_output_add_change_handler(tdm_client_output *output, if (LIST_IS_EMPTY(&private_output->change_handler_list)) { wl_tdm_output_watch_output_changes(private_output->output, 1); + wl_display_roundtrip_queue(private_client->display, private_client->queue); /* TODO: this is very tricky. * If a client adds the change_handler, we might be able to guess that @@ -823,8 +824,10 @@ tdm_client_output_remove_change_handler(tdm_client_output *output, free(h); if (LIST_IS_EMPTY(&private_output->change_handler_list)) { - if (!CHECK_WL_PROTOCOL_ERROR(private_client)) + if (!CHECK_WL_PROTOCOL_ERROR(private_client)) { wl_tdm_output_watch_output_changes(private_output->output, 0); + wl_display_roundtrip_queue(private_client->display, private_client->queue); + } } pthread_mutex_unlock(&private_client->lock); -- 2.7.4 From 51eb6acc7af0c288896dc1a10d7577cfd8459bc8 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Feb 2018 15:33:21 +0900 Subject: [PATCH 16/16] display: add tdm_display_flush Change-Id: I8fd5bf404cac29d323a858bec482e45754d7ef9d --- include/tdm.h | 7 +++++++ src/tdm_display.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/tdm.h b/include/tdm.h index 9ae31a3..09a0f7b 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -96,6 +96,13 @@ tdm_error tdm_display_handle_events(tdm_display *dpy); /** + * @brief Flush the all events to clients + * @param[in] dpy A display object + */ +void +tdm_display_flush(tdm_display *dpy); + +/** * @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 diff --git a/src/tdm_display.c b/src/tdm_display.c index a7e880e..d2fba50 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -405,6 +405,20 @@ tdm_display_handle_events(tdm_display *dpy) return ret; } +EXTERN void +tdm_display_flush(tdm_display *dpy) +{ + tdm_private_display *private_display; + + TDM_RETURN_IF_FAIL(dpy != NULL); + private_display = (tdm_private_display*)dpy; + + if (tdm_thread_is_running()) + return; + + tdm_event_loop_flush(private_display); +} + EXTERN tdm_error tdm_display_get_backend_info(tdm_display *dpy, const char **name, const char **vendor, int *major, int *minor) -- 2.7.4