From: Junkyeong Kim Date: Thu, 11 Oct 2018 07:36:08 +0000 (+0900) Subject: virtual: implementations for virtual output X-Git-Tag: accepted/tizen/5.0/unified/20181108.074357~8 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Flibtdm.git;a=commitdiff_plain;h=b718e753150a166cdc4589188700bcc3878ae3ab virtual: implementations for virtual output - voutput connect & disconnect - set voutput available modes - set voutput mode - set voutput physical size Change-Id: I7aae9f5b425dfbdcf0b50843ee5b31e93e7ca353 Signed-off-by: Junkyeong Kim --- diff --git a/client/tdm_client.c b/client/tdm_client.c index fbb875b..972ae00 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -359,7 +359,7 @@ _tdm_client_output_cb_connection(void *data, struct wl_tdm_output *wl_tdm_output private_client = private_output->private_client; - if (private_output->connection == value) + if (private_output->connection == value && value != TDM_OUTPUT_CONN_STATUS_MODE_SETTED) return; private_output->connection = value; diff --git a/src/tdm.c b/src/tdm.c index 30f3c07..886e847 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -127,6 +127,26 @@ tdm_display_find_output_stamp(tdm_private_display *private_display, double stamp return NULL; } +INTERN void * +tdm_display_find_private_voutput(tdm_private_display *private_display, double stamp) +{ + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput = NULL; + tdm_private_output *private_output = NULL; + + private_module = private_display->virtual_module; + if (!private_module) return NULL; + + LIST_FOR_EACH_ENTRY(private_voutput, &private_module->voutput_list, link) { + if (!private_voutput->private_output) continue; + private_output = private_voutput->private_output; + if (private_output->stamp == stamp) + return private_voutput; + } + + return NULL; +} + tdm_private_hwc * tdm_display_find_private_hwc(tdm_private_display *private_display, tdm_hwc *hwc_backend) { @@ -530,6 +550,7 @@ tdm_display_update_output(tdm_private_module *private_module, tdm_output *output LIST_INITHEAD(&private_output->pending_commit_handler_list); LIST_INITHEAD(&private_output->destroy_handler_list); LIST_INITHEAD(&private_output->change_handler_list); + LIST_INITHEAD(&private_output->mode_change_request_handler_list); if (func_output->output_set_status_handler) { func_output->output_set_status_handler(private_output->output_backend, @@ -1024,6 +1045,7 @@ _tdm_display_load_module_with_file(tdm_private_display *private_display, } LIST_INITHEAD(&private_module->output_list); + LIST_INITHEAD(&private_module->voutput_list); LIST_INITHEAD(&private_module->pp_list); LIST_INITHEAD(&private_module->capture_list); diff --git a/src/tdm_helper.c b/src/tdm_helper.c index afedccd..e9db919 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -947,6 +947,8 @@ _tdm_helper_get_backend_information(tdm_private_module *private_module, char *re } } } + if (LIST_IS_EMPTY(&private_module->output_list)) + TDM_SNPRINTF(reply, len, "(no layer)\n"); TDM_SNPRINTF(reply, len, "\n"); if (private_module->capabilities & TDM_DISPLAY_CAPABILITY_PP) { diff --git a/src/tdm_output.c b/src/tdm_output.c index 4a96e16..9454647 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -500,6 +500,85 @@ tdm_output_add_change_handler(tdm_output *output, return ret; } +EXTERN tdm_error +tdm_output_add_mode_change_request_handler(tdm_output *output, + tdm_output_mode_change_request_handler func, + void *user_data) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_private_output_mode_change_handler *mode_change_handler = NULL; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_output*)output; + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) { + if (mode_change_handler->func == func && mode_change_handler->user_data == user_data) { + TDM_ERR("can't add twice"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + } + + mode_change_handler = calloc(1, sizeof(tdm_private_output_change_handler)); + if (!mode_change_handler) { + /* LCOV_EXCL_START */ + TDM_ERR("failed: alloc memory"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ + } + + mode_change_handler->private_output = private_output; + mode_change_handler->func = func; + mode_change_handler->user_data = user_data; + + LIST_ADDTAIL(&mode_change_handler->link, &private_output->mode_change_request_handler_list); + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_NONE; +} + +EXTERN tdm_error +tdm_output_remove_mode_change_request_handler(tdm_output *output, + tdm_output_mode_change_request_handler func, + void *user_data) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_private_output_mode_change_handler *mode_change_handler = NULL, *hh = NULL; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_output*)output; + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + LIST_FOR_EACH_ENTRY_SAFE(mode_change_handler, hh, &private_output->mode_change_request_handler_list, link) { + if (mode_change_handler->func != func || mode_change_handler->user_data != user_data) + continue; + + LIST_DEL(&mode_change_handler->link); + free(mode_change_handler); + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_NONE; + } + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_INVALID_PARAMETER; +} + EXTERN void tdm_output_remove_change_handler(tdm_output *output, tdm_output_change_handler func, @@ -1206,6 +1285,22 @@ tdm_output_remove_commit_handler(tdm_output *output, tdm_output_commit_handler f return ret; } +INTERN void +tdm_output_request_mode_set(tdm_output *output, unsigned int index) +{ + tdm_private_output *private_output = (tdm_private_output*)output; + tdm_private_output_mode_change_handler *mode_change_handler = NULL; + + TDM_RETURN_IF_FAIL(private_output != NULL); + + if (LIST_IS_EMPTY(&private_output->mode_change_request_handler_list)) + return; + + LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) { + mode_change_handler->func(mode_change_handler->private_output, index, mode_change_handler->user_data); + } +} + INTERN tdm_error tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) { @@ -1856,3 +1951,123 @@ tdm_voutput_destroy(tdm_voutput *voutput) return ret; } + +INTERN tdm_error +tdm_voutput_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *modes, int count) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(count != 0, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_set_available_mode) + ret = func_voutput->voutput_set_available_mode(private_voutput->voutput_backend, modes, count); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_voutput_set_physical_size(tdm_voutput *voutput, unsigned int mmwidth, unsigned int mmheight) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_set_physical_size) + ret = func_voutput->voutput_set_physical_size(private_voutput->voutput_backend, mmwidth, mmheight); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_voutput_connect(tdm_voutput *voutput) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_connect) + ret = func_voutput->voutput_connect(private_voutput->voutput_backend); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} + +INTERN tdm_error +tdm_voutput_disconnect(tdm_voutput *voutput) +{ + tdm_private_display *private_display; + tdm_private_module *private_module = NULL; + tdm_private_voutput *private_voutput; + tdm_func_voutput *func_voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_voutput*)voutput; + private_display = private_voutput->private_display; + private_module = private_voutput->private_module; + TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE); + + _pthread_mutex_lock(&private_display->lock); + + func_voutput = &private_module->func_voutput; + if (func_voutput->voutput_disconnect) + ret = func_voutput->voutput_disconnect(private_voutput->voutput_backend); + else + ret = TDM_ERROR_NOT_IMPLEMENTED; + + _pthread_mutex_unlock(&private_display->lock); + + return ret; +} diff --git a/src/tdm_server.c b/src/tdm_server.c index 12896d5..d035a1d 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -196,6 +196,8 @@ _tdm_server_cb_output_change(tdm_output *output, tdm_output_change_type type, tdm_server_output_info *output_info = user_data; struct wl_client *client; pid_t pid = 0; + tdm_output_conn_status status; + tdm_error ret = TDM_ERROR_NONE; TDM_RETURN_IF_FAIL(output_info != NULL); @@ -209,13 +211,29 @@ _tdm_server_cb_output_change(tdm_output *output, tdm_output_change_type type, return; } - TDM_DBG("send the output changes: %d", (unsigned int)pid); + TDM_DBG("send the output changes: %d, type:%d, value:%d", (unsigned int)pid, type, value.u32); switch (type) { case TDM_OUTPUT_CHANGE_DPMS: wl_tdm_output_send_dpms(output_info->resource, value.u32, TDM_ERROR_NONE); break; case TDM_OUTPUT_CHANGE_CONNECTION: + status = value.u32; + if (status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED) { + const tdm_output_mode *mode = NULL; + unsigned int hdisplay, vdisplay, vrefresh; + + ret = tdm_output_get_mode(output_info->output, &mode); + if (ret == TDM_ERROR_NONE) { + hdisplay = (mode) ? mode->hdisplay : 0; + vdisplay = (mode) ? mode->vdisplay : 0; + vrefresh = (mode) ? mode->vrefresh : 0; + + wl_tdm_output_send_mode(output_info->resource, hdisplay, vdisplay, vrefresh, ret); + } else { + wl_tdm_output_send_mode(output_info->resource, 0, 0, 0, ret); + } + } wl_tdm_output_send_connection(output_info->resource, value.u32, TDM_ERROR_NONE); break; default: @@ -718,32 +736,99 @@ _tdm_voutput_cb_set_available_modes(struct wl_client *client, struct wl_resource *resource, struct wl_array *modes) { - /* TODO */ + tdm_server_voutput_info *voutput_info; + tdm_output_mode *mode; + int size, count = 0, i = 0; + + voutput_info = wl_resource_get_user_data(resource); + + voutput_info->available_modes.count = 0; + if (voutput_info->available_modes.modes) + free(voutput_info->available_modes.modes); + + wl_array_for_each(mode, modes) + count++; + size = sizeof(tdm_output_mode); + + voutput_info->available_modes.modes = malloc(count * size); + voutput_info->available_modes.count = count; + + wl_array_for_each(mode, modes) + memcpy(&voutput_info->available_modes.modes[i++], mode, size); } static void _tdm_voutput_cb_set_physical_size(struct wl_client *client, struct wl_resource *resource, unsigned int mmwidth, unsigned int mmheight) { - /* TODO */ + tdm_server_voutput_info *voutput_info; + + voutput_info = wl_resource_get_user_data(resource); + + voutput_info->mmwidth = mmwidth; + voutput_info->mmheight = mmheight; } static void _tdm_voutput_cb_set_mode(struct wl_client *client, struct wl_resource *resource, unsigned int index) { - /* TODO */ + tdm_server_voutput_info *voutput_info = NULL; + tdm_output *output = NULL; + tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + const tdm_output_mode *modes, *mode; + + int count = 0; + tdm_error ret; + + voutput_info = wl_resource_get_user_data(resource); + TDM_RETURN_IF_FAIL(voutput_info != NULL); + output = voutput_info->output; + + ret = tdm_output_get_conn_status(output, &status); + TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + TDM_RETURN_IF_FAIL(status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED); + + ret = tdm_output_get_available_modes(output, &modes, &count); + TDM_RETURN_IF_FAIL(index < count); + + mode = &modes[index]; + TDM_DBG("mode set request to index:%d (%dx%d, %d)", index, mode->hdisplay, mode->vdisplay, mode->vrefresh); + + ret = tdm_output_set_mode(output, mode); + TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + + tdm_output_request_mode_set(voutput_info->output, index); } static void _tdm_voutput_cb_connect(struct wl_client *client, struct wl_resource *resource) { - /* TODO */ + tdm_server_voutput_info *voutput_info; + + voutput_info = wl_resource_get_user_data(resource); + voutput_info->status = TDM_OUTPUT_CONN_STATUS_CONNECTED; + + tdm_voutput_set_physical_size(voutput_info->voutput, voutput_info->mmwidth, voutput_info->mmheight); + tdm_voutput_set_available_mode(voutput_info->voutput, voutput_info->available_modes.modes, voutput_info->available_modes.count); + tdm_voutput_connect(voutput_info->voutput); } static void _tdm_voutput_cb_disconnect(struct wl_client *client, struct wl_resource *resource) { - /* TODO */ + tdm_server_voutput_info *voutput_info; + + voutput_info = wl_resource_get_user_data(resource); + voutput_info->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + + /* Do free resources when it's being disconnected */ + free(voutput_info->available_modes.modes); + voutput_info->available_modes.modes = NULL; + voutput_info->available_modes.count = 0; + voutput_info->mmwidth = 0; + voutput_info->mmheight = 0; + + tdm_voutput_disconnect(voutput_info->voutput); } static void