Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> --- server/display-channel.c | 104 +++++++++++++++++++++++++++++++++++ server/display-channel.h | 5 ++ server/red-worker.c | 113 ++------------------------------------- 3 files changed, 112 insertions(+), 110 deletions(-) diff --git a/server/display-channel.c b/server/display-channel.c index 49a2bd48..a322045e 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -2541,10 +2541,114 @@ void display_channel_debug_oom(DisplayChannel *display, const char *msg) red_channel_sum_pipes_size(channel)); } +static void guest_set_client_capabilities(DisplayChannel *display) +{ + int i; + RedChannelClient *rcc; + uint8_t caps[SPICE_CAPABILITIES_SIZE] = { 0 }; + int caps_available[] = { + SPICE_DISPLAY_CAP_SIZED_STREAM, + SPICE_DISPLAY_CAP_MONITORS_CONFIG, + SPICE_DISPLAY_CAP_COMPOSITE, + SPICE_DISPLAY_CAP_A8_SURFACE, + }; + QXLInterface *qif = qxl_get_interface(display->priv->qxl); + + if (!red_qxl_check_qxl_version(display->priv->qxl, 3, 2)) { + return; + } + if (!qif->set_client_capabilities) { + return; + } +#define SET_CAP(a,c) \ + ((a)[(c) / 8] |= (1 << ((c) % 8))) + +#define CLEAR_CAP(a,c) \ + ((a)[(c) / 8] &= ~(1 << ((c) % 8))) + + if (!display->priv->running) { + return; + } + if ((red_channel_get_n_clients(RED_CHANNEL(display)) == 0)) { + red_qxl_set_client_capabilities(display->priv->qxl, FALSE, caps); + } else { + // Take least common denominator + for (i = 0 ; i < SPICE_N_ELEMENTS(caps_available); ++i) { + SET_CAP(caps, caps_available[i]); + } + FOREACH_CLIENT(display, rcc) { + for (i = 0 ; i < SPICE_N_ELEMENTS(caps_available); ++i) { + if (!red_channel_client_test_remote_cap(rcc, caps_available[i])) + CLEAR_CAP(caps, caps_available[i]); + } + } + red_qxl_set_client_capabilities(display->priv->qxl, TRUE, caps); + } +} + void display_channel_set_running(DisplayChannel *display, bool running) { if (running == display->priv->running) { return; } display->priv->running = running; + if (running) { + guest_set_client_capabilities(display); + } +} + +void +display_channel_connect(RedChannel *channel, RedClient *client, + RedStream *stream, int migration, + RedChannelCapabilities *caps) +{ + DisplayChannel *display = DISPLAY_CHANNEL(channel); + DisplayChannelClient *dcc; + + spice_debug("connect new client"); + + // FIXME not sure how safe is reading directly from reds + SpiceServer *reds = red_channel_get_server(channel); + dcc = dcc_new(display, client, stream, migration, caps, + spice_server_get_image_compression(reds), reds_get_jpeg_state(reds), + reds_get_zlib_glz_state(reds)); + if (!dcc) { + return; + } + display_channel_update_compression(display, dcc); + guest_set_client_capabilities(display); + dcc_start(dcc); +} + +void display_channel_disconnect(RedChannelClient *rcc) +{ + DisplayChannel *display = DISPLAY_CHANNEL(red_channel_client_get_channel(rcc)); + + guest_set_client_capabilities(display); + + red_channel_client_disconnect(rcc); +} + +static void red_migrate_display(DisplayChannel *display, RedChannelClient *rcc) +{ + /* We need to stop the streams, and to send upgrade_items to the client. + * Otherwise, (1) the client might display lossy regions that we don't track + * (streams are not part of the migration data) (2) streams_timeout may occur + * after the MIGRATE message has been sent. This can result in messages + * being sent to the client after MSG_MIGRATE and before MSG_MIGRATE_DATA (e.g., + * STREAM_CLIP, STREAM_DESTROY, DRAW_COPY) + * No message besides MSG_MIGRATE_DATA should be sent after MSG_MIGRATE. + * Notice that detach_and_stop_streams won't lead to any dev ram changes, since + * handle_dev_stop already took care of releasing all the dev ram resources. + */ + video_stream_detach_and_stop(display); + if (red_channel_client_is_connected(rcc)) { + red_channel_client_default_migrate(rcc); + } +} + +void display_channel_migrate(RedChannelClient *rcc) +{ + DisplayChannel *display = DISPLAY_CHANNEL(red_channel_client_get_channel(rcc)); + red_migrate_display(display, rcc); } diff --git a/server/display-channel.h b/server/display-channel.h index bdf2f059..989bf52b 100644 --- a/server/display-channel.h +++ b/server/display-channel.h @@ -159,6 +159,11 @@ void display_channel_reset_image_cache(DisplayChannel *self); void display_channel_debug_oom(DisplayChannel *display, const char *msg); void display_channel_set_running(DisplayChannel *display, bool running); +void display_channel_connect(RedChannel *channel, RedClient *client, + RedStream *stream, int migration, + RedChannelCapabilities *caps); +void display_channel_disconnect(RedChannelClient *rcc); +void display_channel_migrate(RedChannelClient *rcc); G_END_DECLS diff --git a/server/red-worker.c b/server/red-worker.c index c9c47133..b742925a 100644 --- a/server/red-worker.c +++ b/server/red-worker.c @@ -270,24 +270,6 @@ static bool red_process_is_blocked(RedWorker *worker) red_channel_max_pipe_size(RED_CHANNEL(worker->display_channel)) > MAX_PIPE_SIZE; } -static void red_migrate_display(DisplayChannel *display, RedChannelClient *rcc) -{ - /* We need to stop the streams, and to send upgrade_items to the client. - * Otherwise, (1) the client might display lossy regions that we don't track - * (streams are not part of the migration data) (2) streams_timeout may occur - * after the MIGRATE message has been sent. This can result in messages - * being sent to the client after MSG_MIGRATE and before MSG_MIGRATE_DATA (e.g., - * STREAM_CLIP, STREAM_DESTROY, DRAW_COPY) - * No message besides MSG_MIGRATE_DATA should be sent after MSG_MIGRATE. - * Notice that detach_and_stop_streams won't lead to any dev ram changes, since - * handle_dev_stop already took care of releasing all the dev ram resources. - */ - video_stream_detach_and_stop(display); - if (red_channel_client_is_connected(rcc)) { - red_channel_client_default_migrate(rcc); - } -} - typedef int (*red_process_t)(RedWorker *worker, int *ring_is_empty); static void flush_commands(RedWorker *worker, RedChannel *red_channel, red_process_t process) @@ -352,52 +334,6 @@ static void flush_all_qxl_commands(RedWorker *worker) flush_cursor_commands(worker); } -static void guest_set_client_capabilities(RedWorker *worker) -{ - int i; - RedChannelClient *rcc; - uint8_t caps[SPICE_CAPABILITIES_SIZE] = { 0 }; - int caps_available[] = { - SPICE_DISPLAY_CAP_SIZED_STREAM, - SPICE_DISPLAY_CAP_MONITORS_CONFIG, - SPICE_DISPLAY_CAP_COMPOSITE, - SPICE_DISPLAY_CAP_A8_SURFACE, - }; - QXLInterface *qif = qxl_get_interface(worker->qxl); - - if (!red_qxl_check_qxl_version(worker->qxl, 3, 2)) { - return; - } - if (!qif->set_client_capabilities) { - return; - } -#define SET_CAP(a,c) \ - ((a)[(c) / 8] |= (1 << ((c) % 8))) - -#define CLEAR_CAP(a,c) \ - ((a)[(c) / 8] &= ~(1 << ((c) % 8))) - - if (!worker->running) { - return; - } - if ((worker->display_channel == NULL) || - (red_channel_get_n_clients(RED_CHANNEL(worker->display_channel)) == 0)) { - red_qxl_set_client_capabilities(worker->qxl, FALSE, caps); - } else { - // Take least common denominator - for (i = 0 ; i < SPICE_N_ELEMENTS(caps_available); ++i) { - SET_CAP(caps, caps_available[i]); - } - FOREACH_CLIENT(worker->display_channel, rcc) { - for (i = 0 ; i < SPICE_N_ELEMENTS(caps_available); ++i) { - if (!red_channel_client_test_remote_cap(rcc, caps_available[i])) - CLEAR_CAP(caps, caps_available[i]); - } - } - red_qxl_set_client_capabilities(worker->qxl, TRUE, caps); - } -} - static void handle_dev_update_async(void *opaque, void *payload) { RedWorker *worker = opaque; @@ -619,7 +555,6 @@ static void handle_dev_start(void *opaque, void *payload) worker->running = TRUE; display_channel_set_running(worker->display_channel, true); worker->event_timeout = 0; - guest_set_client_capabilities(worker); } static void handle_dev_wakeup(void *opaque, void *payload) @@ -696,47 +631,6 @@ static void handle_dev_create_primary_surface_async(void *opaque, void *payload) red_qxl_async_complete(worker->qxl, msg->base.cookie); } -static void -handle_dev_display_connect(RedChannel *channel, RedClient *client, - RedStream *stream, int migration, - RedChannelCapabilities *caps) -{ - DisplayChannel *display = DISPLAY_CHANNEL(channel); - DisplayChannelClient *dcc; - RedWorker *worker = g_object_get_data(G_OBJECT(channel), "worker"); - - spice_debug("connect new client"); - - // FIXME not sure how safe is reading directly from reds - SpiceServer *reds = red_channel_get_server(channel); - dcc = dcc_new(display, client, stream, migration, caps, - spice_server_get_image_compression(reds), reds_get_jpeg_state(reds), - reds_get_zlib_glz_state(reds)); - if (!dcc) { - return; - } - display_channel_update_compression(display, dcc); - guest_set_client_capabilities(worker); - dcc_start(dcc); -} - -static void -handle_dev_display_disconnect(RedChannelClient *rcc) -{ - RedChannel *channel = red_channel_client_get_channel(rcc); - RedWorker *worker = g_object_get_data(G_OBJECT(channel), "worker"); - - guest_set_client_capabilities(worker); - - red_channel_client_disconnect(rcc); -} - -static void handle_dev_display_migrate(RedChannelClient *rcc) -{ - DisplayChannel *display = DISPLAY_CHANNEL(red_channel_client_get_channel(rcc)); - red_migrate_display(display, rcc); -} - static inline uint32_t qxl_monitors_config_size(uint32_t heads) { return sizeof(QXLMonitorsConfig) + sizeof(QXLHead) * heads; @@ -1264,12 +1158,11 @@ RedWorker* red_worker_new(QXLInstance *qxl) init_info.n_surfaces); channel = RED_CHANNEL(worker->display_channel); red_channel_init_stat_node(channel, &worker->stat, "display_channel"); - g_object_set_data(G_OBJECT(channel), "worker", worker); ClientCbs client_display_cbs = { NULL, }; - client_display_cbs.connect = handle_dev_display_connect; - client_display_cbs.disconnect = handle_dev_display_disconnect; - client_display_cbs.migrate = handle_dev_display_migrate; + client_display_cbs.connect = display_channel_connect; + client_display_cbs.disconnect = display_channel_disconnect; + client_display_cbs.migrate = display_channel_migrate; red_channel_register_client_cbs(channel, &client_display_cbs); return worker; -- 2.20.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel