From 0b305c9f3c49692af09018785504823039944d97 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Fri, 5 Aug 2016 15:33:04 +0900 Subject: [PATCH] enable mirror showing when booting with hdmi connection Change-Id: Icbc52fcb794636eb787efe36f277a2317053e1d4 Signed-off-by: Junkyeong Kim --- src/e_mod_main.c | 250 ++++++++++++++++++++++++++++++++--------------- src/e_mod_main.h | 4 + 2 files changed, 174 insertions(+), 80 deletions(-) diff --git a/src/e_mod_main.c b/src/e_mod_main.c index 5565a80..e7fac6c 100644 --- a/src/e_mod_main.c +++ b/src/e_mod_main.c @@ -274,6 +274,77 @@ end2: free(client); } +static Eina_Bool +_e_eom_check_boot_connection(void *data) +{ + if (g_eom->check_first_boot != 0) + { + g_eom->timer = NULL; + return ECORE_CALLBACK_CANCEL; + } + + g_eom->check_first_boot = 1; + + if (g_eom->outputs) + { + Eina_List *l; + E_EomOutputPtr eom_output; + + EINA_LIST_FOREACH(g_eom->outputs, l, eom_output) + { + tdm_output *output; + const char *tmp_name; + char new_name[DRM_CONNECTOR_NAME_LEN]; + tdm_output_type tdm_type; + tdm_error ret = TDM_ERROR_NONE; + tdm_output_conn_status status; + + if (eom_output->id == 0) + continue; + + output = eom_output->output; + if (output == NULL) + { + EOM_ERR("output is null fail"); + continue; + } + + ret = tdm_output_get_conn_status(output, &status); + if (ret != TDM_ERROR_NONE) + { + EOM_ERR("tdm_output_get_conn_status fail(%d)", ret); + continue; + } + + if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) + continue; + + ret = tdm_output_get_output_type(output, &tdm_type); + if (ret != TDM_ERROR_NONE) + { + EOM_ERR("tdm_output_get_output_type fail(%d)", ret); + continue; + } + + if (tdm_type < ALEN(eom_conn_types)) + tmp_name = eom_conn_types[tdm_type]; + else + tmp_name = "unknown"; + /*TODO: What if there will more then one output of same type. + *e.g. "HDMI and HDMI" "LVDS and LVDS"*/ + snprintf(new_name, sizeof(new_name), "%s-%d", tmp_name, 0); + + eom_output->type = (eom_output_type_e)tdm_type; + eom_output->name = eina_stringshare_add(new_name); + eom_output->status = status; + + _e_eom_output_connected(eom_output); + } + } + g_eom->timer = NULL; + return ECORE_CALLBACK_CANCEL; +} + static Eina_Bool _e_eom_cb_ecore_drm_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { @@ -298,6 +369,13 @@ _e_eom_cb_ecore_drm_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *e g_eom->main_output_name = strdup(buff); g_eom->main_output_state = UP; + + if (g_eom->check_first_boot == 0) + { + if (g_eom->timer) + ecore_timer_del(g_eom->timer); + g_eom->timer = ecore_timer_add(EOM_CONNECT_CHECK_TIMEOUT, _e_eom_check_boot_connection, NULL); + } } else { @@ -570,20 +648,99 @@ _e_eom_cb_commit(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUS #endif } +static int +_e_eom_output_connected(E_EomOutputPtr eom_output) +{ + tdm_output *output; + tdm_error ret = TDM_ERROR_NONE; + const char *maker = NULL, *model = NULL, *name = NULL; + unsigned int mmWidth, mmHeight, subpixel; + const tdm_output_mode *mode; + int x = 0; + E_EomClientPtr iterator = NULL; + Eina_List *l; + + output = eom_output->output; + + ret = tdm_output_get_model_info(output, &maker, &model, &name); + RETURNVALIFTRUE(ret != TDM_ERROR_NONE, -1, "tdm_output_get_model_info fail(%d)", ret); + + ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight); + RETURNVALIFTRUE(ret != TDM_ERROR_NONE, -1, "tdm_output_get_physical_size fail(%d)", ret); + + ret = tdm_output_get_subpixel(output, &subpixel); + RETURNVALIFTRUE(ret != TDM_ERROR_NONE, -1, "tdm_output_get_subpixel fail(%d)", ret); + + mode = _e_eom_output_get_best_mode(output); + RETURNVALIFTRUE(mode == NULL, -1, "_e_eom_get_best_resolution fail"); + + ret = tdm_output_set_mode(output, mode); + RETURNVALIFTRUE(ret != TDM_ERROR_NONE, -1, "tdm_output_set_mode fail(%d)", ret); + + x = _e_eom_output_get_position(); + EOM_DBG("mode: %dx%d, phy(%dx%d), pos(%d,0), refresh:%d, subpixel:%d", + mode->hdisplay, mode->vdisplay, mmWidth, mmHeight, x, mode->vrefresh, subpixel); + + if (!e_comp_wl_output_init(eom_output->name, maker, eom_output->name, x, 0, + mode->hdisplay, mode->vdisplay, + mmWidth, mmHeight, mode->vrefresh, subpixel, 0)) + { + EOM_ERR("Could not setup new output: %s", eom_output->name); + return -1; + } + EOM_DBG("Setup new output: %s", eom_output->name); + + /* update eom_output connect */ + eom_output->width = mode->hdisplay; + eom_output->height = mode->vdisplay; + eom_output->phys_width = mmWidth; + eom_output->phys_height = mmHeight; +#ifdef DUMP_PRESENTATION + eom_output->dump_do = EINA_TRUE; + eom_output->dump_count = 1; + + EOM_DBG("dump init"); + tbm_surface_internal_dump_start("/eom_buffers", eom_output->width, eom_output->height, DUMP_NUM); +#endif + /* TODO: check output mode(presentation set) and HDMI type */ + _e_eom_output_start_mirror(eom_output); + + /* If there were previously connected clients to the output - notify them */ + EINA_LIST_FOREACH(g_eom->clients, l, iterator) + { + if (iterator) + { + EOM_DBG("Send MIRROR ON notification to clients"); + + wl_eom_send_output_info(iterator->resource, eom_output->id, + eom_output->type, eom_output->mode, + eom_output->width, eom_output->height, + eom_output->phys_width, eom_output->phys_height, + eom_output->status); + + wl_eom_send_output_attribute(iterator->resource, + eom_output->id, + _e_eom_output_state_get_attribute(eom_output), + _e_eom_output_state_get_attribute_state(eom_output), + EOM_ERROR_NONE); + } + } + + return 0; +} + static void _e_eom_cb_tdm_output_status_change(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data) { tdm_output_type tdm_type; tdm_error ret = TDM_ERROR_NONE; tdm_output_conn_status status; - tdm_output_conn_status status2; - const char *maker = NULL, *model = NULL, *name = NULL; const char *tmp_name; char new_name[DRM_CONNECTOR_NAME_LEN]; E_EomOutputPtr eom_output = NULL; tdm_output_conn_status plug; - E_EomClientPtr iterator = NULL; - Eina_List *l; + + g_eom->check_first_boot = 1; if (type == TDM_OUTPUT_CHANGE_DPMS || g_eom->main_output_state == DOWN) return; @@ -603,15 +760,12 @@ _e_eom_cb_tdm_output_status_change(tdm_output *output, tdm_output_change_type ty ret = tdm_output_get_output_type(output, &tdm_type); RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_output_type fail(%d)", ret); - ret = tdm_output_get_model_info(output, &maker, &model, &name); - RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_model_info fail(%d)", ret); - ret = tdm_output_get_conn_status(output, &status); RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_conn_status fail(%d)", ret); - status2 = value.u32; + plug = value.u32; - EOM_DBG("id (%d), type(%d, %d), status(%d, %d) (%s,%s,%s)", eom_output->id, type, tdm_type, status, status2, maker, model, name); + EOM_DBG("id (%d), type(%d, %d), status(%d, %d)", eom_output->id, type, tdm_type, status, plug); if (tdm_type < ALEN(eom_conn_types)) tmp_name = eom_conn_types[tdm_type]; @@ -621,82 +775,19 @@ _e_eom_cb_tdm_output_status_change(tdm_output *output, tdm_output_change_type ty *e.g. "HDMI and HDMI" "LVDS and LVDS"*/ snprintf(new_name, sizeof(new_name), "%s-%d", tmp_name, 0); - plug = value.u32; + eom_output->type = (eom_output_type_e)tdm_type; + eom_output->name = eina_stringshare_add(new_name); + eom_output->status = plug; if (plug == TDM_OUTPUT_CONN_STATUS_CONNECTED) { - unsigned int mmWidth, mmHeight, subpixel; - const tdm_output_mode *mode; - int x = 0; - - ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight); - RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_physical_size fail(%d)", ret); - - ret = tdm_output_get_subpixel(output, &subpixel); - RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_subpixel fail(%d)", ret); - - mode = _e_eom_output_get_best_mode(output); - RETURNIFTRUE(mode == NULL, "_e_eom_get_best_resolution fail"); - - ret = tdm_output_set_mode(output, mode); - RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_set_mode fail(%d)", ret); - - x = _e_eom_output_get_position(); - EOM_DBG("mode: %dx%d, phy(%dx%d), pos(%d,0), refresh:%d, subpixel:%d", - mode->hdisplay, mode->vdisplay, mmWidth, mmHeight, x, mode->vrefresh, subpixel); - - /* model is substituted with new_name. - * It used to bind wl_output with eom_output in libeom. */ - if (!e_comp_wl_output_init(new_name, maker, new_name, x, 0, - mode->hdisplay, mode->vdisplay, - mmWidth, mmHeight, mode->vrefresh, subpixel, 0)) - { - EOM_ERR("Could not setup new output: %s", new_name); - return; - } - EOM_DBG("Setup new output: %s", new_name); - - /* update eom_output connect */ - eom_output->width = mode->hdisplay; - eom_output->height = mode->vdisplay; - eom_output->phys_width = mmWidth; - eom_output->phys_height = mmHeight; - eom_output->status = plug; - eom_output->name = eina_stringshare_add(new_name); - eom_output->type = (eom_output_type_e)tdm_type; -#ifdef DUMP_PRESENTATION - eom_output->dump_do = EINA_TRUE; - eom_output->dump_count = 1; - - EOM_DBG("dump init"); - tbm_surface_internal_dump_start("/eom_buffers", eom_output->width, eom_output->height, DUMP_NUM); -#endif - /* TODO: check output mode(presentation set) and HDMI type */ - _e_eom_output_start_mirror(eom_output); - - /* If there were previously connected clients to the output - notify them */ - EINA_LIST_FOREACH(g_eom->clients, l, iterator) - { - if (iterator) - { - EOM_DBG("Send MIRROR ON notification to clients"); - - wl_eom_send_output_info(iterator->resource, eom_output->id, - eom_output->type, eom_output->mode, - eom_output->width, eom_output->height, - eom_output->phys_width, eom_output->phys_height, - eom_output->status); - - wl_eom_send_output_attribute(iterator->resource, - eom_output->id, - _e_eom_output_state_get_attribute(eom_output), - _e_eom_output_state_get_attribute_state(eom_output), - EOM_ERROR_NONE); - } - } + _e_eom_output_connected(eom_output); } else if (plug == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + E_EomClientPtr iterator = NULL; + Eina_List *l; + if (eom_output->state == MIRROR) _e_eom_output_stop_mirror(eom_output); @@ -705,7 +796,6 @@ _e_eom_cb_tdm_output_status_change(tdm_output *output, tdm_output_change_type ty eom_output->height = 0; eom_output->phys_width = 0; eom_output->phys_height = 0; - eom_output->status = plug; /* If there were previously connected clients to the output - notify them */ EINA_LIST_FOREACH(g_eom->clients, l, iterator) diff --git a/src/e_mod_main.h b/src/e_mod_main.h index 365b914..b24a5b8 100644 --- a/src/e_mod_main.h +++ b/src/e_mod_main.h @@ -70,6 +70,7 @@ E_API int e_modapi_save(E_Module *m); #define NUM_MAIN_BUF 2 #define NUM_ATTR 3 +#define EOM_CONNECT_CHECK_TIMEOUT 7.0 typedef struct _E_Eom E_Eom, *E_EomPtr; typedef struct _E_Eom_Out_Mode E_EomOutMode, *E_EomOutModePtr; @@ -155,6 +156,8 @@ struct _E_Eom char *main_output_name; int width; int height; + char check_first_boot; + Ecore_Timer *timer; unsigned int output_count; Eina_List *outputs; @@ -252,6 +255,7 @@ static void _e_eom_util_calculate_fullsize(int src_h, int src_v, int dst_size_h, int *dst_x, int *dst_y, int *dst_w, int *dst_h); static tbm_surface_h _e_eom_util_get_output_surface(const char *name); static Eina_Bool _e_eom_util_add_comp_object_redirected_hook(E_Client *ec); +static int _e_eom_output_connected(E_EomOutputPtr eom_output); #if 0 static int _e_eom_util_get_stamp(); #endif -- 2.34.1