From a11ee461a70e16163f8e8e75ccd6ef876d9c99e4 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Thu, 12 Mar 2026 17:32:55 +0000 Subject: [PATCH] resizing: Simplify GFX resizing For GFX, we currently resize the client with a deactivation-reactivation sequence. This is unnecessary, as the GFX RESET_GRAPHICS command does all the work for us, and avoids the need to teardown and reestablish the GFX channel. --- xrdp/xrdp.h | 3 - xrdp/xrdp_egfx.c | 15 ----- xrdp/xrdp_mm.c | 165 +++++++++++++++++++++------------------------- xrdp/xrdp_types.h | 18 +---- 4 files changed, 76 insertions(+), 125 deletions(-) diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 4f38765f..9fe55cef 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -493,9 +493,6 @@ struct display_control_monitor_layout_data enum display_resize_state state; unsigned int last_state_update_timestamp; unsigned int start_time; - /// This flag is set if the state machine needs to - /// shutdown/startup EGFX - int using_egfx; }; enum resize_queue_source diff --git a/xrdp/xrdp_egfx.c b/xrdp/xrdp_egfx.c index d04899a1..7e6b1d01 100644 --- a/xrdp/xrdp_egfx.c +++ b/xrdp/xrdp_egfx.c @@ -936,22 +936,7 @@ xrdp_egfx_open_response(struct xrdp_process *id, int chan_id, static int xrdp_egfx_close_response(struct xrdp_process *id, int chan_id) { - struct xrdp_mm *mm; - LOG(LOG_LEVEL_TRACE, "xrdp_egfx_close_response:"); - - mm = id->wm->mm; - - if (mm->resize_queue == 0 || mm->resize_queue->count <= 0) - { - return 0; - } - if (mm->resize_data != NULL - && mm->resize_data->state == WMRZ_EGFX_CONN_CLOSING) - { - LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_close_response: egfx deleted."); - advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSED); - } return 0; } diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 08570218..36252ec7 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -1142,6 +1142,29 @@ xrdp_mm_egfx_create_surfaces(struct xrdp_mm *self) return 0; } +/******************************************************************************/ +static int +xrdp_mm_egfx_delete_surfaces(struct xrdp_mm *self) +{ + int index; + int count = self->wm->client_info->display_sizes.monitorCount; + + LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_mm_egfx_delete_surfaces: " + "monitor count %d", count); + if (count < 1) + { + xrdp_egfx_send_delete_surface(self->egfx, self->egfx->surface_id); + } + else + { + for (index = 0; index < count; index++) + { + xrdp_egfx_send_delete_surface(self->egfx, index); + } + } + return 0; +} + /******************************************************************************/ static int xrdp_mm_egfx_caps_advertise(void *user, int caps_count, @@ -1276,11 +1299,6 @@ xrdp_mm_egfx_caps_advertise(void *user, int caps_count, self->encoder = xrdp_encoder_create(self); xrdp_mm_egfx_invalidate_wm_screen(self); - if (self->resize_data != NULL - && self->resize_data->state == WMRZ_EGFX_INITALIZING) - { - advance_resize_state_machine(self, WMRZ_EGFX_INITIALIZED); - } LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_caps_advertise: egfx created."); if (self->gfx_delay_autologin) { @@ -1616,14 +1634,11 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) int error = 0; struct xrdp_mm *mm; struct xrdp_mod *module; - struct xrdp_rdp *rdp; - struct xrdp_sec *sec; - struct xrdp_channel *chan; int in_progress; LOG_DEVEL(LOG_LEVEL_TRACE, "process_display_control_monitor_layout_data:"); - if (wm == NULL) + if (wm == NULL || wm->session == NULL || wm->session->rdp == NULL) { return 1; } @@ -1652,8 +1667,7 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) { case WMRZ_ENCODER_DELETE: // Stop any output from the module - rdp = wm->session->rdp; - xrdp_rdp_suppress_output(rdp, + xrdp_rdp_suppress_output(wm->session->rdp, 1, XSO_REASON_DYNAMIC_RESIZE, 0, 0, 0, 0); // Disable the encoder until the resize is complete. @@ -1662,58 +1676,35 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) xrdp_encoder_delete(mm->encoder); mm->encoder = NULL; } - if (mm->resize_data->using_egfx == 0) + if (!mm->egfx_up) { advance_resize_state_machine(mm, WMRZ_SERVER_MONITOR_RESIZE); } else { - advance_resize_state_machine(mm, WMRZ_EGFX_DELETE_SURFACE); + advance_resize_state_machine(mm, WMRZ_EGFX_RESET_GRAPHICS); } break; - case WMRZ_EGFX_DELETE_SURFACE: - if (error == 0 && module != 0) - { - xrdp_egfx_shutdown_delete_surface(mm->egfx); - } - advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSE); - break; - case WMRZ_EGFX_CONN_CLOSE: - if (error == 0 && module != 0) - { - xrdp_egfx_shutdown_close_connection(wm->mm->egfx); - mm->egfx_up = 0; - } - advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSING); - break; - // Also processed in xrdp_egfx_close_response - case WMRZ_EGFX_CONN_CLOSING: - rdp = wm->session->rdp; - sec = rdp->sec_layer; - chan = sec->chan_layer; - // Continue to check to see if the connection is closed. If it - // ever is, advance the state machine! - if (chan->drdynvcs[mm->egfx->channel_id].status - == XRDP_DRDYNVC_STATUS_CLOSED - || (g_get_elapsed_ms() - description->last_state_update_timestamp) > 100) + case WMRZ_EGFX_RESET_GRAPHICS: + // EGFX only. Delete the surfaces and send a 'reset graphics' + // command to resize the client. For EGFX, that's all we + // need to do. + xrdp_mm_egfx_delete_surfaces(mm); + error = xrdp_egfx_send_reset_graphics(mm->egfx, + desc_width, desc_height, + description->description.monitorCount, + description->description.minfo); + if (error != 0) { - advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSED); - break; - } - g_set_wait_obj(mm->resize_ready); - break; - case WMRZ_EGFX_CONN_CLOSED: - advance_resize_state_machine(mm, WRMZ_EGFX_DELETE); - break; - case WRMZ_EGFX_DELETE: - if (error == 0 && module != 0) - { - xrdp_egfx_shutdown_delete(wm->mm->egfx); - mm->egfx = NULL; + LOG_DEVEL(LOG_LEVEL_INFO, + "process_display_control_monitor_layout_data:" + " egfx_send_reset_graphics failed %d", error); + return advance_error(error, mm); } advance_resize_state_machine(mm, WMRZ_SERVER_MONITOR_RESIZE); break; + case WMRZ_SERVER_MONITOR_RESIZE: error = module->mod_server_monitor_resize( module, desc_width, desc_height, @@ -1743,10 +1734,23 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) // Not processed here. Processed in client_monitor_resize // case WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING: case WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED: - advance_resize_state_machine(mm, WMRZ_XRDP_CORE_RESET); - break; - case WMRZ_XRDP_CORE_RESET: + // Update the wm with the layout from the description + // we're processing sync_dynamic_monitor_data(wm, &(description->description)); + if (!mm->egfx_up) + { + // Need to resize the client using deactivation-reactivation + // sequence + advance_resize_state_machine(mm, WMRZ_XRDP_CORE_RESET); + } + else + { + // Client is already resized + advance_resize_state_machine(mm, WMRZ_ENCODER_CREATE); + } + break; + + case WMRZ_XRDP_CORE_RESET: error = libxrdp_reset(wm->session); if (error != 0) { @@ -1788,7 +1792,21 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) " xrdp_wm_load_static_pointers failed %d", error); return advance_error(error, mm); } - /* resize the main window */ + advance_resize_state_machine(mm, WMRZ_ENCODER_CREATE); + break; + + case WMRZ_ENCODER_CREATE: + if (mm->egfx_up) + { + xrdp_mm_egfx_create_surfaces(mm); + } + mm->encoder = xrdp_encoder_create(mm); + + // Ack all frames to speed up resize. + module->mod_frame_ack(module, 0, INT_MAX); + + // Restart module output after resizing and invalidating + // the screen. This causes an automatic redraw. error = xrdp_bitmap_resize( wm->screen, desc_width, desc_height); if (error != 0) @@ -1798,42 +1816,8 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) " xrdp_bitmap_resize failed %d", error); return advance_error(error, mm); } - advance_resize_state_machine(mm, WMRZ_EGFX_INITIALIZE); - break; - case WMRZ_EGFX_INITIALIZE: - if (mm->resize_data->using_egfx) - { - egfx_initialize(mm); - advance_resize_state_machine(mm, WMRZ_EGFX_INITALIZING); - } - else - { - advance_resize_state_machine(mm, WMRZ_EGFX_INITIALIZED); - } - break; - // Not processed here. Processed in xrdp_mm_egfx_caps_advertise - // case WMRZ_EGFX_INITALIZING: - case WMRZ_EGFX_INITIALIZED: - advance_resize_state_machine(mm, WMRZ_ENCODER_CREATE); - break; - case WMRZ_ENCODER_CREATE: - if (mm->encoder == NULL) - { - mm->encoder = xrdp_encoder_create(mm); - } - advance_resize_state_machine(mm, WMRZ_SERVER_INVALIDATE); - break; - case WMRZ_SERVER_INVALIDATE: - if (module != 0) - { - // Ack all frames to speed up resize. - module->mod_frame_ack(module, 0, INT_MAX); - } - // Restart module output after invalidating - // the screen. This causes an automatic redraw. xrdp_bitmap_invalidate(wm->screen, 0); - rdp = wm->session->rdp; - xrdp_rdp_suppress_output(rdp, + xrdp_rdp_suppress_output(wm->session->rdp, 0, XSO_REASON_DYNAMIC_RESIZE, 0, 0, desc_width, desc_height); advance_resize_state_machine(mm, WMRZ_COMPLETE); @@ -1930,7 +1914,6 @@ dynamic_monitor_process_queue(struct xrdp_mm *self) const unsigned int time = g_get_elapsed_ms(); self->resize_data->start_time = time; self->resize_data->last_state_update_timestamp = time; - self->resize_data->using_egfx = (self->egfx != NULL); advance_resize_state_machine(self, WMRZ_ENCODER_DELETE); } else diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 2a5be564..26a66d98 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -356,20 +356,13 @@ enum mm_connect_state enum display_resize_state { WMRZ_ENCODER_DELETE = 0, - WMRZ_EGFX_DELETE_SURFACE, - WMRZ_EGFX_CONN_CLOSE, - WMRZ_EGFX_CONN_CLOSING, - WMRZ_EGFX_CONN_CLOSED, - WRMZ_EGFX_DELETE, + WMRZ_EGFX_RESET_GRAPHICS, WMRZ_SERVER_MONITOR_RESIZE, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED, WMRZ_XRDP_CORE_RESET, WMRZ_XRDP_CORE_RESET_PROCESSING, WMRZ_XRDP_CORE_RESET_PROCESSED, - WMRZ_EGFX_INITIALIZE, - WMRZ_EGFX_INITALIZING, - WMRZ_EGFX_INITIALIZED, WMRZ_ENCODER_CREATE, WMRZ_SERVER_INVALIDATE, WMRZ_COMPLETE, @@ -378,11 +371,7 @@ enum display_resize_state #define XRDP_DISPLAY_RESIZE_STATE_TO_STR(status) \ ((status) == WMRZ_ENCODER_DELETE ? "WMRZ_ENCODER_DELETE" : \ - (status) == WMRZ_EGFX_DELETE_SURFACE ? "WMRZ_EGFX_DELETE_SURFACE" : \ - (status) == WMRZ_EGFX_CONN_CLOSE ? "WMRZ_EGFX_CONN_CLOSE" : \ - (status) == WMRZ_EGFX_CONN_CLOSING ? "WMRZ_EGFX_CONN_CLOSING" : \ - (status) == WMRZ_EGFX_CONN_CLOSED ? "WMRZ_EGFX_CONN_CLOSED" : \ - (status) == WRMZ_EGFX_DELETE ? "WMRZ_EGFX_DELETE" : \ + (status) == WMRZ_EGFX_RESET_GRAPHICS ? "WMRZ_EGFX_RESET_GRAPHICS" : \ (status) == WMRZ_SERVER_MONITOR_RESIZE ? "WMRZ_SERVER_MONITOR_RESIZE" : \ (status) == WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING ? \ "WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING" : \ @@ -393,9 +382,6 @@ enum display_resize_state "WMRZ_XRDP_CORE_RESET_PROCESSING" : \ (status) == WMRZ_XRDP_CORE_RESET_PROCESSED ? \ "WMRZ_XRDP_CORE_RESET_PROCESSED" : \ - (status) == WMRZ_EGFX_INITIALIZE ? "WMRZ_EGFX_INITIALIZE" : \ - (status) == WMRZ_EGFX_INITALIZING ? "WMRZ_EGFX_INITALIZING" : \ - (status) == WMRZ_EGFX_INITIALIZED ? "WMRZ_EGFX_INITIALIZED" : \ (status) == WMRZ_ENCODER_CREATE ? "WMRZ_ENCODER_CREATE" : \ (status) == WMRZ_SERVER_INVALIDATE ? "WMRZ_SERVER_INVALIDATE" : \ (status) == WMRZ_COMPLETE ? "WMRZ_COMPLETE" : \