Acked-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx> On Tue, 2019-03-26 at 19:10 +0000, Frediano Ziglio wrote: > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > --- > server/display-channel.c | 108 +++++++++++++++++++++++++++++++++++++ > server/display-channel.h | 7 +++ > server/red-worker.c | 114 ++----------------------------------- > -- > 3 files changed, 120 insertions(+), 109 deletions(-) > > diff --git a/server/display-channel.c b/server/display-channel.c > index cb052bfc..1af87ba4 100644 > --- a/server/display-channel.c > +++ b/server/display-channel.c > @@ -2540,3 +2540,111 @@ void display_channel_debug_oom(DisplayChannel > *display, const char *msg) > ring_get_length(&display->priv->current_list), > 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 (!red_qxl_is_running(display->priv->qxl)) { > + 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_update_qxl_running(DisplayChannel *display, > bool 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 f64da0bd..7dfedd75 100644 > --- a/server/display-channel.h > +++ b/server/display-channel.h > @@ -158,6 +158,13 @@ void > display_channel_reset_image_cache(DisplayChannel *self); > > void display_channel_debug_oom(DisplayChannel *display, const char > *msg); > > +void display_channel_update_qxl_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 > > #endif /* DISPLAY_CHANNEL_H_ */ > diff --git a/server/red-worker.c b/server/red-worker.c > index b80fefab..d6b69f29 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 (!red_qxl_is_running(worker->qxl)) { > - 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; > @@ -588,6 +524,7 @@ static void handle_dev_stop(void *opaque, void > *payload) > spice_assert(red_qxl_is_running(worker->qxl)); > > red_qxl_set_running(worker->qxl, false); > + display_channel_update_qxl_running(worker->display_channel, > false); > > display_channel_free_glz_drawables(worker->display_channel); > display_channel_flush_all_surfaces(worker->display_channel); > @@ -616,8 +553,8 @@ static void handle_dev_start(void *opaque, void > *payload) > display_channel_wait_for_migrate_data(worker- > >display_channel); > } > red_qxl_set_running(worker->qxl, true); > + display_channel_update_qxl_running(worker->display_channel, > true); > worker->event_timeout = 0; > - guest_set_client_capabilities(worker); > } > > static void handle_dev_wakeup(void *opaque, void *payload) > @@ -694,46 +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"); > - > - dcc = dcc_new(display, client, stream, migration, caps, > - worker->image_compression, worker->jpeg_state, > worker->zlib_glz_state); > - 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"); > - > - spice_debug("disconnect display client"); > - > - 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; > @@ -1261,12 +1158,11 @@ RedWorker* red_worker_new(QXLInstance *qxl) > init_info.n_surfac > es); > 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; _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel