From 38d853f97f9bfe50d5c069228cdfcdb990b11f46 Mon Sep 17 00:00:00 2001 From: Michael Scherle Date: Fri, 9 May 2025 17:11:16 +0200 Subject: [PATCH] block draws until first forced draw isdone --- server/dcc-send.cpp | 8 +++----- server/dcc.cpp | 27 ++++++++++++++++++--------- server/dcc.h | 1 + server/display-channel.cpp | 8 +------- server/display-channel.h | 3 +-- server/red-channel-client.cpp | 12 ++++++++++++ server/red-channel-client.h | 6 ++++-- server/red-channel.cpp | 3 +++ 8 files changed, 43 insertions(+), 25 deletions(-) diff --git a/server/dcc-send.cpp b/server/dcc-send.cpp index 5930af7b..bf39222e 100644 --- a/server/dcc-send.cpp +++ b/server/dcc-send.cpp @@ -1755,10 +1755,9 @@ static bool red_marshall_stream_data(DisplayChannelClient *dcc, static void red_free_cb(VideoEncoderDmabufData *dmabuf_data) { auto dcc = static_cast(dmabuf_data->dcc); - DisplayChannel *display = DCC_TO_DC(dcc); dcc->priv->gl_draw_ongoing = false; - display_channel_gl_draw_done(display); + dcc_gl_draw_done(dcc); delete dmabuf_data; } @@ -1816,7 +1815,7 @@ static void red_marshall_gl_draw_stream(DisplayChannelClient *dcc, } dcc->priv->gl_draw_ongoing = false; - display_channel_gl_draw_done(display); + dcc_gl_draw_done(dcc); delete dmabuf_data; return; } @@ -2384,9 +2383,8 @@ static void marshall_gl_draw(DisplayChannelClient *dcc, } else if (DCC_TO_DC(dcc)->priv->gl_draw_stream) { red_marshall_gl_draw_stream(dcc, m); } else if (dcc->priv->gl_draw_ongoing){ - DisplayChannel *display = DCC_TO_DC(dcc); dcc->priv->gl_draw_ongoing = false; - display_channel_gl_draw_done(display); + dcc_gl_draw_done(dcc); } else { spice_warning("nothing to send to the client"); } diff --git a/server/dcc.cpp b/server/dcc.cpp index cde3d96f..91223137 100644 --- a/server/dcc.cpp +++ b/server/dcc.cpp @@ -430,18 +430,18 @@ void dcc_start(DisplayChannelClient *dcc) SpiceMsgDisplayGlScanoutUnix *scanout = red_qxl_get_gl_scanout(qxl); if (scanout) { display_channel_push_monitors_config(display); + dcc->set_pipes_enabled(false); SpiceMsgDisplayGlDraw draw = { .x = 0, .y = 0, .w = scanout->width, - .h = scanout->height + .h = scanout->height, }; red_qxl_put_gl_scanout(qxl, scanout); - display_channel_gl_draw(display, &draw, true); + dcc->pipe_add(dcc_gl_draw_item_new(dcc, &draw, 0)); } else { red_qxl_put_gl_scanout(qxl, scanout); } - display_channel_push_monitors_config(display); } } @@ -457,10 +457,20 @@ static void dcc_destroy_stream_agents(DisplayChannelClient *dcc) } } -static void dcc_stop(DisplayChannelClient *dcc) +void dcc_gl_draw_done(DisplayChannelClient *dcc) { DisplayChannel *dc = DCC_TO_DC(dcc); + if (!dcc->is_pipes_enabled()) { + dcc->set_pipes_enabled(true); + return; + } + display_channel_gl_draw_done(dc); +} + +static void dcc_stop(DisplayChannelClient *dcc) +{ + pixmap_cache_unref(dcc->priv->pixmap_cache); dcc->priv->pixmap_cache = nullptr; dcc_palette_cache_reset(dcc); @@ -469,7 +479,7 @@ static void dcc_stop(DisplayChannelClient *dcc) image_encoders_free(&dcc->priv->encoders); if (dcc->priv->gl_draw_ongoing) { - display_channel_gl_draw_done(dc); + dcc_gl_draw_done(dcc); } } @@ -535,7 +545,7 @@ RedPipeItemPtr dcc_gl_draw_item_new(RedChannelClient *rcc, void *data, int num) { auto dcc = static_cast(rcc); auto draw = static_cast(data); - + if (!dcc->is_gl_client() && !rcc->test_remote_cap(SPICE_DISPLAY_CAP_MULTI_CODEC)) { red_channel_warning(rcc->get_channel(), @@ -1005,9 +1015,8 @@ GArray *dcc_get_preferred_video_codecs_for_encoding(DisplayChannelClient *dcc) return display_channel_get_video_codecs(DCC_TO_DC(dcc)); } -static bool dcc_handle_gl_draw_done(DisplayChannelClient *dcc) +bool dcc_handle_gl_draw_done(DisplayChannelClient *dcc) { - DisplayChannel *display = DCC_TO_DC(dcc); if (G_UNLIKELY(!dcc->priv->gl_draw_ongoing)) { g_warning("unexpected DRAW_DONE received\n"); @@ -1016,7 +1025,7 @@ static bool dcc_handle_gl_draw_done(DisplayChannelClient *dcc) } dcc->priv->gl_draw_ongoing = FALSE; - display_channel_gl_draw_done(display); + dcc_gl_draw_done(dcc); return TRUE; } diff --git a/server/dcc.h b/server/dcc.h index 4e7150d5..797a59dd 100644 --- a/server/dcc.h +++ b/server/dcc.h @@ -143,6 +143,7 @@ int dcc_compress_image (DisplayCha SpiceImage *dest, SpiceBitmap *src, Drawable *drawable, int can_lossy, compress_send_data_t* o_comp_data); +void dcc_gl_draw_done (DisplayChannelClient *dcc); void dcc_create_surface(DisplayChannelClient *dcc, struct RedSurface *surface); void dcc_push_surface_image(DisplayChannelClient *dcc, struct RedSurface *surface); diff --git a/server/display-channel.cpp b/server/display-channel.cpp index 9a46889c..838ab360 100644 --- a/server/display-channel.cpp +++ b/server/display-channel.cpp @@ -2327,9 +2327,6 @@ void display_channel_gl_scanout(DisplayChannel *display) static void set_gl_draw_async_count(DisplayChannel *display, int num) { - if(num < 0) { - return; - } display->priv->gl_draw_async_count = num; if (num == 0) { @@ -2337,16 +2334,13 @@ static void set_gl_draw_async_count(DisplayChannel *display, int num) } } -void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *draw, bool initial) +void display_channel_gl_draw(DisplayChannel *display, SpiceMsgDisplayGlDraw *draw) { int num; spice_return_if_fail(display->priv->gl_draw_async_count == 0); num = display->pipes_new_add(dcc_gl_draw_item_new, draw); - if(initial) { - return; - } set_gl_draw_async_count(display, num); } diff --git a/server/display-channel.h b/server/display-channel.h index bc8a5f95..c54df25c 100644 --- a/server/display-channel.h +++ b/server/display-channel.h @@ -125,8 +125,7 @@ void display_channel_destroy_surface_wait (DisplayCha void display_channel_destroy_surfaces (DisplayChannel *display); void display_channel_gl_scanout (DisplayChannel *display); void display_channel_gl_draw (DisplayChannel *display, - SpiceMsgDisplayGlDraw *draw, - bool initial = false); + SpiceMsgDisplayGlDraw *draw); void display_channel_gl_draw_done (DisplayChannel *display); void display_channel_process_draw(DisplayChannel *display, diff --git a/server/red-channel-client.cpp b/server/red-channel-client.cpp index b7567ffb..f4bc57df 100644 --- a/server/red-channel-client.cpp +++ b/server/red-channel-client.cpp @@ -165,6 +165,8 @@ struct RedChannelClientPrivate bool wait_migrate_data; bool wait_migrate_flush_mark; + bool pipes_enabled = true; + RedChannelClientLatencyMonitor latency_monitor; RedChannelClientConnectivityMonitor connectivity_monitor; @@ -1550,6 +1552,16 @@ bool RedChannelClient::is_blocked() const return priv->send_data.blocked; } +bool RedChannelClient::is_pipes_enabled() const +{ + return priv->pipes_enabled; +}; + +void RedChannelClient::set_pipes_enabled(bool enabled) +{ + priv->pipes_enabled = enabled; +} + int RedChannelClient::send_message_pending() { return priv->send_data.header.get_msg_type(&priv->send_data.header) != 0; diff --git a/server/red-channel-client.h b/server/red-channel-client.h index 5c4df962..4df16817 100644 --- a/server/red-channel-client.h +++ b/server/red-channel-client.h @@ -45,7 +45,7 @@ public: RedChannelCapabilities *caps, bool monitor_latency=false); virtual bool init(); - + bool is_connected() const; bool is_waiting_for_migrate_data() const; bool test_remote_cap(uint32_t cap) const; @@ -107,7 +107,9 @@ public: void push_set_ack(); bool is_blocked() const; - + bool is_pipes_enabled() const; + void set_pipes_enabled(bool enabled); + /* helper for channels that have complex logic that can possibly ready a send */ int send_message_pending(); diff --git a/server/red-channel.cpp b/server/red-channel.cpp index e3cc38a5..b175d155 100644 --- a/server/red-channel.cpp +++ b/server/red-channel.cpp @@ -437,6 +437,9 @@ int RedChannel::pipes_new_add(new_pipe_item_t creator, void *data) spice_assert(creator != nullptr); FOREACH_CLIENT(this, rcc) { + if(!rcc->is_pipes_enabled()){ + continue; + } auto item = (*creator)(rcc, data, num++); if (item) { rcc->pipe_add(std::move(item));