On Mon, Oct 26, 2015 at 07:01:11AM -0400, Frediano Ziglio wrote: > > > > > From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> > > > > Also fix warning due to unexpected pipe item type > > > > The specific item type that was not being handled was > > PIPE_ITEM_TYPE_INVAL_ONE (#102). This item type is used by the cursor > > channel, but the analogous item for the display channel is > > PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE. Use this value instead. > > > > The exact warning follows: > > > > (/usr/bin/qemu-kvm:24458): Spice-Warning **: > > ../../server/dcc-send.c:2442:dcc_send_item: should not be reached > > (/usr/bin/qemu-kvm:24458): Spice-CRITICAL **: > > ../../server/dcc.c:1595:release_item_before_push: invalid item type > > > > Author: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> > > Date: Thu Feb 27 19:38:58 2014 +0200 > > --- > > server/Makefile.am | 3 +- > > server/cache_item.tmpl.c | 4 +- > > server/cursor-channel.c | 489 ++++++++++++++++++++++++++++++ > > server/cursor-channel.h | 103 +++++++ > > server/cursor_channel.h | 62 ---- > > server/red_dispatcher.c | 1 + > > server/red_worker.c | 751 > > ++++++----------------------------------------- > > server/red_worker.h | 71 +++++ > > 8 files changed, 759 insertions(+), 725 deletions(-) > > create mode 100644 server/cursor-channel.c > > create mode 100644 server/cursor-channel.h > > delete mode 100644 server/cursor_channel.h > > > > diff --git a/server/Makefile.am b/server/Makefile.am > > index 013188b..43bbf6f 100644 > > --- a/server/Makefile.am > > +++ b/server/Makefile.am > > @@ -108,7 +108,8 @@ libspice_server_la_SOURCES = \ > > red_worker.c \ > > red_worker.h \ > > display-channel.h \ > > - cursor_channel.h \ > > + cursor-channel.c \ > > + cursor-channel.h \ > > reds.c \ > > reds.h \ > > reds-private.h \ > > diff --git a/server/cache_item.tmpl.c b/server/cache_item.tmpl.c > > index dc314c0..ad2b579 100644 > > --- a/server/cache_item.tmpl.c > > +++ b/server/cache_item.tmpl.c > > @@ -21,6 +21,7 @@ > > #define CACHE_HASH_KEY CURSOR_CACHE_HASH_KEY > > #define CACHE_HASH_SIZE CURSOR_CACHE_HASH_SIZE > > #define CACHE_INVAL_TYPE SPICE_MSG_CURSOR_INVAL_ONE > > +#define PIPE_ITEM_TYPE PIPE_ITEM_TYPE_INVAL_ONE > > #define FUNC_NAME(name) red_cursor_cache_##name > > #define VAR_NAME(name) cursor_cache_##name > > #define CHANNEL CursorChannel > > @@ -32,6 +33,7 @@ > > #define CACHE_HASH_KEY PALETTE_CACHE_HASH_KEY > > #define CACHE_HASH_SIZE PALETTE_CACHE_HASH_SIZE > > #define CACHE_INVAL_TYPE SPICE_MSG_DISPLAY_INVAL_PALETTE > > +#define PIPE_ITEM_TYPE PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE > > #define FUNC_NAME(name) red_palette_cache_##name > > #define VAR_NAME(name) palette_cache_##name > > #define CHANNEL DisplayChannel > > @@ -78,7 +80,7 @@ static void FUNC_NAME(remove)(CHANNELCLIENT > > *channel_client, CacheItem *item) > > channel_client->VAR_NAME(items)--; > > channel_client->VAR_NAME(available) += item->size; > > > > - red_channel_pipe_item_init(&channel->common.base, &item->u.pipe_data, > > PIPE_ITEM_TYPE_INVAL_ONE); > > + red_channel_pipe_item_init(&channel->common.base, &item->u.pipe_data, > > PIPE_ITEM_TYPE); > > red_channel_client_pipe_add_tail(&channel_client->common.base, > > &item->u.pipe_data); // for now > > } > > > > diff --git a/server/cursor-channel.c b/server/cursor-channel.c > > new file mode 100644 > > index 0000000..adf7d78 > > --- /dev/null > > +++ b/server/cursor-channel.c > > @@ -0,0 +1,489 @@ > > +/* -*- 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 > > + > > +CursorItem *cursor_item_new(QXLInstance *qxl, RedCursorCmd *cmd, uint32_t > > group_id) > > +{ > > + CursorItem *cursor_item; > > + > > + spice_return_val_if_fail(cmd != NULL, NULL); > > + > > + cursor_item = g_slice_new0(CursorItem); > > + cursor_item->qxl = qxl; > > + cursor_item->refs = 1; > > + cursor_item->group_id = group_id; > > + cursor_item->red_cursor = cmd; > > + > > + return cursor_item; > > +} > > + > > +CursorItem *cursor_item_ref(CursorItem *item) > > +{ > > + spice_return_val_if_fail(item != NULL, NULL); > > + spice_return_val_if_fail(item->refs > 0, NULL); > > + > > + item->refs++; > > + > > + return item; > > +} > > + > > +void cursor_item_unref(CursorItem *item) > > +{ > > + QXLReleaseInfoExt release_info_ext; > > + RedCursorCmd *cursor_cmd; > > + > > + spice_return_if_fail(item != NULL); > > + > > + if (--item->refs) > > + return; > > + > > + cursor_cmd = item->red_cursor; > > + release_info_ext.group_id = item->group_id; > > + release_info_ext.info = cursor_cmd->release_info; > > + item->qxl->st->qif->release_resource(item->qxl, release_info_ext); > > + red_put_cursor_cmd(cursor_cmd); > > + free(cursor_cmd); > > + > > + g_slice_free(CursorItem, item); > > + > > +} > > + > > +static void cursor_set_item(CursorChannel *cursor, CursorItem *item) > > +{ > > + if (cursor->item) > > + cursor_item_unref(cursor->item); > > + > > + cursor->item = item ? cursor_item_ref(item) : NULL; > > +} > > + > > +#ifdef DEBUG_CURSORS > > +static int _cursor_count = 0; > > +#endif > > + > > +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(CursorChannel *cursor) > > +{ > > + RedChannel *channel = (RedChannel *)cursor; > > + > > + if (!channel || !red_channel_is_connected(channel)) { > > + return; > > + } > > + > > + /* TODO: use a class vdispose */ > > + 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_return_if_fail(pipe_item); > > + spice_return_if_fail(pipe_item->refs > 0); > > + > > + if (--pipe_item->refs) { > > + return; > > + } > > + > > + spice_assert(!pipe_item_is_linked(&pipe_item->base)); > > + > > + cursor_item_unref(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; > > + CursorChannelClient *ccc = RCC_TO_CCC(rcc); > > + SpiceMsgCursorInit msg; > > + AddBufInfo info; > > + > > + spice_assert(rcc); > > + cursor = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base); > > + > > + red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_INIT, NULL); > > + msg.visible = cursor->cursor_visible; > > + msg.position = cursor->cursor_position; > > + msg.trail_length = cursor->cursor_trail_length; > > + msg.trail_frequency = cursor->cursor_trail_frequency; > > + > > + cursor_fill(ccc, &msg.cursor, cursor->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 = SPICE_CONTAINEROF(rcc->channel, CursorChannel, > > common.base); > > + CursorChannelClient *ccc = RCC_TO_CCC(rcc); > > + CursorItem *item = cursor_pipe_item->cursor_item; > > + PipeItem *pipe_item = &cursor_pipe_item->base; > > + RedCursorCmd *cmd; > > + > > + spice_return_if_fail(cursor); > > + > > + cmd = item->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->cursor_visible; > > + > > + cursor_fill(ccc, &cursor_set.cursor, item, &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 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_marshall_inval(rcc, m, (CacheItem *)pipe_item); > > + break; > > + case PIPE_ITEM_TYPE_VERB: > > + red_marshall_verb(rcc, (VerbItem*)pipe_item); > > + 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_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_INVAL_ALL, > > NULL); > > + 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_return_val_if_fail(item, NULL); > > + spice_return_val_if_fail(item->refs > 0, NULL); > > + > > + item->refs++; > > + return item; > > +} > > + > > + > > +static void cursor_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem > > *item) > > +{ > > + CursorPipeItem *cursor_pipe_item; > > + > > + spice_return_if_fail(item); > > + > > + cursor_pipe_item = SPICE_CONTAINEROF(item, CursorPipeItem, base); > > + /* TODO: refcnt at PipeItem instead ? */ > > + 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) > > +{ > > + CursorChannel *cursor; > > + RedChannel *channel = NULL; > > + ChannelCbs cbs = { > > + .on_disconnect = cursor_channel_client_on_disconnect, > > + .send_item = cursor_channel_send_item, > > + .hold_item = cursor_channel_hold_pipe_item, > > + .release_item = cursor_channel_release_item > > + }; > > + > > + spice_info("create cursor channel"); > > + channel = red_worker_new_channel(worker, sizeof(CursorChannel), > > + SPICE_CHANNEL_CURSOR, 0, > > + &cbs, > > red_channel_client_handle_message); > > + > > + cursor = (CursorChannel *)channel; > > + cursor->cursor_visible = TRUE; > > + cursor->mouse_mode = SPICE_MOUSE_MODE_SERVER; > > + > > + return cursor; > > +} > > + > > +CursorChannelClient* cursor_channel_client_new(CursorChannel *cursor, > > RedClient *client, RedsStream *stream, > > + int mig_target, > > + uint32_t *common_caps, int > > num_common_caps, > > + uint32_t *caps, int num_caps) > > +{ > > + spice_return_val_if_fail(cursor, NULL); > > + spice_return_val_if_fail(client, NULL); > > + spice_return_val_if_fail(stream, NULL); > > + spice_return_val_if_fail(!num_common_caps || common_caps, NULL); > > + spice_return_val_if_fail(!num_caps || caps, NULL); > > + > > + CursorChannelClient *ccc = > > + (CursorChannelClient*)common_channel_new_client(&cursor->common, > > + > > sizeof(CursorChannelClient), > > + client, stream, > > + mig_target, > > + FALSE, > > + common_caps, > > + num_common_caps, > > + caps, > > + num_caps); > > + spice_return_val_if_fail(ccc != NULL, 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; > > + > > + spice_return_if_fail(cursor); > > + spice_return_if_fail(cursor_cmd); > > + > > + cursor_item = cursor_item_new(red_worker_get_qxl(cursor->common.worker), > > + 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_warning("invalid cursor command %u", cursor_cmd->type); > > + return; > > + } > > + > > + if (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, cursor_item); > > + } > > + > > + cursor_item_unref(cursor_item); > > +} > > + > > +void cursor_channel_reset(CursorChannel *cursor) > > +{ > > + RedChannel *channel = (RedChannel *)cursor; > > + > > + spice_return_if_fail(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(channel)) { > > + 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 > > new file mode 100644 > > index 0000000..e1ef4b6 > > --- /dev/null > > +++ b/server/cursor-channel.h > > @@ -0,0 +1,103 @@ > > +/* -*- 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/>. > > +*/ > > +#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 > > + > > +#define CURSOR_CACHE_HASH_SHIFT 8 > > +#define CURSOR_CACHE_HASH_SIZE (1 << CURSOR_CACHE_HASH_SHIFT) > > +#define CURSOR_CACHE_HASH_MASK (CURSOR_CACHE_HASH_SIZE - 1) > > +#define CURSOR_CACHE_HASH_KEY(id) ((id) & CURSOR_CACHE_HASH_MASK) > > + > > +enum { > > + PIPE_ITEM_TYPE_CURSOR = PIPE_ITEM_TYPE_COMMON_LAST, > > + PIPE_ITEM_TYPE_CURSOR_INIT, > > + PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE, > > +}; > > + > > +typedef struct CursorItem { > > + QXLInstance *qxl; > > + uint32_t group_id; > > + int refs; > > + RedCursorCmd *red_cursor; > > +} CursorItem; > > + > > +typedef struct CursorPipeItem { > > + PipeItem base; > > + CursorItem *cursor_item; > > + int refs; > > +} CursorPipeItem; > > + > > +typedef struct LocalCursor { > > + CursorItem base; > > + SpicePoint16 position; > > + uint32_t data_size; > > + SpiceCursor red_cursor; > > +} LocalCursor; > > + > > +typedef struct CursorChannelClient { > > + CommonChannelClient common; > > + > > + CacheItem *cursor_cache[CURSOR_CACHE_HASH_SIZE]; > > + Ring cursor_cache_lru; > > + long cursor_cache_available; > > + uint32_t cursor_cache_items; > > +} 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 > > +} CursorChannel; > > + > > +G_STATIC_ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE); > > + > > +CursorChannel* cursor_channel_new (RedWorker *worker); > > +void cursor_channel_disconnect (CursorChannel *cursor); > > +void cursor_channel_reset (CursorChannel *cursor); > > +void cursor_channel_process_cmd (CursorChannel *cursor, > > RedCursorCmd *cursor_cmd, > > + uint32_t group_id); > > + > > +CursorChannelClient* cursor_channel_client_new (CursorChannel *cursor, > > + RedClient *client, > > RedsStream *stream, > > + int mig_target, > > + uint32_t *common_caps, int > > num_common_caps, > > + uint32_t *caps, int > > num_caps); > > + > > +CursorItem* cursor_item_new (QXLInstance *qxl, > > RedCursorCmd *cmd, uint32_t group_id); > > +CursorItem* cursor_item_ref (CursorItem *cursor); > > +void cursor_item_unref (CursorItem *cursor); > > + > > +#endif /* CURSOR_CHANNEL_H_ */ > > diff --git a/server/cursor_channel.h b/server/cursor_channel.h > > deleted file mode 100644 > > index 0104988..0000000 > > --- a/server/cursor_channel.h > > +++ /dev/null > > @@ -1,62 +0,0 @@ > > -#ifndef CURSOR_CHANNEL_H_ > > -# define CURSOR_CHANNEL_H_ > > - > > -#include "red_worker.h" > > -#include "stat.h" > > - > > -#define CLIENT_CURSOR_CACHE_SIZE 256 > > - > > -#define CURSOR_CACHE_HASH_SHIFT 8 > > -#define CURSOR_CACHE_HASH_SIZE (1 << CURSOR_CACHE_HASH_SHIFT) > > -#define CURSOR_CACHE_HASH_MASK (CURSOR_CACHE_HASH_SIZE - 1) > > -#define CURSOR_CACHE_HASH_KEY(id) ((id) & CURSOR_CACHE_HASH_MASK) > > - > > -typedef struct CursorItem { > > - uint32_t group_id; > > - int refs; > > - RedCursorCmd *red_cursor; > > -} CursorItem; > > - > > -typedef struct CursorPipeItem { > > - PipeItem base; > > - CursorItem *cursor_item; > > - int refs; > > -} CursorPipeItem; > > - > > -typedef struct LocalCursor { > > - CursorItem base; > > - SpicePoint16 position; > > - uint32_t data_size; > > - SpiceCursor red_cursor; > > -} LocalCursor; > > - > > -typedef struct CursorChannelClient { > > - CommonChannelClient common; > > - > > - CacheItem *cursor_cache[CURSOR_CACHE_HASH_SIZE]; > > - Ring cursor_cache_lru; > > - long cursor_cache_available; > > - uint32_t cursor_cache_items; > > -} CursorChannelClient; > > - > > -typedef struct CursorChannel { > > - CommonChannel common; // Must be the first thing > > - > > -#ifdef RED_STATISTICS > > - StatNodeRef stat; > > -#endif > > -} CursorChannel; > > - > > -typedef struct _CursorItem _CursorItem; > > - > > -struct _CursorItem { > > - union { > > - CursorItem cursor_item; > > - _CursorItem *next; > > - } u; > > -}; > > - > > -G_STATIC_ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE); > > - > > - > > -#endif /* CURSOR_CHANNEL_H_ */ > > diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c > > index 5e9b5bf..ecfef48 100644 > > --- a/server/red_dispatcher.c > > +++ b/server/red_dispatcher.c > > @@ -160,6 +160,7 @@ static void red_dispatcher_set_cursor_peer(RedChannel > > *channel, RedClient *clien > > memcpy(payload.common_caps, common_caps, > > sizeof(uint32_t)*num_common_caps); > > memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps); > > > > + /* TODO serialize it all, no dangling pointers */ > > dispatcher_send_message(&dispatcher->dispatcher, > > RED_WORKER_MESSAGE_CURSOR_CONNECT, > > &payload); > > diff --git a/server/red_worker.c b/server/red_worker.c > > index 4b69a38..9741758 100644 > > --- a/server/red_worker.c > > +++ b/server/red_worker.c > > @@ -94,7 +94,7 @@ > > #include "spice_image_cache.h" > > #include "pixmap-cache.h" > > #include "display-channel.h" > > -#include "cursor_channel.h" > > +#include "cursor-channel.h" > > > > //#define COMPRESS_STAT > > //#define DUMP_BITMAP > > @@ -266,24 +266,15 @@ struct SpiceWatch { > > }; > > > > enum { > > - BUF_TYPE_RAW = 1, > > -}; > > - > > -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_DRAW = PIPE_ITEM_TYPE_COMMON_LAST, > > 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, > > @@ -291,11 +282,6 @@ enum { > > 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 { > > @@ -639,18 +625,9 @@ 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; > > > > - _CursorItem cursor_items[NUM_CURSORS]; > > - _CursorItem *free_cursor_items; > > - > > RedMemSlotInfo mem_slots; > > > > ImageCache image_cache; > > @@ -659,8 +636,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; > > @@ -737,7 +712,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 red_release_cursor(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); > > @@ -756,16 +730,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); > > > > /* > > @@ -774,21 +743,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) \ > > @@ -824,7 +778,6 @@ static void red_push_monitors_config(DisplayChannelClient > > *dcc); > > DisplayChannel, common.base) > > > > #define RCC_TO_DCC(rcc) SPICE_CONTAINEROF((rcc), DisplayChannelClient, > > common.base) > > -#define RCC_TO_CCC(rcc) SPICE_CONTAINEROF((rcc), CursorChannelClient, > > common.base) > > > > > > > > @@ -916,6 +869,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++; > > @@ -1071,28 +1031,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) > > { > > @@ -1325,10 +1266,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 > > @@ -1338,11 +1275,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; > > @@ -4241,153 +4173,6 @@ static void red_update_area(RedWorker *worker, const > > SpiceRect *area, int surfac > > validate_area(worker, area, surface_id); > > } > > > > -static inline void free_cursor_item(RedWorker *worker, CursorItem *item); > > - > > -static void red_release_cursor(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); > > - free_cursor_item(worker, cursor); > > - red_put_cursor_cmd(cursor_cmd); > > - free(cursor_cmd); > > - } > > -} > > - > > -static void red_set_cursor(RedWorker *worker, CursorItem *cursor) > > -{ > > - if (worker->cursor) { > > - red_release_cursor(worker, worker->cursor); > > - } > > - ++cursor->refs; > > - worker->cursor = cursor; > > -} > > - > > -#ifdef DEBUG_CURSORS > > -static int _cursor_count = 0; > > -#endif > > - > > -static inline CursorItem *alloc_cursor_item(RedWorker *worker) > > -{ > > - CursorItem *cursor; > > - > > - if (!worker->free_cursor_items) { > > - return NULL; > > - } > > -#ifdef DEBUG_CURSORS > > - --_cursor_count; > > -#endif > > - cursor = &worker->free_cursor_items->u.cursor_item; > > - worker->free_cursor_items = worker->free_cursor_items->u.next; > > - return cursor; > > -} > > - > > -static inline void free_cursor_item(RedWorker *worker, CursorItem *item) > > -{ > > - ((_CursorItem *)item)->u.next = worker->free_cursor_items; > > - worker->free_cursor_items = (_CursorItem *)item; > > -#ifdef DEBUG_CURSORS > > - ++_cursor_count; > > - spice_assert(_cursor_count <= NUM_CURSORS); > > -#endif > > -} > > - > > -static void cursor_items_init(RedWorker *worker) > > -{ > > - int i; > > - > > - worker->free_cursor_items = NULL; > > - for (i = 0; i < NUM_CURSORS; i++) { > > - free_cursor_item(worker, &worker->cursor_items[i].u.cursor_item); > > - } > > -} > > - > > -static CursorItem *get_cursor_item(RedWorker *worker, RedCursorCmd *cmd, > > uint32_t group_id) > > -{ > > - CursorItem *cursor_item; > > - > > - spice_warn_if(!(cursor_item = alloc_cursor_item(worker))); > > - > > - cursor_item->refs = 1; > > - cursor_item->group_id = group_id; > > - cursor_item->red_cursor = cmd; > > - > > - return cursor_item; > > -} > > - > > -static CursorPipeItem *ref_cursor_pipe_item(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)); > > - > > - red_release_cursor(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 = get_cursor_item(worker, 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); > > - } > > - red_release_cursor(worker, cursor_item); > > -} > > - > > static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int > > *ring_is_empty) > > { > > QXLCommandExt ext_cmd; > > @@ -4425,12 +4210,11 @@ static int red_process_cursor(RedWorker *worker, > > uint32_t max_pipe_size, int *ri > > free(cursor); > > break; > > } > > - > > - qxl_process_cursor(worker, cursor, ext_cmd.group_id); > > + cursor_channel_process_cmd(worker->cursor_channel, cursor, > > ext_cmd.group_id); > > break; > > } > > default: > > - spice_error("bad command type"); > > + spice_warning("bad command type"); > > } > > n++; > > } > > @@ -4690,12 +4474,6 @@ static void > > red_push_surface_image(DisplayChannelClient *dcc, int surface_id) > > red_channel_client_push(&dcc->common.base); > > } > > > > -typedef struct { > > - uint32_t type; > > - void *data; > > - uint32_t size; > > -} AddBufInfo; > > - > > static void marshaller_add_compressed(SpiceMarshaller *m, > > RedCompressBuf *comp_buf, size_t size) > > { > > @@ -4710,18 +4488,6 @@ static void marshaller_add_compressed(SpiceMarshaller > > *m, > > } while (max); > > } > > > > - > > -static void add_buf_from_info(SpiceMarshaller *m, AddBufInfo *info) > > -{ > > - if (info->data) { > > - switch (info->type) { > > - case BUF_TYPE_RAW: > > - spice_marshaller_add_ref(m, info->data, info->size); > > - break; > > - } > > - } > > -} > > - > > static void fill_base(SpiceMarshaller *base_marshaller, Drawable *drawable) > > { > > SpiceMsgDisplayBase base; > > @@ -6413,37 +6179,6 @@ static void fill_attr(SpiceMarshaller *m, > > SpiceLineAttr *attr, uint32_t group_id > > } > > } > > > > -static void fill_cursor(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->type = BUF_TYPE_RAW; > > - 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); > > @@ -8199,23 +7934,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) > > @@ -8591,92 +8309,7 @@ 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; > > - > > - fill_cursor(ccc, &msg.cursor, worker->cursor, &info); > > - spice_marshall_msg_cursor_init(base_marshaller, &msg); > > - add_buf_from_info(base_marshaller, &info); > > -} > > - > > -static void red_marshall_cursor(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; > > - > > - fill_cursor(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); > > - } > > -} > > +#define RCC_TO_CCC(rcc) SPICE_CONTAINEROF((rcc), CursorChannelClient, > > common.base) > > > > static void red_marshall_surface_create(RedChannelClient *rcc, > > SpiceMarshaller *base_marshaller, SpiceMsgSurfaceCreate *surface_create) > > @@ -8758,9 +8391,6 @@ static void display_channel_send_item(RedChannelClient > > *rcc, PipeItem *pipe_item > > marshall_qxl_drawable(rcc, m, dpi); > > break; > > } > > - case PIPE_ITEM_TYPE_INVAL_ONE: > > - red_marshall_inval(rcc, m, (CacheItem *)pipe_item); > > - break; > > case PIPE_ITEM_TYPE_STREAM_CREATE: { > > StreamAgent *agent = SPICE_CONTAINEROF(pipe_item, StreamAgent, > > create_item); > > red_display_marshall_stream_start(rcc, m, agent); > > @@ -8780,7 +8410,7 @@ static void display_channel_send_item(RedChannelClient > > *rcc, PipeItem *pipe_item > > red_display_marshall_upgrade(rcc, m, (UpgradeItem *)pipe_item); > > break; > > case PIPE_ITEM_TYPE_VERB: > > - red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb); > > + red_marshall_verb(rcc, (VerbItem*)pipe_item); > > break; > > case PIPE_ITEM_TYPE_MIGRATE_DATA: > > display_channel_marshall_migrate_data(rcc, m); > > @@ -8796,7 +8426,7 @@ static void display_channel_send_item(RedChannelClient > > *rcc, PipeItem *pipe_item > > break; > > case PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE: > > red_reset_palette_cache(dcc); > > - red_marshall_verb(rcc, SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES); > > + red_channel_client_init_send_data(rcc, > > SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES, NULL); > > break; > > case PIPE_ITEM_TYPE_CREATE_SURFACE: { > > SurfaceCreateItem *surface_create = SPICE_CONTAINEROF(pipe_item, > > SurfaceCreateItem, > > @@ -8835,37 +8465,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: > > - red_marshall_cursor(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) { > > @@ -9313,7 +8912,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(worker->cursor_channel); > > + worker->cursor_channel = NULL; > > } else { > > sleep_count++; > > usleep(DISPLAY_CLIENT_RETRY_INTERVAL); > > @@ -9924,16 +9524,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_new_client(CommonChannel *common, > > + int size, > > + 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, > > @@ -9961,8 +9561,8 @@ DisplayChannelClient > > *display_channel_client_create(CommonChannel *common, > > uint32_t *caps, int > > num_caps) > > { > > DisplayChannelClient *dcc = > > - (DisplayChannelClient*)common_channel_client_create( > > - sizeof(DisplayChannelClient), common, client, stream, > > + (DisplayChannelClient*)common_channel_new_client( > > + common, sizeof(DisplayChannelClient), client, stream, > > mig_target, > > TRUE, > > common_caps, num_common_caps, > > @@ -9976,62 +9576,30 @@ 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 *red_worker_new_channel(RedWorker *worker, int size, > > + uint32_t channel_type, int > > migration_flags, > > + ChannelCbs *channel_cbs, > > + channel_handle_parsed_proc handle_parsed) > > { > > RedChannel *channel = NULL; > > CommonChannel *common; > > - ChannelCbs channel_cbs = { NULL, }; > > - > > - channel_cbs.config_socket = common_channel_config_socket; > > - channel_cbs.on_disconnect = on_disconnect; > > - channel_cbs.send_item = send_item; > > - channel_cbs.hold_item = hold_item; > > - channel_cbs.release_item = release_item; > > - channel_cbs.alloc_recv_buf = common_alloc_recv_buf; > > - channel_cbs.release_recv_buf = common_release_recv_buf; > > - channel_cbs.handle_migrate_flush_mark = handle_migrate_flush_mark; > > - channel_cbs.handle_migrate_data = handle_migrate_data; > > - channel_cbs.handle_migrate_data_get_serial = migrate_get_serial; > > + > > + spice_return_val_if_fail(worker, NULL); > > + spice_return_val_if_fail(channel_cbs, NULL); > > + spice_return_val_if_fail(!channel_cbs->config_socket, NULL); > > + spice_return_val_if_fail(!channel_cbs->alloc_recv_buf, NULL); > > + spice_return_val_if_fail(!channel_cbs->release_recv_buf, NULL); > > + > > + channel_cbs->config_socket = common_channel_config_socket; > > + channel_cbs->alloc_recv_buf = common_alloc_recv_buf; > > + channel_cbs->release_recv_buf = common_release_recv_buf; > > > > channel = red_channel_create_parser(size, &worker_core, > > channel_type, worker->id, > > TRUE /* handle_acks */, > > spice_get_client_channel_parser(channel_type, > > NULL), > > handle_parsed, > > - &channel_cbs, > > + channel_cbs, > > migration_flags); > > common = (CommonChannel *)channel; > > if (!channel) { > > @@ -10151,7 +9719,6 @@ static void > > display_channel_client_release_item_before_push(DisplayChannelClient > > free(item); > > break; > > } > > - case PIPE_ITEM_TYPE_INVAL_ONE: > > case PIPE_ITEM_TYPE_VERB: > > case PIPE_ITEM_TYPE_MIGRATE_DATA: > > case PIPE_ITEM_TYPE_PIXMAP_SYNC: > > @@ -10181,25 +9748,26 @@ static void > > display_channel_release_item(RedChannelClient *rcc, PipeItem *item, > > static void display_channel_create(RedWorker *worker, int migrate) > > { > > DisplayChannel *display_channel; > > + ChannelCbs cbs = { > > + .on_disconnect = display_channel_client_on_disconnect, > > + .send_item = display_channel_send_item, > > + .hold_item = display_channel_hold_pipe_item, > > + .release_item = display_channel_release_item, > > + .handle_migrate_flush_mark = display_channel_handle_migrate_mark, > > + .handle_migrate_data = display_channel_handle_migrate_data, > > + .handle_migrate_data_get_serial = > > display_channel_handle_migrate_data_get_serial > > + }; > > > > if (worker->display_channel) { > > return; > > } > > > > spice_info("create display channel"); > > - if (!(worker->display_channel = (DisplayChannel *)__new_channel( > > + if (!(worker->display_channel = (DisplayChannel > > *)red_worker_new_channel( > > worker, sizeof(*display_channel), > > SPICE_CHANNEL_DISPLAY, > > SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER, > > - display_channel_client_on_disconnect, > > - display_channel_send_item, > > - display_channel_hold_pipe_item, > > - display_channel_release_item, > > - display_channel_handle_message, > > - display_channel_handle_migrate_mark, > > - display_channel_handle_migrate_data, > > - display_channel_handle_migrate_data_get_serial > > - ))) { > > + &cbs, display_channel_handle_message))) { > > spice_warning("failed to create display channel"); > > return; > > } > > @@ -10334,129 +9902,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)) { > > - red_channel_client_pipe_add_type(rcc, > > - PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE); > > - red_channel_client_default_migrate(rcc); > > - } > > -} > > - > > -static void on_new_cursor_channel(RedWorker *worker, RedChannelClient *rcc) > > -{ > > - CursorChannel *channel = worker->cursor_channel; > > - > > - spice_assert(channel); > > - red_channel_client_ack_zero_messages_window(rcc); > > - red_channel_client_push_set_ack(rcc); > > - // TODO: why do we check for context.canvas? defer this to after display > > cc is connected > > - // and test it's canvas? this is just a test to see if there is an > > active renderer? > > - if (worker->surfaces[0].context.canvas && > > !channel->common.during_target_migrate) { > > - red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_CURSOR_INIT); > > - } > > -} > > - > > -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); > > - ref_cursor_pipe_item(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_create(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, > > @@ -10465,24 +9910,28 @@ static void red_connect_cursor(RedWorker *worker, > > RedClient *client, RedsStream > > CursorChannel *channel; > > CursorChannelClient *ccc; > > > > - if (worker->cursor_channel == NULL) { > > - spice_warning("cursor channel was not created"); > > - return; > > - } > > + spice_return_if_fail(worker->cursor_channel != NULL); > > + > > 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, client, stream, > > migrate, > > common_caps, num_common_caps, > > caps, num_caps); > > - if (!ccc) { > > - return; > > - } > > + spice_return_if_fail(ccc != NULL); > > #ifdef RED_STATISTICS > > channel->stat = stat_add_node(worker->stat, "cursor_channel", TRUE); > > channel->common.base.out_bytes_counter = stat_add_counter(channel->stat, > > "out_bytes", TRUE); > > #endif > > - on_new_cursor_channel(worker, &ccc->common.base); > > + > > + RedChannelClient *rcc = &ccc->common.base; > > + red_channel_client_ack_zero_messages_window(rcc); > > + red_channel_client_push_set_ack(rcc); > > + // TODO: why do we check for context.canvas? defer this to after display > > cc is connected > > + // and test it's canvas? this is just a test to see if there is an > > active renderer? > > + if (worker->surfaces[0].context.canvas && > > !channel->common.during_target_migrate) { > > + red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_CURSOR_INIT); > > + } > > } > > > > static void surface_dirty_region_to_rects(RedSurface *surface, > > @@ -10636,31 +10085,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) { > > - red_release_cursor(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*/ > > @@ -10691,7 +10115,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) > > @@ -10849,10 +10273,9 @@ static void dev_create_primary_surface(RedWorker > > *worker, uint32_t surface_id, > > red_channel_push(&worker->display_channel->common.base); > > } > > > > - if (cursor_is_connected(worker) && > > !worker->cursor_channel->common.during_target_migrate) { > > + if (!worker->cursor_channel->common.during_target_migrate) > > red_channel_pipes_add_type(&worker->cursor_channel->common.base, > > PIPE_ITEM_TYPE_CURSOR_INIT); > > - } > > } > > > > void handle_dev_create_primary_surface(void *opaque, void *payload) > > @@ -10881,7 +10304,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) > > @@ -11051,7 +10474,9 @@ void handle_dev_oom(void *opaque, void *payload) > > > > void handle_dev_reset_cursor(void *opaque, void *payload) > > { > > - red_cursor_reset((RedWorker *)opaque); > > + RedWorker *worker = opaque; > > + > > + cursor_channel_reset(worker->cursor_channel); > > } > > > > void handle_dev_reset_image_cache(void *opaque, void *payload) > > @@ -11195,8 +10620,12 @@ void handle_dev_cursor_channel_create(void *opaque, > > void *payload) > > RedWorker *worker = opaque; > > RedChannel *red_channel; > > > > - // TODO: handle seemless migration. Temp, setting migrate to FALSE > > - cursor_channel_create(worker, FALSE); > > + if (!worker->cursor_channel) { > > + worker->cursor_channel = cursor_channel_new(worker); > > + } else { > > + spice_warning("cursor channel already created"); > > + } > > + > > red_channel = &worker->cursor_channel->common.base; > > send_data(worker->channel, &red_channel, sizeof(RedChannel *)); > > } > > @@ -11223,19 +10652,20 @@ void handle_dev_cursor_disconnect(void *opaque, > > void *payload) > > RedChannelClient *rcc = msg->rcc; > > > > spice_info("disconnect cursor client"); > > - spice_assert(rcc); > > red_channel_client_disconnect(rcc); > > } > > > > void handle_dev_cursor_migrate(void *opaque, void *payload) > > { > > RedWorkerMessageCursorMigrate *msg = payload; > > - RedWorker *worker = opaque; > > RedChannelClient *rcc = msg->rcc; > > > > spice_info("migrate cursor client"); > > - spice_assert(rcc); > > - red_migrate_cursor(worker, rcc); > > + if (!red_channel_client_is_connected(rcc)) > > + return; > > + > > + red_channel_client_pipe_add_type(rcc, > > PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE); > > + red_channel_client_default_migrate(rcc); > > } > > > > void handle_dev_set_compression(void *opaque, void *payload) > > @@ -11312,8 +10742,10 @@ 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); > > + spice_info("mouse mode %u", msg->mode); > > + spice_return_if_fail(worker->cursor_channel); > > + > > + worker->cursor_channel->mouse_mode = msg->mode; > > } > > > > void handle_dev_add_memslot_async(void *opaque, void *payload) > > @@ -11350,7 +10782,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); > > @@ -11628,12 +11060,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; > > @@ -11643,7 +11073,6 @@ RedWorker* red_worker_new(QXLInstance *qxl, > > RedDispatcher *red_dispatcher) > > image_cache_init(&worker->image_cache); > > image_surface_init(worker); > > drawables_init(worker); > > - cursor_items_init(worker); > > red_init_streams(worker); > > stat_init(&worker->add_stat, add_stat_name); > > stat_init(&worker->exclude_stat, exclude_stat_name); > > diff --git a/server/red_worker.h b/server/red_worker.h > > index 0f5fac7..60c326a 100644 > > --- a/server/red_worker.h > > +++ b/server/red_worker.h > > @@ -32,6 +32,9 @@ 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 +48,75 @@ typedef struct CommonChannel { > > of the primary surface) */ > > } CommonChannel; > > > > +enum { > > + PIPE_ITEM_TYPE_VERB = PIPE_ITEM_TYPE_CHANNEL_BASE, > > + PIPE_ITEM_TYPE_INVAL_ONE, > > + > > + PIPE_ITEM_TYPE_COMMON_LAST > > +}; > > + > > +typedef struct VerbItem { > > + PipeItem base; > > + uint16_t verb; > > +} VerbItem; > > + > > +static inline void red_marshall_verb(RedChannelClient *rcc, VerbItem *item) > > +{ > > + red_channel_client_init_send_data(rcc, item->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); > > + > > +RedChannel *red_worker_new_channel(RedWorker *worker, int size, > > + uint32_t channel_type, int > > migration_flags, > > + ChannelCbs *channel_cbs, > > + channel_handle_parsed_proc > > handle_parsed); > > + > > +CommonChannelClient *common_channel_new_client(CommonChannel *common, > > + int size, > > + RedClient *client, > > + RedsStream *stream, > > + int mig_target, > > + int monitor_latency, > > + uint32_t *common_caps, > > + int num_common_caps, > > + uint32_t *caps, > > + int num_caps); > > > > #endif > > -- > > 2.4.3 > > > > This patch does a lot of stuff: > - move code to new files; > - change cursor structures (for instance to add qxl pointer); > - renames many functions; Imo the renaming goes together with the move to the new file (at least for the few methods I looked at). I agree it would be better to split this a bit (for example, move CursorItem in a separate patch if at all possible, and also the other changes you mention). > - change cursor memory management; > - fix some bugs. Christophe
Attachment:
signature.asc
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel