From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> Signed-off-by: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> --- server/Makefile.am | 1 + server/cursor-channel.c | 464 ++++++++++++++++++++++++++++++++++++ server/cursor-channel.h | 26 +++ server/red_worker.c | 611 +++++------------------------------------------- server/red_worker.h | 92 ++++++++ 5 files changed, 635 insertions(+), 559 deletions(-) create mode 100644 server/cursor-channel.c diff --git a/server/Makefile.am b/server/Makefile.am index 42b222b..19ff3c8 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -108,6 +108,7 @@ libspice_server_la_SOURCES = \ red_worker.c \ red_worker.h \ display-channel.h \ + cursor-channel.c \ cursor-channel.h \ reds.c \ reds.h \ diff --git a/server/cursor-channel.c b/server/cursor-channel.c new file mode 100644 index 0000000..7ba4a7d --- /dev/null +++ b/server/cursor-channel.c @@ -0,0 +1,464 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#include <glib.h> +#include "common/generated_server_marshallers.h" +#include "cursor-channel.h" + +#define RCC_TO_CCC(rcc) SPICE_CONTAINEROF((rcc), CursorChannelClient, common.base) + +#define CLIENT_CURSOR_CACHE +#include "cache_item.tmpl.c" +#undef CLIENT_CURSOR_CACHE + +static inline CursorItem *alloc_cursor_item(void) +{ + CursorItem *cursor_item; + + cursor_item = g_slice_new0(CursorItem); + cursor_item->refs = 1; + + return cursor_item; +} + +CursorItem *cursor_item_new(RedCursorCmd *cmd, uint32_t group_id) +{ + CursorItem *cursor_item; + + spice_return_val_if_fail(cmd != NULL, NULL); + spice_warn_if(!(cursor_item = alloc_cursor_item())); + + cursor_item->group_id = group_id; + cursor_item->red_cursor = cmd; + + return cursor_item; +} + +void cursor_item_unref(QXLInstance *qxl, CursorItem *cursor) +{ + if (!--cursor->refs) { + QXLReleaseInfoExt release_info_ext; + RedCursorCmd *cursor_cmd; + + cursor_cmd = cursor->red_cursor; + release_info_ext.group_id = cursor->group_id; + release_info_ext.info = cursor_cmd->release_info; + qxl->st->qif->release_resource(qxl, release_info_ext); + red_put_cursor_cmd(cursor_cmd); + free(cursor_cmd); + + g_slice_free(CursorItem, cursor); + } +} + +static void cursor_set_item(CursorChannel *cursor, CursorItem *item) +{ + if (cursor->item) + cursor_item_unref(red_worker_get_qxl(cursor->common.worker), cursor->item); + + if (item) + item->refs++; + + cursor->item = item; +} + +static PipeItem *new_cursor_pipe_item(RedChannelClient *rcc, void *data, int num) +{ + CursorPipeItem *item = spice_malloc0(sizeof(CursorPipeItem)); + + red_channel_pipe_item_init(rcc->channel, &item->base, PIPE_ITEM_TYPE_CURSOR); + item->refs = 1; + item->cursor_item = data; + item->cursor_item->refs++; + return &item->base; +} + +typedef struct { + void *data; + uint32_t size; +} AddBufInfo; + +static void add_buf_from_info(SpiceMarshaller *m, AddBufInfo *info) +{ + if (info->data) { + spice_marshaller_add_ref(m, info->data, info->size); + } +} + +static void cursor_fill(CursorChannelClient *ccc, SpiceCursor *red_cursor, + CursorItem *cursor, AddBufInfo *addbuf) +{ + RedCursorCmd *cursor_cmd; + addbuf->data = NULL; + + if (!cursor) { + red_cursor->flags = SPICE_CURSOR_FLAGS_NONE; + return; + } + + cursor_cmd = cursor->red_cursor; + *red_cursor = cursor_cmd->u.set.shape; + + if (red_cursor->header.unique) { + if (red_cursor_cache_find(ccc, red_cursor->header.unique)) { + red_cursor->flags |= SPICE_CURSOR_FLAGS_FROM_CACHE; + return; + } + if (red_cursor_cache_add(ccc, red_cursor->header.unique, 1)) { + red_cursor->flags |= SPICE_CURSOR_FLAGS_CACHE_ME; + } + } + + if (red_cursor->data_size) { + addbuf->data = red_cursor->data; + addbuf->size = red_cursor->data_size; + } +} + + +static void red_reset_cursor_cache(RedChannelClient *rcc) +{ + red_cursor_cache_reset(RCC_TO_CCC(rcc), CLIENT_CURSOR_CACHE_SIZE); +} + +void cursor_channel_disconnect(RedChannel *channel) +{ + if (!channel || !red_channel_is_connected(channel)) { + return; + } + red_channel_apply_clients(channel, red_reset_cursor_cache); + red_channel_disconnect(channel); +} + + +static void put_cursor_pipe_item(CursorChannelClient *ccc, CursorPipeItem *pipe_item) +{ + spice_assert(pipe_item); + + if (--pipe_item->refs) { + return; + } + + spice_assert(!pipe_item_is_linked(&pipe_item->base)); + + cursor_item_unref(red_worker_get_qxl(ccc->common.worker), pipe_item->cursor_item); + free(pipe_item); +} + +static void cursor_channel_client_on_disconnect(RedChannelClient *rcc) +{ + if (!rcc) { + return; + } + red_reset_cursor_cache(rcc); +} + +// TODO: share code between before/after_push since most of the items need the same +// release +static void cursor_channel_client_release_item_before_push(CursorChannelClient *ccc, + PipeItem *item) +{ + switch (item->type) { + case PIPE_ITEM_TYPE_CURSOR: { + CursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, CursorPipeItem, base); + put_cursor_pipe_item(ccc, cursor_pipe_item); + break; + } + case PIPE_ITEM_TYPE_INVAL_ONE: + case PIPE_ITEM_TYPE_VERB: + case PIPE_ITEM_TYPE_CURSOR_INIT: + case PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE: + free(item); + break; + default: + spice_error("invalid pipe item type"); + } +} + +static void cursor_channel_client_release_item_after_push(CursorChannelClient *ccc, + PipeItem *item) +{ + switch (item->type) { + case PIPE_ITEM_TYPE_CURSOR: { + CursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, CursorPipeItem, base); + put_cursor_pipe_item(ccc, cursor_pipe_item); + break; + } + default: + spice_critical("invalid item type"); + } +} + +static void red_marshall_cursor_init(RedChannelClient *rcc, SpiceMarshaller *base_marshaller, + PipeItem *pipe_item) +{ + CursorChannel *cursor_channel; + CursorChannelClient *ccc = RCC_TO_CCC(rcc); + SpiceMsgCursorInit msg; + AddBufInfo info; + + spice_assert(rcc); + cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base); + + red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_INIT, NULL); + msg.visible = cursor_channel->cursor_visible; + msg.position = cursor_channel->cursor_position; + msg.trail_length = cursor_channel->cursor_trail_length; + msg.trail_frequency = cursor_channel->cursor_trail_frequency; + + cursor_fill(ccc, &msg.cursor, cursor_channel->item, &info); + spice_marshall_msg_cursor_init(base_marshaller, &msg); + add_buf_from_info(base_marshaller, &info); +} + +static void cursor_marshall(RedChannelClient *rcc, + SpiceMarshaller *m, CursorPipeItem *cursor_pipe_item) +{ + CursorChannel *cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base); + CursorChannelClient *ccc = RCC_TO_CCC(rcc); + CursorItem *cursor = cursor_pipe_item->cursor_item; + PipeItem *pipe_item = &cursor_pipe_item->base; + RedCursorCmd *cmd; + + spice_assert(cursor_channel); + + cmd = cursor->red_cursor; + switch (cmd->type) { + case QXL_CURSOR_MOVE: + { + SpiceMsgCursorMove cursor_move; + red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_MOVE, pipe_item); + cursor_move.position = cmd->u.position; + spice_marshall_msg_cursor_move(m, &cursor_move); + break; + } + case QXL_CURSOR_SET: + { + SpiceMsgCursorSet cursor_set; + AddBufInfo info; + + red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_SET, pipe_item); + cursor_set.position = cmd->u.set.position; + cursor_set.visible = cursor_channel->cursor_visible; + + cursor_fill(ccc, &cursor_set.cursor, cursor, &info); + spice_marshall_msg_cursor_set(m, &cursor_set); + add_buf_from_info(m, &info); + break; + } + case QXL_CURSOR_HIDE: + red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_HIDE, pipe_item); + break; + case QXL_CURSOR_TRAIL: + { + SpiceMsgCursorTrail cursor_trail; + + red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_TRAIL, pipe_item); + cursor_trail.length = cmd->u.trail.length; + cursor_trail.frequency = cmd->u.trail.frequency; + spice_marshall_msg_cursor_trail(m, &cursor_trail); + } + break; + default: + spice_error("bad cursor command %d", cmd->type); + } +} + +static inline void red_marshall_inval(RedChannelClient *rcc, + SpiceMarshaller *base_marshaller, CacheItem *cach_item) +{ + SpiceMsgDisplayInvalOne inval_one; + + red_channel_client_init_send_data(rcc, cach_item->inval_type, NULL); + inval_one.id = *(uint64_t *)&cach_item->id; + + spice_marshall_msg_cursor_inval_one(base_marshaller, &inval_one); +} + +static void red_cursor_marshall_inval(RedChannelClient *rcc, + SpiceMarshaller *m, CacheItem *cach_item) +{ + spice_assert(rcc); + red_marshall_inval(rcc, m, cach_item); +} + +static void cursor_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item) +{ + SpiceMarshaller *m = red_channel_client_get_marshaller(rcc); + CursorChannelClient *ccc = RCC_TO_CCC(rcc); + + switch (pipe_item->type) { + case PIPE_ITEM_TYPE_CURSOR: + cursor_marshall(rcc, m, SPICE_CONTAINEROF(pipe_item, CursorPipeItem, base)); + break; + case PIPE_ITEM_TYPE_INVAL_ONE: + red_cursor_marshall_inval(rcc, m, (CacheItem *)pipe_item); + break; + case PIPE_ITEM_TYPE_VERB: + red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb); + break; + case PIPE_ITEM_TYPE_CURSOR_INIT: + red_reset_cursor_cache(rcc); + red_marshall_cursor_init(rcc, m, pipe_item); + break; + case PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE: + red_reset_cursor_cache(rcc); + red_marshall_verb(rcc, SPICE_MSG_CURSOR_INVAL_ALL); + break; + default: + spice_error("invalid pipe item type"); + } + + cursor_channel_client_release_item_before_push(ccc, pipe_item); + red_channel_client_begin_send_message(rcc); +} + +static CursorPipeItem *cursor_pipe_item_ref(CursorPipeItem *item) +{ + spice_assert(item); + item->refs++; + return item; +} + + +static void cursor_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item) +{ + CursorPipeItem *cursor_pipe_item; + spice_assert(item); + cursor_pipe_item = SPICE_CONTAINEROF(item, CursorPipeItem, base); + cursor_pipe_item_ref(cursor_pipe_item); +} + +static void cursor_channel_release_item(RedChannelClient *rcc, PipeItem *item, int item_pushed) +{ + CursorChannelClient *ccc = RCC_TO_CCC(rcc); + + spice_assert(item); + + if (item_pushed) { + cursor_channel_client_release_item_after_push(ccc, item); + } else { + spice_debug("not pushed (%d)", item->type); + cursor_channel_client_release_item_before_push(ccc, item); + } +} + +CursorChannel* cursor_channel_new(RedWorker *worker, int migrate) +{ + CursorChannel* cursor; + + spice_info("create cursor channel"); + cursor = (CursorChannel *)__new_channel( + worker, sizeof(CursorChannel), + SPICE_CHANNEL_CURSOR, + 0, + cursor_channel_client_on_disconnect, + cursor_channel_send_item, + cursor_channel_hold_pipe_item, + cursor_channel_release_item, + red_channel_client_handle_message, + NULL, + NULL, + NULL); + + cursor->cursor_visible = TRUE; + cursor->mouse_mode = SPICE_MOUSE_MODE_SERVER; + + return cursor; +} + +CursorChannelClient *cursor_channel_client_new(CommonChannel *common, + RedClient *client, RedsStream *stream, + int mig_target, + uint32_t *common_caps, int num_common_caps, + uint32_t *caps, int num_caps) +{ + CursorChannelClient *ccc = + (CursorChannelClient*)common_channel_client_create( + sizeof(CursorChannelClient), common, client, stream, + mig_target, + FALSE, + common_caps, + num_common_caps, + caps, + num_caps); + + if (!ccc) { + return NULL; + } + ring_init(&ccc->cursor_cache_lru); + ccc->cursor_cache_available = CLIENT_CURSOR_CACHE_SIZE; + return ccc; +} + +void cursor_channel_process_cmd(CursorChannel *cursor, RedCursorCmd *cursor_cmd, + uint32_t group_id) +{ + CursorItem *cursor_item; + int cursor_show = FALSE; + + cursor_item = cursor_item_new(cursor_cmd, group_id); + + switch (cursor_cmd->type) { + case QXL_CURSOR_SET: + cursor->cursor_visible = cursor_cmd->u.set.visible; + cursor_set_item(cursor, cursor_item); + break; + case QXL_CURSOR_MOVE: + cursor_show = !cursor->cursor_visible; + cursor->cursor_visible = TRUE; + cursor->cursor_position = cursor_cmd->u.position; + break; + case QXL_CURSOR_HIDE: + cursor->cursor_visible = FALSE; + break; + case QXL_CURSOR_TRAIL: + cursor->cursor_trail_length = cursor_cmd->u.trail.length; + cursor->cursor_trail_frequency = cursor_cmd->u.trail.frequency; + break; + default: + spice_error("invalid cursor command %u", cursor_cmd->type); + } + + if (red_channel_is_connected(&cursor->common.base) && (cursor->mouse_mode == SPICE_MOUSE_MODE_SERVER || + cursor_cmd->type != QXL_CURSOR_MOVE || cursor_show)) { + red_channel_pipes_new_add(&cursor->common.base, new_cursor_pipe_item, + (void*)cursor_item); + } + cursor_item_unref(red_worker_get_qxl(cursor->common.worker), cursor_item); +} + +void cursor_channel_reset(CursorChannel *cursor) +{ + cursor_set_item(cursor, NULL); + cursor->cursor_visible = TRUE; + cursor->cursor_position.x = cursor->cursor_position.y = 0; + cursor->cursor_trail_length = cursor->cursor_trail_frequency = 0; + + if (red_channel_is_connected(&cursor->common.base)) { + red_channel_pipes_add_type(&cursor->common.base, + PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE); + if (!cursor->common.during_target_migrate) { + red_pipes_add_verb(&cursor->common.base, SPICE_MSG_CURSOR_RESET); + } + if (!red_channel_wait_all_sent(&cursor->common.base, + DISPLAY_CLIENT_TIMEOUT)) { + red_channel_apply_clients(&cursor->common.base, + red_channel_client_disconnect_if_pending_send); + } + } +} diff --git a/server/cursor-channel.h b/server/cursor-channel.h index 4654bcb..2c19859 100644 --- a/server/cursor-channel.h +++ b/server/cursor-channel.h @@ -18,7 +18,11 @@ #ifndef CURSOR_CHANNEL_H_ # define CURSOR_CHANNEL_H_ +#include "spice.h" +#include "reds.h" #include "red_worker.h" +#include "red_parse_qxl.h" +#include "cache-item.h" #include "stat.h" #define CLIENT_CURSOR_CACHE_SIZE 256 @@ -59,6 +63,13 @@ typedef struct CursorChannelClient { typedef struct CursorChannel { CommonChannel common; // Must be the first thing + CursorItem *item; + int cursor_visible; + SpicePoint16 cursor_position; + uint16_t cursor_trail_length; + uint16_t cursor_trail_frequency; + uint32_t mouse_mode; + #ifdef RED_STATISTICS StatNodeRef stat; #endif @@ -66,5 +77,20 @@ typedef struct CursorChannel { G_STATIC_ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE); +CursorChannel* cursor_channel_new (RedWorker *worker, int migrate); +void cursor_channel_disconnect (RedChannel *channel); +void cursor_channel_reset (CursorChannel *cursor); +void cursor_channel_process_cmd (CursorChannel *cursor, RedCursorCmd *cursor_cmd, + uint32_t group_id); + +CursorItem* cursor_item_new (RedCursorCmd *cmd, uint32_t group_id); +void cursor_item_unref (QXLInstance *qxl, CursorItem *cursor); + + +CursorChannelClient *cursor_channel_client_new(CommonChannel *common, + RedClient *client, RedsStream *stream, + int mig_target, + uint32_t *common_caps, int num_common_caps, + uint32_t *caps, int num_caps); #endif /* CURSOR_CHANNEL_H_ */ diff --git a/server/red_worker.c b/server/red_worker.c index 5e982db..8ae0878 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -265,33 +265,6 @@ struct SpiceWatch { void *watch_func_opaque; }; -enum { - PIPE_ITEM_TYPE_DRAW = PIPE_ITEM_TYPE_CHANNEL_BASE, - PIPE_ITEM_TYPE_INVAL_ONE, - PIPE_ITEM_TYPE_CURSOR, - PIPE_ITEM_TYPE_CURSOR_INIT, - PIPE_ITEM_TYPE_IMAGE, - PIPE_ITEM_TYPE_STREAM_CREATE, - PIPE_ITEM_TYPE_STREAM_CLIP, - PIPE_ITEM_TYPE_STREAM_DESTROY, - PIPE_ITEM_TYPE_UPGRADE, - PIPE_ITEM_TYPE_VERB, - PIPE_ITEM_TYPE_MIGRATE_DATA, - PIPE_ITEM_TYPE_PIXMAP_SYNC, - PIPE_ITEM_TYPE_PIXMAP_RESET, - PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE, - PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE, - PIPE_ITEM_TYPE_CREATE_SURFACE, - PIPE_ITEM_TYPE_DESTROY_SURFACE, - PIPE_ITEM_TYPE_MONITORS_CONFIG, - PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT, -}; - -typedef struct VerbItem { - PipeItem base; - uint16_t verb; -} VerbItem; - #define MAX_LZ_ENCODERS MAX_CACHE_CLIENTS typedef struct SurfaceCreateItem { @@ -637,12 +610,6 @@ typedef struct RedWorker { uint32_t bits_unique; - CursorItem *cursor; - int cursor_visible; - SpicePoint16 cursor_position; - uint16_t cursor_trail_length; - uint16_t cursor_trail_frequency; - _Drawable drawables[NUM_DRAWABLES]; _Drawable *free_drawables; @@ -654,8 +621,6 @@ typedef struct RedWorker { spice_wan_compression_t jpeg_state; spice_wan_compression_t zlib_glz_state; - uint32_t mouse_mode; - uint32_t streaming_video; Stream streams_buf[NUM_STREAMS]; Stream *free_streams; @@ -732,7 +697,6 @@ static void red_draw_drawable(RedWorker *worker, Drawable *item); static void red_update_area(RedWorker *worker, const SpiceRect *area, int surface_id); static void red_update_area_till(RedWorker *worker, const SpiceRect *area, int surface_id, Drawable *last); -static void cursor_item_unref(RedWorker *worker, CursorItem *cursor); static inline void release_drawable(RedWorker *worker, Drawable *item); static void red_display_release_stream(RedWorker *worker, StreamAgent *agent); static inline void red_detach_stream(RedWorker *worker, Stream *stream, int detach_sized); @@ -751,15 +715,11 @@ static ImageItem *red_add_surface_area_image(DisplayChannelClient *dcc, int surf static BitmapGradualType _get_bitmap_graduality_level(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_id); static inline int _stride_is_extra(SpiceBitmap *bitmap); -static void red_disconnect_cursor(RedChannel *channel); + static void display_channel_client_release_item_before_push(DisplayChannelClient *dcc, PipeItem *item); static void display_channel_client_release_item_after_push(DisplayChannelClient *dcc, PipeItem *item); -static void cursor_channel_client_release_item_before_push(CursorChannelClient *ccc, - PipeItem *item); -static void cursor_channel_client_release_item_after_push(CursorChannelClient *ccc, - PipeItem *item); static void red_push_monitors_config(DisplayChannelClient *dcc); @@ -769,21 +729,6 @@ static void red_push_monitors_config(DisplayChannelClient *dcc); * given a channel, iterate over it's clients */ -/* a generic safe for loop macro */ -#define SAFE_FOREACH(link, next, cond, ring, data, get_data) \ - for ((((link) = ((cond) ? ring_get_head(ring) : NULL)), \ - ((next) = ((link) ? ring_next((ring), (link)) : NULL)), \ - ((data) = ((link)? (get_data) : NULL))); \ - (link); \ - (((link) = (next)), \ - ((next) = ((link) ? ring_next((ring), (link)) : NULL)), \ - ((data) = ((link)? (get_data) : NULL)))) - -#define LINK_TO_RCC(ptr) SPICE_CONTAINEROF(ptr, RedChannelClient, channel_link) -#define RCC_FOREACH_SAFE(link, next, rcc, channel) \ - SAFE_FOREACH(link, next, channel, &(channel)->clients, rcc, LINK_TO_RCC(link)) - - #define LINK_TO_DCC(ptr) SPICE_CONTAINEROF(ptr, DisplayChannelClient, \ common.base.channel_link) #define DCC_FOREACH_SAFE(link, next, dcc, channel) \ @@ -911,6 +856,13 @@ static void print_compress_stats(DisplayChannel *display_channel) #endif +QXLInstance* red_worker_get_qxl(RedWorker *worker) +{ + spice_return_val_if_fail(worker != NULL, NULL); + + return worker->qxl; +} + static MonitorsConfig *monitors_config_getref(MonitorsConfig *monitors_config) { monitors_config->refs++; @@ -1066,28 +1018,9 @@ static void show_draw_item(RedWorker *worker, DrawItem *draw_item, const char *p draw_item->base.rgn.extents.y2); } -static void red_pipe_add_verb(RedChannelClient* rcc, uint16_t verb) -{ - VerbItem *item = spice_new(VerbItem, 1); - - red_channel_pipe_item_init(rcc->channel, &item->base, PIPE_ITEM_TYPE_VERB); - item->verb = verb; - red_channel_client_pipe_add(rcc, &item->base); -} - static inline void red_create_surface_item(DisplayChannelClient *dcc, int surface_id); static void red_push_surface_image(DisplayChannelClient *dcc, int surface_id); -static void red_pipes_add_verb(RedChannel *channel, uint16_t verb) -{ - RedChannelClient *rcc; - RingItem *link, *next; - - RCC_FOREACH_SAFE(link, next, rcc, channel) { - red_pipe_add_verb(rcc, verb); - } -} - static inline void red_handle_drawable_surfaces_client_synced( DisplayChannelClient *dcc, Drawable *drawable) { @@ -1320,10 +1253,6 @@ static void common_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32 } } -#define CLIENT_CURSOR_CACHE -#include "cache_item.tmpl.c" -#undef CLIENT_CURSOR_CACHE - #define CLIENT_PALETTE_CACHE #include "cache_item.tmpl.c" #undef CLIENT_PALETTE_CACHE @@ -1333,11 +1262,6 @@ static void red_reset_palette_cache(DisplayChannelClient *dcc) red_palette_cache_reset(dcc, CLIENT_PALETTE_CACHE_SIZE); } -static void red_reset_cursor_cache(RedChannelClient *rcc) -{ - red_cursor_cache_reset(RCC_TO_CCC(rcc), CLIENT_CURSOR_CACHE_SIZE); -} - static inline Drawable *alloc_drawable(RedWorker *worker) { Drawable *drawable; @@ -4231,123 +4155,6 @@ static void red_update_area(RedWorker *worker, const SpiceRect *area, int surfac validate_area(worker, area, surface_id); } -static void cursor_item_unref(RedWorker *worker, CursorItem *cursor) -{ - if (!--cursor->refs) { - QXLReleaseInfoExt release_info_ext; - RedCursorCmd *cursor_cmd; - - cursor_cmd = cursor->red_cursor; - release_info_ext.group_id = cursor->group_id; - release_info_ext.info = cursor_cmd->release_info; - worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext); - red_put_cursor_cmd(cursor_cmd); - free(cursor_cmd); - - g_slice_free(CursorItem, cursor); - } -} - -static void red_set_cursor(RedWorker *worker, CursorItem *cursor) -{ - if (worker->cursor) { - cursor_item_unref(worker, worker->cursor); - } - ++cursor->refs; - worker->cursor = cursor; -} - -static inline CursorItem *alloc_cursor_item(void) -{ - CursorItem *cursor_item; - - cursor_item = g_slice_new0(CursorItem); - cursor_item->refs = 1; - - return cursor_item; -} - -static CursorItem *cursor_item_new(RedCursorCmd *cmd, uint32_t group_id) -{ - CursorItem *cursor_item; - - spice_return_val_if_fail(cmd != NULL, NULL); - spice_warn_if(!(cursor_item = alloc_cursor_item())); - - cursor_item->group_id = group_id; - cursor_item->red_cursor = cmd; - - return cursor_item; -} - -static CursorPipeItem *cursor_pipe_item_ref(CursorPipeItem *item) -{ - spice_assert(item); - item->refs++; - return item; -} - -static PipeItem *new_cursor_pipe_item(RedChannelClient *rcc, void *data, int num) -{ - CursorPipeItem *item = spice_malloc0(sizeof(CursorPipeItem)); - - red_channel_pipe_item_init(rcc->channel, &item->base, PIPE_ITEM_TYPE_CURSOR); - item->refs = 1; - item->cursor_item = data; - item->cursor_item->refs++; - return &item->base; -} - -static void put_cursor_pipe_item(CursorChannelClient *ccc, CursorPipeItem *pipe_item) -{ - spice_assert(pipe_item); - - if (--pipe_item->refs) { - return; - } - - spice_assert(!pipe_item_is_linked(&pipe_item->base)); - - cursor_item_unref(ccc->common.worker, pipe_item->cursor_item); - free(pipe_item); -} - -static void qxl_process_cursor(RedWorker *worker, RedCursorCmd *cursor_cmd, uint32_t group_id) -{ - CursorItem *cursor_item; - int cursor_show = FALSE; - - cursor_item = cursor_item_new(cursor_cmd, group_id); - - switch (cursor_cmd->type) { - case QXL_CURSOR_SET: - worker->cursor_visible = cursor_cmd->u.set.visible; - red_set_cursor(worker, cursor_item); - break; - case QXL_CURSOR_MOVE: - cursor_show = !worker->cursor_visible; - worker->cursor_visible = TRUE; - worker->cursor_position = cursor_cmd->u.position; - break; - case QXL_CURSOR_HIDE: - worker->cursor_visible = FALSE; - break; - case QXL_CURSOR_TRAIL: - worker->cursor_trail_length = cursor_cmd->u.trail.length; - worker->cursor_trail_frequency = cursor_cmd->u.trail.frequency; - break; - default: - spice_error("invalid cursor command %u", cursor_cmd->type); - } - - if (cursor_is_connected(worker) && (worker->mouse_mode == SPICE_MOUSE_MODE_SERVER || - cursor_cmd->type != QXL_CURSOR_MOVE || cursor_show)) { - red_channel_pipes_new_add(&worker->cursor_channel->common.base, new_cursor_pipe_item, - (void*)cursor_item); - } - cursor_item_unref(worker, cursor_item); -} - static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty) { QXLCommandExt ext_cmd; @@ -4386,7 +4193,7 @@ static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ri break; } - qxl_process_cursor(worker, cursor, ext_cmd.group_id); + cursor_channel_process_cmd(worker->cursor_channel, cursor, ext_cmd.group_id); break; } default: @@ -4650,11 +4457,6 @@ static void red_push_surface_image(DisplayChannelClient *dcc, int surface_id) red_channel_client_push(&dcc->common.base); } -typedef struct { - void *data; - uint32_t size; -} AddBufInfo; - static void marshaller_add_compressed(SpiceMarshaller *m, RedCompressBuf *comp_buf, size_t size) { @@ -4670,13 +4472,6 @@ static void marshaller_add_compressed(SpiceMarshaller *m, } -static void add_buf_from_info(SpiceMarshaller *m, AddBufInfo *info) -{ - if (info->data) { - spice_marshaller_add_ref(m, info->data, info->size); - } -} - static void fill_base(SpiceMarshaller *base_marshaller, Drawable *drawable) { SpiceMsgDisplayBase base; @@ -6368,36 +6163,6 @@ static void fill_attr(SpiceMarshaller *m, SpiceLineAttr *attr, uint32_t group_id } } -static void cursor_fill(CursorChannelClient *ccc, SpiceCursor *red_cursor, - CursorItem *cursor, AddBufInfo *addbuf) -{ - RedCursorCmd *cursor_cmd; - addbuf->data = NULL; - - if (!cursor) { - red_cursor->flags = SPICE_CURSOR_FLAGS_NONE; - return; - } - - cursor_cmd = cursor->red_cursor; - *red_cursor = cursor_cmd->u.set.shape; - - if (red_cursor->header.unique) { - if (red_cursor_cache_find(ccc, red_cursor->header.unique)) { - red_cursor->flags |= SPICE_CURSOR_FLAGS_FROM_CACHE; - return; - } - if (red_cursor_cache_add(ccc, red_cursor->header.unique, 1)) { - red_cursor->flags |= SPICE_CURSOR_FLAGS_CACHE_ME; - } - } - - if (red_cursor->data_size) { - addbuf->data = red_cursor->data; - addbuf->size = red_cursor->data_size; - } -} - static inline void red_display_reset_send_data(DisplayChannelClient *dcc) { red_display_reset_compress_buf(dcc); @@ -8153,23 +7918,6 @@ static inline void marshall_qxl_drawable(RedChannelClient *rcc, red_lossy_marshall_qxl_drawable(display_channel->common.worker, rcc, m, dpi); } -static inline void red_marshall_verb(RedChannelClient *rcc, uint16_t verb) -{ - spice_assert(rcc); - red_channel_client_init_send_data(rcc, verb, NULL); -} - -static inline void red_marshall_inval(RedChannelClient *rcc, - SpiceMarshaller *base_marshaller, CacheItem *cach_item) -{ - SpiceMsgDisplayInvalOne inval_one; - - red_channel_client_init_send_data(rcc, cach_item->inval_type, NULL); - inval_one.id = *(uint64_t *)&cach_item->id; - - spice_marshall_msg_cursor_inval_one(base_marshaller, &inval_one); -} - static void display_channel_marshall_migrate_data_surfaces(DisplayChannelClient *dcc, SpiceMarshaller *m, int lossy) @@ -8545,93 +8293,6 @@ static void red_display_marshall_stream_end(RedChannelClient *rcc, spice_marshall_msg_display_stream_destroy(base_marshaller, &destroy); } -static void red_cursor_marshall_inval(RedChannelClient *rcc, - SpiceMarshaller *m, CacheItem *cach_item) -{ - spice_assert(rcc); - red_marshall_inval(rcc, m, cach_item); -} - -static void red_marshall_cursor_init(RedChannelClient *rcc, SpiceMarshaller *base_marshaller, - PipeItem *pipe_item) -{ - CursorChannel *cursor_channel; - CursorChannelClient *ccc = RCC_TO_CCC(rcc); - RedWorker *worker; - SpiceMsgCursorInit msg; - AddBufInfo info; - - spice_assert(rcc); - cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base); - worker = cursor_channel->common.worker; - - red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_INIT, NULL); - msg.visible = worker->cursor_visible; - msg.position = worker->cursor_position; - msg.trail_length = worker->cursor_trail_length; - msg.trail_frequency = worker->cursor_trail_frequency; - - cursor_fill(ccc, &msg.cursor, worker->cursor, &info); - spice_marshall_msg_cursor_init(base_marshaller, &msg); - add_buf_from_info(base_marshaller, &info); -} - -static void cursor_marshall(RedChannelClient *rcc, - SpiceMarshaller *m, CursorPipeItem *cursor_pipe_item) -{ - CursorChannel *cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base); - CursorChannelClient *ccc = RCC_TO_CCC(rcc); - CursorItem *cursor = cursor_pipe_item->cursor_item; - PipeItem *pipe_item = &cursor_pipe_item->base; - RedCursorCmd *cmd; - RedWorker *worker; - - spice_assert(cursor_channel); - - worker = cursor_channel->common.worker; - - cmd = cursor->red_cursor; - switch (cmd->type) { - case QXL_CURSOR_MOVE: - { - SpiceMsgCursorMove cursor_move; - red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_MOVE, pipe_item); - cursor_move.position = cmd->u.position; - spice_marshall_msg_cursor_move(m, &cursor_move); - break; - } - case QXL_CURSOR_SET: - { - SpiceMsgCursorSet cursor_set; - AddBufInfo info; - - red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_SET, pipe_item); - cursor_set.position = cmd->u.set.position; - cursor_set.visible = worker->cursor_visible; - - cursor_fill(ccc, &cursor_set.cursor, cursor, &info); - spice_marshall_msg_cursor_set(m, &cursor_set); - add_buf_from_info(m, &info); - break; - } - case QXL_CURSOR_HIDE: - red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_HIDE, pipe_item); - break; - case QXL_CURSOR_TRAIL: - { - SpiceMsgCursorTrail cursor_trail; - - red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_TRAIL, pipe_item); - cursor_trail.length = cmd->u.trail.length; - cursor_trail.frequency = cmd->u.trail.frequency; - spice_marshall_msg_cursor_trail(m, &cursor_trail); - } - break; - default: - spice_error("bad cursor command %d", cmd->type); - } -} - static void red_marshall_surface_create(RedChannelClient *rcc, SpiceMarshaller *base_marshaller, SpiceMsgSurfaceCreate *surface_create) { @@ -8700,6 +8361,17 @@ static void red_marshall_stream_activate_report(RedChannelClient *rcc, spice_marshall_msg_display_stream_activate_report(base_marshaller, &msg); } +static inline void red_marshall_inval(RedChannelClient *rcc, + SpiceMarshaller *base_marshaller, CacheItem *cach_item) +{ + SpiceMsgDisplayInvalOne inval_one; + + red_channel_client_init_send_data(rcc, cach_item->inval_type, NULL); + inval_one.id = *(uint64_t *)&cach_item->id; + + spice_marshall_msg_cursor_inval_one(base_marshaller, &inval_one); +} + static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item) { SpiceMarshaller *m = red_channel_client_get_marshaller(rcc); @@ -8789,37 +8461,6 @@ static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item } } -static void cursor_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item) -{ - SpiceMarshaller *m = red_channel_client_get_marshaller(rcc); - CursorChannelClient *ccc = RCC_TO_CCC(rcc); - - switch (pipe_item->type) { - case PIPE_ITEM_TYPE_CURSOR: - cursor_marshall(rcc, m, SPICE_CONTAINEROF(pipe_item, CursorPipeItem, base)); - break; - case PIPE_ITEM_TYPE_INVAL_ONE: - red_cursor_marshall_inval(rcc, m, (CacheItem *)pipe_item); - break; - case PIPE_ITEM_TYPE_VERB: - red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb); - break; - case PIPE_ITEM_TYPE_CURSOR_INIT: - red_reset_cursor_cache(rcc); - red_marshall_cursor_init(rcc, m, pipe_item); - break; - case PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE: - red_reset_cursor_cache(rcc); - red_marshall_verb(rcc, SPICE_MSG_CURSOR_INVAL_ALL); - break; - default: - spice_error("invalid pipe item type"); - } - - cursor_channel_client_release_item_before_push(ccc, pipe_item); - red_channel_client_begin_send_message(rcc); -} - static inline void red_push(RedWorker *worker) { if (worker->cursor_channel) { @@ -9267,7 +8908,8 @@ static inline void flush_cursor_commands(RedWorker *worker) red_channel_send(channel); if (red_now() >= end_time) { spice_warning("flush cursor timeout"); - red_disconnect_cursor(channel); + cursor_channel_disconnect(channel); + worker->cursor_channel = NULL; } else { sleep_count++; usleep(DISPLAY_CLIENT_RETRY_INTERVAL); @@ -9878,16 +9520,16 @@ SpiceCoreInterface worker_core = { .watch_remove = worker_watch_remove, }; -static CommonChannelClient *common_channel_client_create(int size, - CommonChannel *common, - RedClient *client, - RedsStream *stream, - int mig_target, - int monitor_latency, - uint32_t *common_caps, - int num_common_caps, - uint32_t *caps, - int num_caps) +CommonChannelClient *common_channel_client_create(int size, + CommonChannel *common, + RedClient *client, + RedsStream *stream, + int mig_target, + int monitor_latency, + uint32_t *common_caps, + int num_common_caps, + uint32_t *caps, + int num_caps) { RedChannelClient *rcc = red_channel_client_create(size, &common->base, client, stream, monitor_latency, @@ -9930,40 +9572,16 @@ DisplayChannelClient *display_channel_client_create(CommonChannel *common, return dcc; } -CursorChannelClient *cursor_channel_create_rcc(CommonChannel *common, - RedClient *client, RedsStream *stream, - int mig_target, - uint32_t *common_caps, int num_common_caps, - uint32_t *caps, int num_caps) -{ - CursorChannelClient *ccc = - (CursorChannelClient*)common_channel_client_create( - sizeof(CursorChannelClient), common, client, stream, - mig_target, - FALSE, - common_caps, - num_common_caps, - caps, - num_caps); - - if (!ccc) { - return NULL; - } - ring_init(&ccc->cursor_cache_lru); - ccc->cursor_cache_available = CLIENT_CURSOR_CACHE_SIZE; - return ccc; -} - -static RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_type, - int migration_flags, - channel_disconnect_proc on_disconnect, - channel_send_pipe_item_proc send_item, - channel_hold_pipe_item_proc hold_item, - channel_release_pipe_item_proc release_item, - channel_handle_parsed_proc handle_parsed, - channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark, - channel_handle_migrate_data_proc handle_migrate_data, - channel_handle_migrate_data_get_serial_proc migrate_get_serial) +RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_type, + int migration_flags, + channel_disconnect_proc on_disconnect, + channel_send_pipe_item_proc send_item, + channel_hold_pipe_item_proc hold_item, + channel_release_pipe_item_proc release_item, + channel_handle_parsed_proc handle_parsed, + channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark, + channel_handle_migrate_data_proc handle_migrate_data, + channel_handle_migrate_data_get_serial_proc migrate_get_serial) { RedChannel *channel = NULL; CommonChannel *common; @@ -10288,28 +9906,6 @@ static void handle_new_display_channel(RedWorker *worker, RedClient *client, Red on_new_display_channel_client(dcc); } -static void cursor_channel_client_on_disconnect(RedChannelClient *rcc) -{ - if (!rcc) { - return; - } - red_reset_cursor_cache(rcc); -} - -static void red_disconnect_cursor(RedChannel *channel) -{ - CommonChannel *common; - - if (!channel || !red_channel_is_connected(channel)) { - return; - } - common = SPICE_CONTAINEROF(channel, CommonChannel, base); - spice_assert(channel == (RedChannel *)common->worker->cursor_channel); - common->worker->cursor_channel = NULL; - red_channel_apply_clients(channel, red_reset_cursor_cache); - red_channel_disconnect(channel); -} - static void red_migrate_cursor(RedWorker *worker, RedChannelClient *rcc) { if (red_channel_client_is_connected(rcc)) { @@ -10333,84 +9929,6 @@ static void on_new_cursor_channel(RedWorker *worker, RedChannelClient *rcc) } } -static void cursor_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item) -{ - CursorPipeItem *cursor_pipe_item; - spice_assert(item); - cursor_pipe_item = SPICE_CONTAINEROF(item, CursorPipeItem, base); - cursor_pipe_item_ref(cursor_pipe_item); -} - -// TODO: share code between before/after_push since most of the items need the same -// release -static void cursor_channel_client_release_item_before_push(CursorChannelClient *ccc, - PipeItem *item) -{ - switch (item->type) { - case PIPE_ITEM_TYPE_CURSOR: { - CursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, CursorPipeItem, base); - put_cursor_pipe_item(ccc, cursor_pipe_item); - break; - } - case PIPE_ITEM_TYPE_INVAL_ONE: - case PIPE_ITEM_TYPE_VERB: - case PIPE_ITEM_TYPE_CURSOR_INIT: - case PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE: - free(item); - break; - default: - spice_error("invalid pipe item type"); - } -} - -static void cursor_channel_client_release_item_after_push(CursorChannelClient *ccc, - PipeItem *item) -{ - switch (item->type) { - case PIPE_ITEM_TYPE_CURSOR: { - CursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, CursorPipeItem, base); - put_cursor_pipe_item(ccc, cursor_pipe_item); - break; - } - default: - spice_critical("invalid item type"); - } -} - -static void cursor_channel_release_item(RedChannelClient *rcc, PipeItem *item, int item_pushed) -{ - CursorChannelClient *ccc = RCC_TO_CCC(rcc); - - spice_assert(item); - - if (item_pushed) { - cursor_channel_client_release_item_after_push(ccc, item); - } else { - spice_debug("not pushed (%d)", item->type); - cursor_channel_client_release_item_before_push(ccc, item); - } -} - -static void cursor_channel_new(RedWorker *worker, int migrate) -{ - if (worker->cursor_channel != NULL) { - return; - } - spice_info("create cursor channel"); - worker->cursor_channel = (CursorChannel *)__new_channel( - worker, sizeof(*worker->cursor_channel), - SPICE_CHANNEL_CURSOR, - 0, - cursor_channel_client_on_disconnect, - cursor_channel_send_item, - cursor_channel_hold_pipe_item, - cursor_channel_release_item, - red_channel_client_handle_message, - NULL, - NULL, - NULL); -} - static void red_connect_cursor(RedWorker *worker, RedClient *client, RedsStream *stream, int migrate, uint32_t *common_caps, int num_common_caps, @@ -10425,7 +9943,7 @@ static void red_connect_cursor(RedWorker *worker, RedClient *client, RedsStream } channel = worker->cursor_channel; spice_info("add cursor channel client"); - ccc = cursor_channel_create_rcc(&channel->common, client, stream, + ccc = cursor_channel_client_new(&channel->common, client, stream, migrate, common_caps, num_common_caps, caps, num_caps); @@ -10590,31 +10108,6 @@ void handle_dev_destroy_surface_wait(void *opaque, void *payload) dev_destroy_surface_wait(worker, msg->surface_id); } -static inline void red_cursor_reset(RedWorker *worker) -{ - if (worker->cursor) { - cursor_item_unref(worker, worker->cursor); - worker->cursor = NULL; - } - - worker->cursor_visible = TRUE; - worker->cursor_position.x = worker->cursor_position.y = 0; - worker->cursor_trail_length = worker->cursor_trail_frequency = 0; - - if (cursor_is_connected(worker)) { - red_channel_pipes_add_type(&worker->cursor_channel->common.base, - PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE); - if (!worker->cursor_channel->common.during_target_migrate) { - red_pipes_add_verb(&worker->cursor_channel->common.base, SPICE_MSG_CURSOR_RESET); - } - if (!red_channel_wait_all_sent(&worker->cursor_channel->common.base, - DISPLAY_CLIENT_TIMEOUT)) { - red_channel_apply_clients(&worker->cursor_channel->common.base, - red_channel_client_disconnect_if_pending_send); - } - } -} - /* called upon device reset */ /* TODO: split me*/ @@ -10645,7 +10138,7 @@ static inline void dev_destroy_surfaces(RedWorker *worker) red_display_clear_glz_drawables(worker->display_channel); - red_cursor_reset(worker); + cursor_channel_reset(worker->cursor_channel); } void handle_dev_destroy_surfaces(void *opaque, void *payload) @@ -10835,7 +10328,7 @@ static void dev_destroy_primary_surface(RedWorker *worker, uint32_t surface_id) spice_assert(!worker->surfaces[surface_id].context.canvas); - red_cursor_reset(worker); + cursor_channel_reset(worker->cursor_channel); } void handle_dev_destroy_primary_surface(void *opaque, void *payload) @@ -11005,7 +10498,7 @@ void handle_dev_oom(void *opaque, void *payload) void handle_dev_reset_cursor(void *opaque, void *payload) { - red_cursor_reset((RedWorker *)opaque); + cursor_channel_reset(((RedWorker*)opaque)->cursor_channel); } void handle_dev_reset_image_cache(void *opaque, void *payload) @@ -11150,7 +10643,9 @@ void handle_dev_cursor_channel_create(void *opaque, void *payload) RedChannel *red_channel; // TODO: handle seemless migration. Temp, setting migrate to FALSE - cursor_channel_new(worker, FALSE); + if (!worker->cursor_channel) { + worker->cursor_channel = cursor_channel_new(worker, FALSE); + } red_channel = &worker->cursor_channel->common.base; send_data(worker->channel, &red_channel, sizeof(RedChannel *)); } @@ -11266,8 +10761,8 @@ void handle_dev_set_mouse_mode(void *opaque, void *payload) RedWorkerMessageSetMouseMode *msg = payload; RedWorker *worker = opaque; - worker->mouse_mode = msg->mode; - spice_info("mouse mode %u", worker->mouse_mode); + worker->cursor_channel->mouse_mode = msg->mode; + spice_info("mouse mode %u", worker->cursor_channel->mouse_mode); } void handle_dev_add_memslot_async(void *opaque, void *payload) @@ -11304,7 +10799,7 @@ static int loadvm_command(RedWorker *worker, QXLCommandExt *ext) free(cursor_cmd); return FALSE; } - qxl_process_cursor(worker, cursor_cmd, ext->group_id); + cursor_channel_process_cmd(worker->cursor_channel, cursor_cmd, ext->group_id); break; case QXL_CMD_SURFACE: surface_cmd = spice_new0(RedSurfaceCmd, 1); @@ -11581,12 +11076,10 @@ RedWorker* red_worker_new(QXLInstance *qxl, RedDispatcher *red_dispatcher) if (worker->record_fd) { dispatcher_register_universal_handler(dispatcher, worker_dispatcher_record); } - worker->cursor_visible = TRUE; spice_assert(num_renderers > 0); worker->num_renderers = num_renderers; memcpy(worker->renderers, renderers, sizeof(worker->renderers)); worker->renderer = RED_RENDERER_INVALID; - worker->mouse_mode = SPICE_MOUSE_MODE_SERVER; worker->image_compression = image_compression; worker->jpeg_state = jpeg_state; worker->zlib_glz_state = zlib_glz_state; diff --git a/server/red_worker.h b/server/red_worker.h index 0f5fac7..502283e 100644 --- a/server/red_worker.h +++ b/server/red_worker.h @@ -32,6 +32,8 @@ typedef struct CommonChannelClient { int is_low_bandwidth; } CommonChannelClient; +#define DISPLAY_CLIENT_TIMEOUT 30000000000ULL //nano + #define CHANNEL_RECEIVE_BUF_SIZE 1024 typedef struct CommonChannel { RedChannel base; // Must be the first thing @@ -45,7 +47,97 @@ typedef struct CommonChannel { of the primary surface) */ } CommonChannel; +enum { + PIPE_ITEM_TYPE_DRAW = PIPE_ITEM_TYPE_CHANNEL_BASE, + PIPE_ITEM_TYPE_INVAL_ONE, + PIPE_ITEM_TYPE_CURSOR, + PIPE_ITEM_TYPE_CURSOR_INIT, + PIPE_ITEM_TYPE_IMAGE, + PIPE_ITEM_TYPE_STREAM_CREATE, + PIPE_ITEM_TYPE_STREAM_CLIP, + PIPE_ITEM_TYPE_STREAM_DESTROY, + PIPE_ITEM_TYPE_UPGRADE, + PIPE_ITEM_TYPE_VERB, + PIPE_ITEM_TYPE_MIGRATE_DATA, + PIPE_ITEM_TYPE_PIXMAP_SYNC, + PIPE_ITEM_TYPE_PIXMAP_RESET, + PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE, + PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE, + PIPE_ITEM_TYPE_CREATE_SURFACE, + PIPE_ITEM_TYPE_DESTROY_SURFACE, + PIPE_ITEM_TYPE_MONITORS_CONFIG, + PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT, +}; + +typedef struct VerbItem { + PipeItem base; + uint16_t verb; +} VerbItem; + +static inline void red_marshall_verb(RedChannelClient *rcc, uint16_t verb) +{ + spice_assert(rcc); + red_channel_client_init_send_data(rcc, verb, NULL); +} + +static inline void red_pipe_add_verb(RedChannelClient* rcc, uint16_t verb) +{ + VerbItem *item = spice_new(VerbItem, 1); + + red_channel_pipe_item_init(rcc->channel, &item->base, PIPE_ITEM_TYPE_VERB); + item->verb = verb; + red_channel_client_pipe_add(rcc, &item->base); +} + +/* a generic safe for loop macro */ +#define SAFE_FOREACH(link, next, cond, ring, data, get_data) \ + for ((((link) = ((cond) ? ring_get_head(ring) : NULL)), \ + ((next) = ((link) ? ring_next((ring), (link)) : NULL)), \ + ((data) = ((link)? (get_data) : NULL))); \ + (link); \ + (((link) = (next)), \ + ((next) = ((link) ? ring_next((ring), (link)) : NULL)), \ + ((data) = ((link)? (get_data) : NULL)))) + +#define LINK_TO_RCC(ptr) SPICE_CONTAINEROF(ptr, RedChannelClient, channel_link) +#define RCC_FOREACH_SAFE(link, next, rcc, channel) \ + SAFE_FOREACH(link, next, channel, &(channel)->clients, rcc, LINK_TO_RCC(link)) + + +static inline void red_pipes_add_verb(RedChannel *channel, uint16_t verb) +{ + RedChannelClient *rcc; + RingItem *link, *next; + + RCC_FOREACH_SAFE(link, next, rcc, channel) { + red_pipe_add_verb(rcc, verb); + } +} + RedWorker* red_worker_new(QXLInstance *qxl, RedDispatcher *red_dispatcher); bool red_worker_run(RedWorker *worker); +QXLInstance* red_worker_get_qxl(RedWorker *worker); + +CommonChannelClient *common_channel_client_create(int size, + CommonChannel *common, + RedClient *client, + RedsStream *stream, + int mig_target, + int monitor_latency, + uint32_t *common_caps, + int num_common_caps, + uint32_t *caps, + int num_caps); + +RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_type, + int migration_flags, + channel_disconnect_proc on_disconnect, + channel_send_pipe_item_proc send_item, + channel_hold_pipe_item_proc hold_item, + channel_release_pipe_item_proc release_item, + channel_handle_parsed_proc handle_parsed, + channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark, + channel_handle_migrate_data_proc handle_migrate_data, + channel_handle_migrate_data_get_serial_proc migrate_get_serial); #endif -- 2.4.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel