diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index f477b3b491..b2a8ae9717 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -502,6 +502,9 @@ int xrdp_mm_check_wait_objs(struct xrdp_mm *self); int xrdp_mm_frame_ack(struct xrdp_mm *self, int frame_id); +void +xrdp_mm_efgx_add_dirty_region_to_planar_list(struct xrdp_mm *self, + struct xrdp_region *dirty_region); int xrdp_mm_egfx_send_planar_bitmap(struct xrdp_mm *self, struct xrdp_bitmap *bitmap, diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 650dfb48b9..c136894a26 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -1095,25 +1095,32 @@ xrdp_mm_egfx_send_planar_bitmap(struct xrdp_mm *self, /******************************************************************************/ static int -xrdp_mm_egfx_invalidate_all(struct xrdp_mm *self) +xrdp_mm_egfx_invalidate_wm_screen(struct xrdp_mm *self) { - struct xrdp_rect xr_rect; - struct xrdp_bitmap *screen; - int error; - - LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_invalidate_all:"); + int error = 0; - screen = self->wm->screen; + LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_invalidate_wm_screen:"); - xr_rect.left = 0; - xr_rect.top = 0; - xr_rect.right = screen->width; - xr_rect.bottom = screen->height; - if (self->wm->screen_dirty_region == NULL) + // Only invalidate the WM screen if the module is using the WM screen, + // or we haven't loaded the module yet. + // + // Otherwise we may send client updates which conflict with the + // updates sent directly from the module via the encoder. + if (self->mod_uses_wm_screen_for_gfx || self->mod_handle == 0) { - self->wm->screen_dirty_region = xrdp_region_create(self->wm); + struct xrdp_bitmap *screen = self->wm->screen; + struct xrdp_rect xr_rect; + + xr_rect.left = 0; + xr_rect.top = 0; + xr_rect.right = screen->width; + xr_rect.bottom = screen->height; + if (self->wm->screen_dirty_region == NULL) + { + self->wm->screen_dirty_region = xrdp_region_create(self->wm); + } + error = xrdp_region_add_rect(self->wm->screen_dirty_region, &xr_rect); } - error = xrdp_region_add_rect(self->wm->screen_dirty_region, &xr_rect); return error; } @@ -1370,7 +1377,7 @@ xrdp_mm_egfx_caps_advertise(void *user, int caps_count, self->egfx_up = 1; xrdp_mm_egfx_create_surfaces(self); self->encoder = xrdp_encoder_create(self); - xrdp_mm_egfx_invalidate_all(self); + xrdp_mm_egfx_invalidate_wm_screen(self); if (self->resize_data != NULL && self->resize_data->state == WMRZ_EGFX_INITALIZING) @@ -1846,20 +1853,13 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm) // Ack all frames to speed up resize. module->mod_frame_ack(module, 0, INT_MAX); } - // Restart module output + // Restart module output after invalidating + // the screen. This causes an automatic redraw. + xrdp_bitmap_invalidate(wm->screen, 0); rdp = (struct xrdp_rdp *) (wm->session->rdp); xrdp_rdp_suppress_output(rdp, 0, XSO_REASON_DYNAMIC_RESIZE, 0, 0, desc_width, desc_height); - /* redraw */ - error = xrdp_bitmap_invalidate(wm->screen, 0); - if (error != 0) - { - LOG_DEVEL(LOG_LEVEL_INFO, - "process_display_control_monitor_layout_data:" - " xrdp_bitmap_invalidate failed %d", error); - return advance_error(error, mm); - } advance_resize_state_machine(mm, WMRZ_COMPLETE); break; default: @@ -3535,6 +3535,39 @@ xrdp_mm_process_enc_done(struct xrdp_mm *self) return 0; } +/*****************************************************************************/ +void +xrdp_mm_efgx_add_dirty_region_to_planar_list(struct xrdp_mm *self, + struct xrdp_region *dirty_region) +{ + int jndex = 0; + struct xrdp_rect rect; + + int error = xrdp_region_get_rect(dirty_region, jndex, &rect); + if (error == 0) + { + if (self->wm->screen_dirty_region == NULL) + { + self->wm->screen_dirty_region = xrdp_region_create(self->wm); + } + + do + { + xrdp_region_add_rect(self->wm->screen_dirty_region, &rect); + jndex++; + error = xrdp_region_get_rect(dirty_region, jndex, &rect); + } + while (error == 0); + + if (self->mod_handle != 0) + { + // Module has been writing to WM screen using GFX + self->mod_uses_wm_screen_for_gfx = 1; + } + } + +} + /*****************************************************************************/ static int xrdp_mm_draw_dirty(struct xrdp_mm *self) diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c index fce0d3780d..a5ef48a026 100644 --- a/xrdp/xrdp_painter.c +++ b/xrdp/xrdp_painter.c @@ -95,18 +95,8 @@ xrdp_painter_send_dirty(struct xrdp_painter *self) if (self->session->client_info->gfx) { - if (self->wm->screen_dirty_region == NULL) - { - self->wm->screen_dirty_region = xrdp_region_create(self->wm); - } - jndex = 0; - error = xrdp_region_get_rect(self->dirty_region, jndex, &rect); - while (error == 0) - { - xrdp_region_add_rect(self->wm->screen_dirty_region, &rect); - jndex++; - error = xrdp_region_get_rect(self->dirty_region, jndex, &rect); - } + xrdp_mm_efgx_add_dirty_region_to_planar_list(self->wm->mm, + self->dirty_region); } else { diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 7607c39c67..c2195a9cf5 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -439,6 +439,7 @@ struct xrdp_mm int egfx_up; enum xrdp_egfx_flags egfx_flags; int gfx_delay_autologin; + int mod_uses_wm_screen_for_gfx; /* Resize on-the-fly control */ struct display_control_monitor_layout_data *resize_data; struct list *resize_queue;