diff options
Diffstat (limited to 'server/cursor-channel.c')
-rw-r--r-- | server/cursor-channel.c | 77 |
1 files changed, 75 insertions, 2 deletions
diff --git a/server/cursor-channel.c b/server/cursor-channel.c index 48f9ad37..91eb55d8 100644 --- a/server/cursor-channel.c +++ b/server/cursor-channel.c @@ -19,6 +19,41 @@ #include "common/generated_server_marshallers.h" #include "cursor-channel.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; + +G_STATIC_ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE); + +typedef struct LocalCursor { + CursorItem base; + SpicePoint16 position; + uint32_t data_size; + SpiceCursor red_cursor; +} LocalCursor; + +typedef struct CursorPipeItem { + PipeItem base; + CursorItem *cursor_item; + int refs; +} CursorPipeItem; + struct CursorChannel { CommonChannel common; // Must be the first thing @@ -34,6 +69,16 @@ struct CursorChannel { #endif }; +struct CursorChannelClient { + CommonChannelClient common; + + CacheItem *cursor_cache[CURSOR_CACHE_HASH_SIZE]; + Ring cursor_cache_lru; + long cursor_cache_available; + uint32_t cursor_cache_items; +}; + + #define RCC_TO_CCC(rcc) SPICE_CONTAINEROF((rcc), CursorChannelClient, common.base) #define CLIENT_CURSOR_CACHE @@ -50,7 +95,7 @@ static inline CursorItem *alloc_cursor_item(void) return cursor_item; } -CursorItem *cursor_item_new(RedCursorCmd *cmd, uint32_t group_id) +static CursorItem *cursor_item_new(RedCursorCmd *cmd, uint32_t group_id) { CursorItem *cursor_item; @@ -63,7 +108,7 @@ CursorItem *cursor_item_new(RedCursorCmd *cmd, uint32_t group_id) return cursor_item; } -void cursor_item_unref(QXLInstance *qxl, CursorItem *cursor) +static void cursor_item_unref(QXLInstance *qxl, CursorItem *cursor) { if (!--cursor->refs) { QXLReleaseInfoExt release_info_ext; @@ -390,6 +435,17 @@ CursorChannel* cursor_channel_new(RedWorker *worker) return cursor_channel; } +void cursor_channel_client_migrate(CursorChannelClient* client) +{ + RedChannelClient *rcc; + + spice_return_if_fail(client); + rcc = RED_CHANNEL_CLIENT(client); + + red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE); + red_channel_client_default_migrate(rcc); +} + CursorChannelClient* cursor_channel_client_new(CursorChannel *cursor, RedClient *client, RedsStream *stream, int mig_target, uint32_t *common_caps, int num_common_caps, @@ -476,6 +532,23 @@ void cursor_channel_reset(CursorChannel *cursor) } } +void cursor_channel_init(CursorChannel *cursor, CursorChannelClient *client) +{ + spice_return_if_fail(cursor); + + if (red_channel_is_connected(&cursor->common.base) + || COMMON_CHANNEL(cursor)->during_target_migrate) { + spice_debug("during_target_migrate: skip init"); + return; + } + + if (client) + red_channel_client_pipe_add_type(RED_CHANNEL_CLIENT(client), + PIPE_ITEM_TYPE_CURSOR_INIT); + else + red_channel_pipes_add_type(RED_CHANNEL(cursor), PIPE_ITEM_TYPE_CURSOR_INIT); +} + void cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32_t mode) { spice_return_if_fail(cursor); |