Acked-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx> On Tue, 2019-03-26 at 19:10 +0000, Frediano Ziglio wrote: > Currently channel threading/handling is spread between RedQxl, > RedWorker and RedChannel. > Move more to RedChannel simplify RedQxl and RedWorker. > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > --- > server/cursor-channel.c | 4 +- > server/cursor-channel.h | 4 +- > server/display-channel.c | 2 + > server/display-channel.h | 1 + > server/red-channel.c | 112 +++++++++++++++++++++++++++++++-- > server/red-qxl.c | 110 +------------------------------- > server/red-replay-qxl.c | 3 - > server/red-stream-device.c | 2 +- > server/red-worker.c | 126 +++++++++------------------------ > ---- > server/red-worker.h | 46 +++----------- > 10 files changed, 157 insertions(+), 253 deletions(-) > > diff --git a/server/cursor-channel.c b/server/cursor-channel.c > index 4220084f..e8af01b0 100644 > --- a/server/cursor-channel.c > +++ b/server/cursor-channel.c > @@ -228,7 +228,8 @@ static void > cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it > } > > CursorChannel* cursor_channel_new(RedsState *server, int id, > - const SpiceCoreInterfaceInternal > *core) > + const SpiceCoreInterfaceInternal > *core, > + Dispatcher *dispatcher) > { > spice_debug("create cursor channel"); > return g_object_new(TYPE_CURSOR_CHANNEL, > @@ -238,6 +239,7 @@ CursorChannel* cursor_channel_new(RedsState > *server, int id, > "id", id, > "migration-flags", 0, > "handle-acks", TRUE, > + "dispatcher", dispatcher, > NULL); > } > > diff --git a/server/cursor-channel.h b/server/cursor-channel.h > index 603c2c0a..767325ea 100644 > --- a/server/cursor-channel.h > +++ b/server/cursor-channel.h > @@ -21,6 +21,7 @@ > > #include "common-graphics-channel.h" > #include "red-parse-qxl.h" > +#include "dispatcher.h" > > G_BEGIN_DECLS > > @@ -57,7 +58,8 @@ GType cursor_channel_get_type(void) G_GNUC_CONST; > * CursorChannel thread. > */ > CursorChannel* cursor_channel_new(RedsState *server, int id, > - const SpiceCoreInterfaceInternal > *core); > + const SpiceCoreInterfaceInternal > *core, > + Dispatcher *dispatcher); > > void cursor_channel_reset (CursorChannel > *cursor); > void cursor_channel_do_init (CursorChannel > *cursor); > diff --git a/server/display-channel.c b/server/display-channel.c > index e179abfd..cb052bfc 100644 > --- a/server/display-channel.c > +++ b/server/display-channel.c > @@ -2227,6 +2227,7 @@ static SpiceCanvas > *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t su > DisplayChannel* display_channel_new(RedsState *reds, > QXLInstance *qxl, > const SpiceCoreInterfaceInternal > *core, > + Dispatcher *dispatcher, > int migrate, int stream_video, > GArray *video_codecs, > uint32_t n_surfaces) > @@ -2246,6 +2247,7 @@ DisplayChannel* display_channel_new(RedsState > *reds, > "n-surfaces", n_surfaces, > "video-codecs", video_codecs, > "handle-acks", TRUE, > + "dispatcher", dispatcher, > NULL); > if (display) { > display_channel_set_stream_video(display, stream_video); > diff --git a/server/display-channel.h b/server/display-channel.h > index 948018cf..f64da0bd 100644 > --- a/server/display-channel.h > +++ b/server/display-channel.h > @@ -99,6 +99,7 @@ struct Drawable { > DisplayChannel* display_channel_new > (RedsState *reds, > > QXLInstance *qxl, > > const SpiceCoreInterfaceInternal *core, > + > Dispatcher *dispatcher, > > int migrate, > > int stream_video, > > GArray *video_codecs, > diff --git a/server/red-channel.c b/server/red-channel.c > index 1d88739e..8d4992fa 100644 > --- a/server/red-channel.c > +++ b/server/red-channel.c > @@ -90,6 +90,12 @@ struct RedChannelPrivate > // TODO: when different channel_clients are in different threads > // from Channel -> need to protect! > pthread_t thread_id; > + /* Setting dispatcher allows the channel to execute code in the > right > + * thread. > + * thread_id will be used to check the channel thread and > automatically > + * use the dispatcher if the thread is different. > + */ > + Dispatcher *dispatcher; > RedsState *reds; > RedStatNode stat; > }; > @@ -103,7 +109,8 @@ enum { > PROP_TYPE, > PROP_ID, > PROP_HANDLE_ACKS, > - PROP_MIGRATION_FLAGS > + PROP_MIGRATION_FLAGS, > + PROP_DISPATCHER, > }; > > static void > @@ -134,6 +141,9 @@ red_channel_get_property(GObject *object, > case PROP_MIGRATION_FLAGS: > g_value_set_uint(value, self->priv->migration_flags); > break; > + case PROP_DISPATCHER: > + g_value_set_object(value, self->priv->dispatcher); > + break; > default: > G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, > pspec); > } > @@ -167,6 +177,10 @@ red_channel_set_property(GObject *object, > case PROP_MIGRATION_FLAGS: > self->priv->migration_flags = g_value_get_uint(value); > break; > + case PROP_DISPATCHER: > + g_clear_object(&self->priv->dispatcher); > + self->priv->dispatcher = g_value_dup_object(value); > + break; > default: > G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, > pspec); > } > @@ -177,6 +191,7 @@ red_channel_finalize(GObject *object) > { > RedChannel *self = RED_CHANNEL(object); > > + g_clear_object(&self->priv->dispatcher); > red_channel_capabilities_reset(&self->priv->local_caps); > > G_OBJECT_CLASS(red_channel_parent_class)->finalize(object); > @@ -279,6 +294,14 @@ red_channel_class_init(RedChannelClass *klass) > G_PARAM_CONSTRUCT_ONLY | > G_PARAM_STATIC_STRINGS); > g_object_class_install_property(object_class, > PROP_MIGRATION_FLAGS, spec); > + > + spec = g_param_spec_object("dispatcher", "dispatcher", > + "Dispatcher bound to channel thread", > + TYPE_DISPATCHER, > + G_PARAM_STATIC_STRINGS > + | G_PARAM_READWRITE > + | G_PARAM_CONSTRUCT_ONLY); > + g_object_class_install_property(object_class, PROP_DISPATCHER, > spec); > } > > static void > @@ -483,11 +506,49 @@ void red_channel_disconnect(RedChannel > *channel) > red_channel_foreach_client(channel, > red_channel_client_disconnect); > } > > +typedef struct RedMessageConnect { > + RedChannel *channel; > + RedClient *client; > + RedStream *stream; > + RedChannelCapabilities caps; > + int migration; > +} RedMessageConnect; > + > +static void handle_dispatcher_connect(void *opaque, void *payload) > +{ > + RedMessageConnect *msg = payload; > + RedChannel *channel = msg->channel; > + > + channel->priv->client_cbs.connect(channel, msg->client, msg- > >stream, > + msg->migration, &msg->caps); > + g_object_unref(msg->client); > + red_channel_capabilities_reset(&msg->caps); > +} > + > void red_channel_connect(RedChannel *channel, RedClient *client, > RedStream *stream, int migration, > RedChannelCapabilities *caps) > { > - channel->priv->client_cbs.connect(channel, client, stream, > migration, caps); > + if (channel->priv->dispatcher == NULL || > + pthread_equal(pthread_self(), channel->priv->thread_id)) { > + channel->priv->client_cbs.connect(channel, client, stream, > migration, caps); > + return; > + } > + > + Dispatcher *dispatcher = channel->priv->dispatcher; > + > + // get a reference potentially the main channel can be destroyed > in > + // the main thread causing RedClient to be destroyed before > using it > + RedMessageConnect payload = { > + .channel = channel, > + .client = g_object_ref(client), > + .stream = stream, > + .migration = migration > + }; > + red_channel_capabilities_init(&payload.caps, caps); > + > + dispatcher_send_message_custom(dispatcher, > handle_dispatcher_connect, > + &payload, sizeof(payload), > false); > } > > GList *red_channel_get_clients(RedChannel *channel) > @@ -690,12 +751,55 @@ const RedChannelCapabilities* > red_channel_get_local_capabilities(RedChannel *sel > return &self->priv->local_caps; > } > > +typedef struct RedMessageMigrate { > + RedChannelClient *rcc; > +} RedMessageMigrate; > + > +static void handle_dispatcher_migrate(void *opaque, void *payload) > +{ > + RedMessageMigrate *msg = payload; > + RedChannel *channel = red_channel_client_get_channel(msg->rcc); > + > + channel->priv->client_cbs.migrate(msg->rcc); > + g_object_unref(msg->rcc); > +} > + > void red_channel_migrate_client(RedChannel *channel, > RedChannelClient *rcc) > { > - channel->priv->client_cbs.migrate(rcc); > + if (channel->priv->dispatcher == NULL || > + pthread_equal(pthread_self(), channel->priv->thread_id)) { > + channel->priv->client_cbs.migrate(rcc); > + return; > + } > + > + RedMessageMigrate payload = { .rcc = g_object_ref(rcc) }; > + dispatcher_send_message_custom(channel->priv->dispatcher, > handle_dispatcher_migrate, > + &payload, sizeof(payload), > false); > +} > + > +typedef struct RedMessageDisconnect { > + RedChannelClient *rcc; > +} RedMessageDisconnect; > + > +static void handle_dispatcher_disconnect(void *opaque, void > *payload) > +{ > + RedMessageDisconnect *msg = payload; > + RedChannel *channel = red_channel_client_get_channel(msg->rcc); > + > + channel->priv->client_cbs.disconnect(msg->rcc); > } > > void red_channel_disconnect_client(RedChannel *channel, > RedChannelClient *rcc) > { > - channel->priv->client_cbs.disconnect(rcc); > + if (channel->priv->dispatcher == NULL || > + pthread_equal(pthread_self(), channel->priv->thread_id)) { > + channel->priv->client_cbs.disconnect(rcc); > + return; > + } > + > + // TODO: we turned it to be sync, due to client_destroy . Should > we support async? - for this we will need ref count > + // for channels > + RedMessageDisconnect payload = { .rcc = rcc }; > + dispatcher_send_message_custom(channel->priv->dispatcher, > handle_dispatcher_disconnect, > + &payload, sizeof(payload), true); > } > diff --git a/server/red-qxl.c b/server/red-qxl.c > index 789817f6..8274be56 100644 > --- a/server/red-qxl.c > +++ b/server/red-qxl.c > @@ -75,102 +75,6 @@ int red_qxl_check_qxl_version(QXLInstance *qxl, > int major, int minor) > ((qxl_major == major) && (qxl_minor >= minor))); > } > > -static void red_qxl_set_display_peer(RedChannel *channel, RedClient > *client, > - RedStream *stream, int > migration, > - RedChannelCapabilities *caps) > -{ > - RedWorkerMessageDisplayConnect payload = {0,}; > - Dispatcher *dispatcher; > - > - spice_debug("%s", ""); > - dispatcher = (Dispatcher *)g_object_get_data(G_OBJECT(channel), > "dispatcher"); > - // get a reference potentially the main channel can be destroyed > in > - // the main thread causing RedClient to be destroyed before > using it > - payload.client = g_object_ref(client); > - payload.stream = stream; > - payload.migration = migration; > - red_channel_capabilities_init(&payload.caps, caps); > - > - dispatcher_send_message(dispatcher, > - RED_WORKER_MESSAGE_DISPLAY_CONNECT, > - &payload); > -} > - > -static void red_qxl_disconnect_display_peer(RedChannelClient *rcc) > -{ > - RedWorkerMessageDisplayDisconnect payload; > - Dispatcher *dispatcher; > - RedChannel *channel = red_channel_client_get_channel(rcc); > - > - dispatcher = (Dispatcher *)g_object_get_data(G_OBJECT(channel), > "dispatcher"); > - > - payload.rcc = rcc; > - > - // TODO: we turned it to be sync, due to client_destroy . Should > we support async? - for this we will need ref count > - // for channels > - dispatcher_send_message(dispatcher, > - RED_WORKER_MESSAGE_DISPLAY_DISCONNECT, > - &payload); > -} > - > -static void red_qxl_display_migrate(RedChannelClient *rcc) > -{ > - RedWorkerMessageDisplayMigrate payload; > - Dispatcher *dispatcher; > - RedChannel *channel = red_channel_client_get_channel(rcc); > - > - dispatcher = (Dispatcher *)g_object_get_data(G_OBJECT(channel), > "dispatcher"); > - payload.rcc = g_object_ref(rcc); > - dispatcher_send_message(dispatcher, > - RED_WORKER_MESSAGE_DISPLAY_MIGRATE, > - &payload); > -} > - > -static void red_qxl_set_cursor_peer(RedChannel *channel, RedClient > *client, RedStream *stream, > - int migration, > - RedChannelCapabilities *caps) > -{ > - RedWorkerMessageCursorConnect payload = {0,}; > - Dispatcher *dispatcher = (Dispatcher > *)g_object_get_data(G_OBJECT(channel), "dispatcher"); > - // get a reference potentially the main channel can be destroyed > in > - // the main thread causing RedClient to be destroyed before > using it > - payload.client = g_object_ref(client); > - payload.stream = stream; > - payload.migration = migration; > - red_channel_capabilities_init(&payload.caps, caps); > - > - dispatcher_send_message(dispatcher, > - RED_WORKER_MESSAGE_CURSOR_CONNECT, > - &payload); > -} > - > -static void red_qxl_disconnect_cursor_peer(RedChannelClient *rcc) > -{ > - RedWorkerMessageCursorDisconnect payload; > - Dispatcher *dispatcher; > - RedChannel *channel = red_channel_client_get_channel(rcc); > - > - dispatcher = (Dispatcher *)g_object_get_data(G_OBJECT(channel), > "dispatcher"); > - payload.rcc = rcc; > - > - dispatcher_send_message(dispatcher, > - RED_WORKER_MESSAGE_CURSOR_DISCONNECT, > - &payload); > -} > - > -static void red_qxl_cursor_migrate(RedChannelClient *rcc) > -{ > - RedWorkerMessageCursorMigrate payload; > - Dispatcher *dispatcher; > - RedChannel *channel = red_channel_client_get_channel(rcc); > - > - dispatcher = (Dispatcher *)g_object_get_data(G_OBJECT(channel), > "dispatcher"); > - payload.rcc = g_object_ref(rcc); > - dispatcher_send_message(dispatcher, > - RED_WORKER_MESSAGE_CURSOR_MIGRATE, > - &payload); > -} > - > static void red_qxl_update_area(QXLState *qxl_state, uint32_t > surface_id, > QXLRect *qxl_area, QXLRect > *qxl_dirty_rects, > uint32_t num_dirty_rects, uint32_t > clear_dirty_region) > @@ -914,8 +818,6 @@ size_t red_qxl_get_monitors_count(const > QXLInstance *qxl) > void red_qxl_init(RedsState *reds, QXLInstance *qxl) > { > QXLState *qxl_state; > - ClientCbs client_cursor_cbs = { NULL, }; > - ClientCbs client_display_cbs = { NULL, }; > > spice_return_if_fail(qxl != NULL); > > @@ -948,17 +850,7 @@ void red_qxl_init(RedsState *reds, QXLInstance > *qxl) > qxl_state->max_monitors = UINT_MAX; > qxl->st = qxl_state; > > - // TODO: move to their respective channel files > - client_cursor_cbs.connect = red_qxl_set_cursor_peer; > - client_cursor_cbs.disconnect = red_qxl_disconnect_cursor_peer; > - client_cursor_cbs.migrate = red_qxl_cursor_migrate; > - > - client_display_cbs.connect = red_qxl_set_display_peer; > - client_display_cbs.disconnect = red_qxl_disconnect_display_peer; > - client_display_cbs.migrate = red_qxl_display_migrate; > - > - qxl_state->worker = red_worker_new(qxl, &client_cursor_cbs, > - &client_display_cbs); > + qxl_state->worker = red_worker_new(qxl); > > red_worker_run(qxl_state->worker); > } > diff --git a/server/red-replay-qxl.c b/server/red-replay-qxl.c > index 4884e97e..8124c1fd 100644 > --- a/server/red-replay-qxl.c > +++ b/server/red-replay-qxl.c > @@ -1283,9 +1283,6 @@ static void replay_handle_dev_input(QXLWorker > *worker, SpiceReplay *replay, > break; > case RED_WORKER_MESSAGE_UPDATE: > // XXX do anything? we record the correct bitmaps already. > - case RED_WORKER_MESSAGE_DISPLAY_CONNECT: > - // we want to ignore this one - it is sent on client > connection, we > - // shall have our own clients > case RED_WORKER_MESSAGE_WAKEUP: > // safe to ignore > break; > diff --git a/server/red-stream-device.c b/server/red-stream-device.c > index 78a8c908..cf5a6e9a 100644 > --- a/server/red-stream-device.c > +++ b/server/red-stream-device.c > @@ -696,7 +696,7 @@ stream_device_create_channel(StreamDevice *dev) > > StreamChannel *stream_channel = stream_channel_new(reds, id); > > - CursorChannel *cursor_channel = cursor_channel_new(reds, id, > core); > + CursorChannel *cursor_channel = cursor_channel_new(reds, id, > core, NULL); > ClientCbs client_cbs = { NULL, }; > client_cbs.connect = (channel_client_connect_proc) > cursor_channel_connect; > client_cbs.migrate = cursor_channel_client_migrate; > diff --git a/server/red-worker.c b/server/red-worker.c > index 99369a0c..27fe04cc 100644 > --- a/server/red-worker.c > +++ b/server/red-worker.c > @@ -695,20 +695,19 @@ 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(void *opaque, void *payload) > +static void > +handle_dev_display_connect(RedChannel *channel, RedClient *client, > + RedStream *stream, int migration, > + RedChannelCapabilities *caps) > { > - RedWorkerMessageDisplayConnect *msg = payload; > - RedWorker *worker = opaque; > - DisplayChannel *display = worker->display_channel; > + DisplayChannel *display = DISPLAY_CHANNEL(channel); > DisplayChannelClient *dcc; > + RedWorker *worker = g_object_get_data(G_OBJECT(channel), > "worker"); > > spice_debug("connect new client"); > - spice_return_if_fail(display); > > - dcc = dcc_new(display, msg->client, msg->stream, msg->migration, > &msg->caps, > + dcc = dcc_new(display, client, stream, migration, caps, > worker->image_compression, worker->jpeg_state, > worker->zlib_glz_state); > - g_object_unref(msg->client); > - red_channel_capabilities_reset(&msg->caps); > if (!dcc) { > return; > } > @@ -717,30 +716,23 @@ static void handle_dev_display_connect(void > *opaque, void *payload) > dcc_start(dcc); > } > > -static void handle_dev_display_disconnect(void *opaque, void > *payload) > +static void > +handle_dev_display_disconnect(RedChannelClient *rcc) > { > - RedWorkerMessageDisplayDisconnect *msg = payload; > - RedChannelClient *rcc = msg->rcc; > - RedWorker *worker = opaque; > + RedChannel *channel = red_channel_client_get_channel(rcc); > + RedWorker *worker = g_object_get_data(G_OBJECT(channel), > "worker"); > > spice_debug("disconnect display client"); > - spice_assert(rcc); > > guest_set_client_capabilities(worker); > > red_channel_client_disconnect(rcc); > } > > -static void handle_dev_display_migrate(void *opaque, void *payload) > +static void handle_dev_display_migrate(RedChannelClient *rcc) > { > - RedWorkerMessageDisplayMigrate *msg = payload; > - RedWorker *worker = opaque; > - > - RedChannelClient *rcc = msg->rcc; > - spice_debug("migrate display client"); > - spice_assert(rcc); > - red_migrate_display(worker->display_channel, rcc); > - g_object_unref(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) > @@ -792,40 +784,6 @@ async_complete: > red_qxl_async_complete(worker->qxl, msg->base.cookie); > } > > -/* TODO: special, perhaps use another dispatcher? */ > -static void handle_dev_cursor_connect(void *opaque, void *payload) > -{ > - RedWorkerMessageCursorConnect *msg = payload; > - RedWorker *worker = opaque; > - > - spice_debug("cursor connect"); > - cursor_channel_connect(worker->cursor_channel, > - msg->client, msg->stream, msg->migration, > - &msg->caps); > - g_object_unref(msg->client); > - red_channel_capabilities_reset(&msg->caps); > -} > - > -static void handle_dev_cursor_disconnect(void *opaque, void > *payload) > -{ > - RedWorkerMessageCursorDisconnect *msg = payload; > - RedChannelClient *rcc = msg->rcc; > - > - spice_debug("disconnect cursor client"); > - spice_return_if_fail(rcc); > - red_channel_client_disconnect(rcc); > -} > - > -static void handle_dev_cursor_migrate(void *opaque, void *payload) > -{ > - RedWorkerMessageCursorMigrate *msg = payload; > - RedChannelClient *rcc = msg->rcc; > - > - spice_debug("migrate cursor client"); > - cursor_channel_client_migrate(rcc); > - g_object_unref(rcc); > -} > - > static void handle_dev_set_compression(void *opaque, void *payload) > { > RedWorkerMessageSetCompression *msg = payload; > @@ -999,36 +957,6 @@ static void worker_dispatcher_record(void > *opaque, uint32_t message_type, void * > static void register_callbacks(Dispatcher *dispatcher) > { > /* TODO: register cursor & display specific msg in respective > channel files */ > - dispatcher_register_handler(dispatcher, > - RED_WORKER_MESSAGE_DISPLAY_CONNECT, > - handle_dev_display_connect, > - sizeof(RedWorkerMessageDisplayConnec > t), > - false); > - dispatcher_register_handler(dispatcher, > - RED_WORKER_MESSAGE_DISPLAY_DISCONNEC > T, > - handle_dev_display_disconnect, > - sizeof(RedWorkerMessageDisplayDiscon > nect), > - true); > - dispatcher_register_handler(dispatcher, > - RED_WORKER_MESSAGE_DISPLAY_MIGRATE, > - handle_dev_display_migrate, > - sizeof(RedWorkerMessageDisplayMigrat > e), > - false); > - dispatcher_register_handler(dispatcher, > - RED_WORKER_MESSAGE_CURSOR_CONNECT, > - handle_dev_cursor_connect, > - sizeof(RedWorkerMessageCursorConnect > ), > - false); > - dispatcher_register_handler(dispatcher, > - RED_WORKER_MESSAGE_CURSOR_DISCONNECT > , > - handle_dev_cursor_disconnect, > - sizeof(RedWorkerMessageCursorDisconn > ect), > - true); > - dispatcher_register_handler(dispatcher, > - RED_WORKER_MESSAGE_CURSOR_MIGRATE, > - handle_dev_cursor_migrate, > - sizeof(RedWorkerMessageCursorMigrate > ), > - false); > dispatcher_register_handler(dispatcher, > RED_WORKER_MESSAGE_UPDATE, > handle_dev_update, > @@ -1260,9 +1188,7 @@ static GSourceFuncs worker_source_funcs = { > .dispatch = worker_source_dispatch, > }; > > -RedWorker* red_worker_new(QXLInstance *qxl, > - const ClientCbs *client_cursor_cbs, > - const ClientCbs *client_display_cbs) > +RedWorker* red_worker_new(QXLInstance *qxl) > { > QXLDevInitInfo init_info; > RedWorker *worker; > @@ -1318,21 +1244,31 @@ RedWorker* red_worker_new(QXLInstance *qxl, > worker->event_timeout = INF_EVENT_WAIT; > > worker->cursor_channel = cursor_channel_new(reds, qxl->id, > - &worker->core); > + &worker->core, > dispatcher); > channel = RED_CHANNEL(worker->cursor_channel); > red_channel_init_stat_node(channel, &worker->stat, > "cursor_channel"); > - red_channel_register_client_cbs(channel, client_cursor_cbs); > - g_object_set_data(G_OBJECT(channel), "dispatcher", dispatcher); > + > + ClientCbs client_cursor_cbs = { NULL, }; > + client_cursor_cbs.connect = (channel_client_connect_proc) > cursor_channel_connect; > + client_cursor_cbs.disconnect = NULL; > + client_cursor_cbs.migrate = cursor_channel_client_migrate; > + red_channel_register_client_cbs(channel, &client_cursor_cbs); > > // TODO: handle seamless migration. Temp, setting migrate to > FALSE > - worker->display_channel = display_channel_new(reds, qxl, > &worker->core, FALSE, > + worker->display_channel = display_channel_new(reds, qxl, > &worker->core, dispatcher, > + FALSE, > reds_get_streaming > _video(reds), > reds_get_video_cod > ecs(reds), > init_info.n_surfac > es); > channel = RED_CHANNEL(worker->display_channel); > red_channel_init_stat_node(channel, &worker->stat, > "display_channel"); > - red_channel_register_client_cbs(channel, client_display_cbs); > - g_object_set_data(G_OBJECT(channel), "dispatcher", dispatcher); > + 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; > + red_channel_register_client_cbs(channel, &client_display_cbs); > > return worker; > } > diff --git a/server/red-worker.h b/server/red-worker.h > index 767329da..3d2841ba 100644 > --- a/server/red-worker.h > +++ b/server/red-worker.h > @@ -28,9 +28,7 @@ > > typedef struct RedWorker RedWorker; > > -RedWorker* red_worker_new(QXLInstance *qxl, > - const ClientCbs *client_cursor_cbs, > - const ClientCbs *client_display_cbs); > +RedWorker* red_worker_new(QXLInstance *qxl); > bool red_worker_run(RedWorker *worker); > void red_worker_free(RedWorker *worker); > > @@ -51,14 +49,14 @@ enum { > RED_WORKER_MESSAGE_OOM, > RED_WORKER_MESSAGE_READY, /* unused */ > > - RED_WORKER_MESSAGE_DISPLAY_CONNECT, > - RED_WORKER_MESSAGE_DISPLAY_DISCONNECT, > - RED_WORKER_MESSAGE_DISPLAY_MIGRATE, > + RED_WORKER_MESSAGE_DISPLAY_CONNECT_DEPRECATED, > + RED_WORKER_MESSAGE_DISPLAY_DISCONNECT_DEPRECATED, > + RED_WORKER_MESSAGE_DISPLAY_MIGRATE_DEPRECATED, > RED_WORKER_MESSAGE_START, > RED_WORKER_MESSAGE_STOP, > - RED_WORKER_MESSAGE_CURSOR_CONNECT, > - RED_WORKER_MESSAGE_CURSOR_DISCONNECT, > - RED_WORKER_MESSAGE_CURSOR_MIGRATE, > + RED_WORKER_MESSAGE_CURSOR_CONNECT_DEPRECATED, > + RED_WORKER_MESSAGE_CURSOR_DISCONNECT_DEPRECATED, > + RED_WORKER_MESSAGE_CURSOR_MIGRATE_DEPRECATED, > RED_WORKER_MESSAGE_SET_COMPRESSION, > RED_WORKER_MESSAGE_SET_STREAMING_VIDEO, > RED_WORKER_MESSAGE_SET_MOUSE_MODE, > @@ -97,36 +95,6 @@ enum { > RED_WORKER_MESSAGE_COUNT // LAST > }; > > -typedef struct RedWorkerMessageDisplayConnect { > - RedClient * client; > - RedStream * stream; > - RedChannelCapabilities caps; // red_worker should reset > - int migration; > -} RedWorkerMessageDisplayConnect; > - > -typedef struct RedWorkerMessageDisplayDisconnect { > - RedChannelClient *rcc; > -} RedWorkerMessageDisplayDisconnect; > - > -typedef struct RedWorkerMessageDisplayMigrate { > - RedChannelClient *rcc; > -} RedWorkerMessageDisplayMigrate; > - > -typedef struct RedWorkerMessageCursorConnect { > - RedClient *client; > - RedStream *stream; > - int migration; > - RedChannelCapabilities caps; // red_worker should reset > -} RedWorkerMessageCursorConnect; > - > -typedef struct RedWorkerMessageCursorDisconnect { > - RedChannelClient *rcc; > -} RedWorkerMessageCursorDisconnect; > - > -typedef struct RedWorkerMessageCursorMigrate { > - RedChannelClient *rcc; > -} RedWorkerMessageCursorMigrate; > - > typedef struct RedWorkerMessageUpdate { > uint32_t surface_id; > QXLRect * qxl_area; _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel