From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> --- server/dcc-encoders.c | 131 +++++++++++++++++++++++++- server/dcc-encoders.h | 7 ++ server/dcc.c | 81 ++++++++++++++++ server/dcc.h | 3 + server/red_worker.c | 250 ++------------------------------------------------ 5 files changed, 228 insertions(+), 244 deletions(-) diff --git a/server/dcc-encoders.c b/server/dcc-encoders.c index 24064a8..1eaa604 100644 --- a/server/dcc-encoders.c +++ b/server/dcc-encoders.c @@ -584,8 +584,133 @@ void dcc_free_glz_drawables(DisplayChannelClient *dcc) void dcc_freeze_glz(DisplayChannelClient *dcc) { pthread_rwlock_wrlock(&dcc->glz_dict->encode_lock); - if (!dcc->glz_dict->migrate_freeze) { - dcc->glz_dict->migrate_freeze = TRUE; - } + dcc->glz_dict->migrate_freeze = TRUE; pthread_rwlock_unlock(&dcc->glz_dict->encode_lock); } + +static GlzSharedDictionary *glz_shared_dictionary_new(RedClient *client, uint8_t id, + GlzEncDictContext *dict) +{ + spice_return_val_if_fail(dict != NULL, NULL); + + GlzSharedDictionary *shared_dict = spice_new0(GlzSharedDictionary, 1); + + shared_dict->dict = dict; + shared_dict->id = id; + shared_dict->refs = 1; + shared_dict->migrate_freeze = FALSE; + shared_dict->client = client; + ring_item_init(&shared_dict->base); + pthread_rwlock_init(&shared_dict->encode_lock, NULL); + + return shared_dict; +} + +static pthread_mutex_t glz_dictionary_list_lock = PTHREAD_MUTEX_INITIALIZER; +static Ring glz_dictionary_list = {&glz_dictionary_list, &glz_dictionary_list}; + +static GlzSharedDictionary *find_glz_dictionary(RedClient *client, uint8_t dict_id) +{ + RingItem *now; + GlzSharedDictionary *ret = NULL; + + now = &glz_dictionary_list; + while ((now = ring_next(&glz_dictionary_list, now))) { + GlzSharedDictionary *dict = (GlzSharedDictionary *)now; + if ((dict->client == client) && (dict->id == dict_id)) { + ret = dict; + break; + } + } + + return ret; +} + +#define MAX_LZ_ENCODERS MAX_CACHE_CLIENTS + +static GlzSharedDictionary *create_glz_dictionary(DisplayChannelClient *dcc, + uint8_t id, int window_size) +{ + spice_info("Lz Window %d Size=%d", id, window_size); + + GlzEncDictContext *glz_dict = + glz_enc_dictionary_create(window_size, MAX_LZ_ENCODERS, &dcc->glz_data.usr); + + return glz_shared_dictionary_new(RED_CHANNEL_CLIENT(dcc)->client, id, glz_dict); +} + +GlzSharedDictionary *dcc_get_glz_dictionary(DisplayChannelClient *dcc, + uint8_t id, int window_size) +{ + GlzSharedDictionary *shared_dict; + + pthread_mutex_lock(&glz_dictionary_list_lock); + + shared_dict = find_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id); + if (shared_dict) { + shared_dict->refs++; + } else { + shared_dict = create_glz_dictionary(dcc, id, window_size); + ring_add(&glz_dictionary_list, &shared_dict->base); + } + + pthread_mutex_unlock(&glz_dictionary_list_lock); + return shared_dict; +} + +static GlzSharedDictionary *restore_glz_dictionary(DisplayChannelClient *dcc, + uint8_t id, + GlzEncDictRestoreData *restore_data) +{ + GlzEncDictContext *glz_dict = + glz_enc_dictionary_restore(restore_data, &dcc->glz_data.usr); + + return glz_shared_dictionary_new(RED_CHANNEL_CLIENT(dcc)->client, id, glz_dict); +} + +GlzSharedDictionary *dcc_restore_glz_dictionary(DisplayChannelClient *dcc, + uint8_t id, + GlzEncDictRestoreData *restore_data) +{ + GlzSharedDictionary *shared_dict = NULL; + + pthread_mutex_lock(&glz_dictionary_list_lock); + + shared_dict = find_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id); + + if (shared_dict) { + shared_dict->refs++; + } else { + shared_dict = restore_glz_dictionary(dcc, id, restore_data); + ring_add(&glz_dictionary_list, &shared_dict->base); + } + + pthread_mutex_unlock(&glz_dictionary_list_lock); + return shared_dict; +} + +/* destroy encoder, and dictionary if no one uses it*/ +void dcc_release_glz(DisplayChannelClient *dcc) +{ + GlzSharedDictionary *shared_dict; + + dcc_free_glz_drawables(dcc); + + glz_encoder_destroy(dcc->glz); + dcc->glz = NULL; + + if (!(shared_dict = dcc->glz_dict)) { + return; + } + + dcc->glz_dict = NULL; + pthread_mutex_lock(&glz_dictionary_list_lock); + if (--shared_dict->refs != 0) { + pthread_mutex_unlock(&glz_dictionary_list_lock); + return; + } + ring_remove(&shared_dict->base); + pthread_mutex_unlock(&glz_dictionary_list_lock); + glz_enc_dictionary_destroy(shared_dict->dict, &dcc->glz_data.usr); + free(shared_dict); +} diff --git a/server/dcc-encoders.h b/server/dcc-encoders.h index 05fd29e..5de66f7 100644 --- a/server/dcc-encoders.h +++ b/server/dcc-encoders.h @@ -46,6 +46,7 @@ int dcc_free_some_independent_glz_drawables (DisplayChannelClie void dcc_free_glz_drawables (DisplayChannelClient *dcc); void dcc_free_glz_drawables_to_free (DisplayChannelClient* dcc); void dcc_freeze_glz (DisplayChannelClient *dcc); +void dcc_release_glz (DisplayChannelClient *dcc); void marshaller_add_compressed (SpiceMarshaller *m, RedCompressBuf *comp_buf, @@ -77,6 +78,12 @@ typedef struct GlzSharedDictionary { RedClient *client; // channel clients of the same client share the dict } GlzSharedDictionary; +GlzSharedDictionary* dcc_get_glz_dictionary (DisplayChannelClient *dcc, + uint8_t id, int window_size); +GlzSharedDictionary* dcc_restore_glz_dictionary (DisplayChannelClient *dcc, + uint8_t id, + GlzEncDictRestoreData *restore_data); + typedef struct { DisplayChannelClient *dcc; RedCompressBuf *bufs_head; diff --git a/server/dcc.c b/server/dcc.c index 6115569..ec0295a 100644 --- a/server/dcc.c +++ b/server/dcc.c @@ -1091,3 +1091,84 @@ int dcc_pixmap_cache_unlocked_add(DisplayChannelClient *dcc, uint64_t id, cache->sync[dcc->common.id] = serial; return TRUE; } + +static int dcc_handle_init(DisplayChannelClient *dcc, SpiceMsgcDisplayInit *init) +{ + spice_return_val_if_fail(dcc->expect_init, FALSE); + dcc->expect_init = FALSE; + + spice_return_val_if_fail(!dcc->pixmap_cache, FALSE); + dcc->pixmap_cache = pixmap_cache_get(RED_CHANNEL_CLIENT(dcc)->client, + init->pixmap_cache_id, + init->pixmap_cache_size); + spice_return_val_if_fail(dcc->pixmap_cache, FALSE); + + spice_return_val_if_fail(!dcc->glz_dict, FALSE); + ring_init(&dcc->glz_drawables); + ring_init(&dcc->glz_drawables_inst_to_free); + pthread_mutex_init(&dcc->glz_drawables_inst_to_free_lock, NULL); + dcc->glz_dict = dcc_get_glz_dictionary(dcc, + init->glz_dictionary_id, + init->glz_dictionary_window_size); + spice_return_val_if_fail(dcc->glz_dict, FALSE); + + return TRUE; +} + +static int dcc_handle_stream_report(DisplayChannelClient *dcc, + SpiceMsgcDisplayStreamReport *report) +{ + StreamAgent *agent; + + spice_return_val_if_fail(report->stream_id < NUM_STREAMS, FALSE); + agent = &dcc->stream_agents[report->stream_id]; + spice_return_val_if_fail(agent->mjpeg_encoder, TRUE); + spice_return_val_if_fail(report->unique_id == agent->report_id, TRUE); + + mjpeg_encoder_client_stream_report(agent->mjpeg_encoder, + report->num_frames, + report->num_drops, + report->start_frame_mm_time, + report->end_frame_mm_time, + report->last_frame_delay, + report->audio_delay); + return TRUE; +} + +static int dcc_handle_preferred_compression(DisplayChannelClient *dcc, + SpiceMsgcDisplayPreferredCompression *pc) +{ + switch (pc->image_compression) { + case SPICE_IMAGE_COMPRESSION_AUTO_LZ: + case SPICE_IMAGE_COMPRESSION_AUTO_GLZ: + case SPICE_IMAGE_COMPRESSION_QUIC: +#ifdef USE_LZ4 + case SPICE_IMAGE_COMPRESSION_LZ4: +#endif + case SPICE_IMAGE_COMPRESSION_LZ: + case SPICE_IMAGE_COMPRESSION_GLZ: + case SPICE_IMAGE_COMPRESSION_OFF: + dcc->image_compression = pc->image_compression; + return TRUE; + default: + spice_warning("preferred-compression: unsupported image compression setting"); + return FALSE; + } +} + +int dcc_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, void *msg) +{ + DisplayChannelClient *dcc = RCC_TO_DCC(rcc); + + switch (type) { + case SPICE_MSGC_DISPLAY_INIT: + return dcc_handle_init(dcc, (SpiceMsgcDisplayInit *)msg); + case SPICE_MSGC_DISPLAY_STREAM_REPORT: + return dcc_handle_stream_report(dcc, (SpiceMsgcDisplayStreamReport *)msg); + case SPICE_MSGC_DISPLAY_PREFERRED_COMPRESSION: + return dcc_handle_preferred_compression(dcc, + (SpiceMsgcDisplayPreferredCompression *)msg); + default: + return red_channel_client_handle_message(rcc, size, type, msg); + } +} diff --git a/server/dcc.h b/server/dcc.h index c62c3c9..a6e1cc7 100644 --- a/server/dcc.h +++ b/server/dcc.h @@ -147,6 +147,9 @@ DisplayChannelClient* dcc_new (DisplayCha spice_wan_compression_t jpeg_state, spice_wan_compression_t zlib_glz_state); void dcc_start (DisplayChannelClient *dcc); +int dcc_handle_message (RedChannelClient *rcc, + uint32_t size, + uint16_t type, void *msg); void dcc_push_monitors_config (DisplayChannelClient *dcc); void dcc_destroy_surface (DisplayChannelClient *dcc, uint32_t surface_id); diff --git a/server/red_worker.c b/server/red_worker.c index 188cb16..e655876 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -83,16 +83,11 @@ struct SpiceWatch { void *watch_func_opaque; }; -#define MAX_LZ_ENCODERS MAX_CACHE_CLIENTS - #define MAX_PIPE_SIZE 50 #define WIDE_CLIENT_ACK_WINDOW 40 #define NARROW_CLIENT_ACK_WINDOW 20 -pthread_mutex_t glz_dictionary_list_lock = PTHREAD_MUTEX_INITIALIZER; -Ring glz_dictionary_list = {&glz_dictionary_list, &glz_dictionary_list}; - typedef struct UpgradeItem { PipeItem base; int refs; @@ -156,7 +151,6 @@ static void display_channel_draw(DisplayChannel *display, const SpiceRect *area, static void display_channel_draw_till(DisplayChannel *display, const SpiceRect *area, int surface_id, Drawable *last); static inline void display_begin_send_message(RedChannelClient *rcc); -static void dcc_release_glz(DisplayChannelClient *dcc); static void display_channel_client_release_item_before_push(DisplayChannelClient *dcc, PipeItem *item); static void display_channel_client_release_item_after_push(DisplayChannelClient *dcc, @@ -4454,167 +4448,18 @@ static inline void flush_all_qxl_commands(RedWorker *worker) flush_cursor_commands(worker); } -static GlzSharedDictionary *_red_find_glz_dictionary(RedClient *client, uint8_t dict_id) -{ - RingItem *now; - GlzSharedDictionary *ret = NULL; - - now = &glz_dictionary_list; - while ((now = ring_next(&glz_dictionary_list, now))) { - GlzSharedDictionary *dict = (GlzSharedDictionary *)now; - if ((dict->client == client) && (dict->id == dict_id)) { - ret = dict; - break; - } - } - - return ret; -} - -static GlzSharedDictionary *_red_create_glz_dictionary(RedClient *client, uint8_t id, - GlzEncDictContext *opaque_dict) -{ - GlzSharedDictionary *shared_dict = spice_new0(GlzSharedDictionary, 1); - shared_dict->dict = opaque_dict; - shared_dict->id = id; - shared_dict->refs = 1; - shared_dict->migrate_freeze = FALSE; - shared_dict->client = client; - ring_item_init(&shared_dict->base); - pthread_rwlock_init(&shared_dict->encode_lock, NULL); - return shared_dict; -} - -static GlzSharedDictionary *red_create_glz_dictionary(DisplayChannelClient *dcc, - uint8_t id, int window_size) -{ - GlzEncDictContext *glz_dict = glz_enc_dictionary_create(window_size, - MAX_LZ_ENCODERS, - &dcc->glz_data.usr); -#ifdef COMPRESS_DEBUG - spice_info("Lz Window %d Size=%d", id, window_size); -#endif - if (!glz_dict) { - spice_critical("failed creating lz dictionary"); - return NULL; - } - return _red_create_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id, glz_dict); -} - -static GlzSharedDictionary *red_create_restored_glz_dictionary(DisplayChannelClient *dcc, - uint8_t id, - GlzEncDictRestoreData *restore_data) -{ - GlzEncDictContext *glz_dict = glz_enc_dictionary_restore(restore_data, - &dcc->glz_data.usr); - if (!glz_dict) { - spice_critical("failed creating lz dictionary"); - return NULL; - } - return _red_create_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id, glz_dict); -} - -static GlzSharedDictionary *red_get_glz_dictionary(DisplayChannelClient *dcc, - uint8_t id, int window_size) -{ - GlzSharedDictionary *shared_dict = NULL; - - pthread_mutex_lock(&glz_dictionary_list_lock); - - shared_dict = _red_find_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id); - - if (!shared_dict) { - shared_dict = red_create_glz_dictionary(dcc, id, window_size); - ring_add(&glz_dictionary_list, &shared_dict->base); - } else { - shared_dict->refs++; - } - pthread_mutex_unlock(&glz_dictionary_list_lock); - return shared_dict; -} - -static GlzSharedDictionary *red_restore_glz_dictionary(DisplayChannelClient *dcc, - uint8_t id, - GlzEncDictRestoreData *restore_data) -{ - GlzSharedDictionary *shared_dict = NULL; - - pthread_mutex_lock(&glz_dictionary_list_lock); - - shared_dict = _red_find_glz_dictionary(RED_CHANNEL_CLIENT(dcc)->client, id); - - if (!shared_dict) { - shared_dict = red_create_restored_glz_dictionary(dcc, id, restore_data); - ring_add(&glz_dictionary_list, &shared_dict->base); - } else { - shared_dict->refs++; - } - pthread_mutex_unlock(&glz_dictionary_list_lock); - return shared_dict; -} - -/* destroy encoder, and dictionary if no one uses it*/ -static void dcc_release_glz(DisplayChannelClient *dcc) -{ - GlzSharedDictionary *shared_dict; - - dcc_free_glz_drawables(dcc); - - glz_encoder_destroy(dcc->glz); - dcc->glz = NULL; - - if (!(shared_dict = dcc->glz_dict)) { - return; - } - - dcc->glz_dict = NULL; - pthread_mutex_lock(&glz_dictionary_list_lock); - if (--shared_dict->refs) { - pthread_mutex_unlock(&glz_dictionary_list_lock); - return; - } - ring_remove(&shared_dict->base); - pthread_mutex_unlock(&glz_dictionary_list_lock); - glz_enc_dictionary_destroy(shared_dict->dict, &dcc->glz_data.usr); - free(shared_dict); -} - -static int display_channel_init_cache(DisplayChannelClient *dcc, SpiceMsgcDisplayInit *init_info) +static int dcc_handle_migrate_glz_dictionary(DisplayChannelClient *dcc, + SpiceMigrateDataDisplay *migrate) { - spice_assert(!dcc->pixmap_cache); - return !!(dcc->pixmap_cache = pixmap_cache_get(RED_CHANNEL_CLIENT(dcc)->client, - init_info->pixmap_cache_id, - init_info->pixmap_cache_size)); -} + spice_return_val_if_fail(!dcc->glz_dict, FALSE); -static int display_channel_init_glz_dictionary(DisplayChannelClient *dcc, - SpiceMsgcDisplayInit *init_info) -{ - spice_assert(!dcc->glz_dict); ring_init(&dcc->glz_drawables); ring_init(&dcc->glz_drawables_inst_to_free); pthread_mutex_init(&dcc->glz_drawables_inst_to_free_lock, NULL); - return !!(dcc->glz_dict = red_get_glz_dictionary(dcc, - init_info->glz_dictionary_id, - init_info->glz_dictionary_window_size)); -} - -static int display_channel_init(DisplayChannelClient *dcc, SpiceMsgcDisplayInit *init_info) -{ - return (display_channel_init_cache(dcc, init_info) && - display_channel_init_glz_dictionary(dcc, init_info)); -} - -static int display_channel_handle_migrate_glz_dictionary(DisplayChannelClient *dcc, - SpiceMigrateDataDisplay *migrate_info) -{ - spice_assert(!dcc->glz_dict); - ring_init(&dcc->glz_drawables); - ring_init(&dcc->glz_drawables_inst_to_free); - pthread_mutex_init(&dcc->glz_drawables_inst_to_free_lock, NULL); - return !!(dcc->glz_dict = red_restore_glz_dictionary(dcc, - migrate_info->glz_dict_id, - &migrate_info->glz_dict_data)); + dcc->glz_dict = dcc_restore_glz_dictionary(dcc, + migrate->glz_dict_id, + &migrate->glz_dict_data); + return dcc->glz_dict != NULL; } static int display_channel_handle_migrate_mark(RedChannelClient *rcc) @@ -4738,7 +4583,7 @@ static int display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t s PIPE_ITEM_TYPE_PIXMAP_RESET); } - if (display_channel_handle_migrate_glz_dictionary(dcc, migrate_data)) { + if (dcc_handle_migrate_glz_dictionary(dcc, migrate_data)) { dcc->glz = glz_encoder_create(dcc->common.id, dcc->glz_dict->dict, &dcc->glz_data.usr); if (!dcc->glz) { @@ -4778,83 +4623,6 @@ static int display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t s return TRUE; } -static int display_channel_handle_stream_report(DisplayChannelClient *dcc, - SpiceMsgcDisplayStreamReport *stream_report) -{ - StreamAgent *stream_agent; - - if (stream_report->stream_id >= NUM_STREAMS) { - spice_warning("stream_report: invalid stream id %u", stream_report->stream_id); - return FALSE; - } - stream_agent = &dcc->stream_agents[stream_report->stream_id]; - if (!stream_agent->mjpeg_encoder) { - spice_info("stream_report: no encoder for stream id %u." - "Probably the stream has been destroyed", stream_report->stream_id); - return TRUE; - } - - if (stream_report->unique_id != stream_agent->report_id) { - spice_warning("local reoprt-id (%u) != msg report-id (%u)", - stream_agent->report_id, stream_report->unique_id); - return TRUE; - } - mjpeg_encoder_client_stream_report(stream_agent->mjpeg_encoder, - stream_report->num_frames, - stream_report->num_drops, - stream_report->start_frame_mm_time, - stream_report->end_frame_mm_time, - stream_report->last_frame_delay, - stream_report->audio_delay); - return TRUE; -} - -static int display_channel_handle_preferred_compression(DisplayChannelClient *dcc, - SpiceMsgcDisplayPreferredCompression *pc) -{ - switch (pc->image_compression) { - case SPICE_IMAGE_COMPRESSION_AUTO_LZ: - case SPICE_IMAGE_COMPRESSION_AUTO_GLZ: - case SPICE_IMAGE_COMPRESSION_QUIC: -#ifdef USE_LZ4 - case SPICE_IMAGE_COMPRESSION_LZ4: -#endif - case SPICE_IMAGE_COMPRESSION_LZ: - case SPICE_IMAGE_COMPRESSION_GLZ: - case SPICE_IMAGE_COMPRESSION_OFF: - dcc->image_compression = pc->image_compression; - return TRUE; - default: - spice_warning("preferred-compression: unsupported image compression setting"); - return FALSE; - } -} - -static int display_channel_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, - void *message) -{ - DisplayChannelClient *dcc = RCC_TO_DCC(rcc); - - switch (type) { - case SPICE_MSGC_DISPLAY_INIT: - if (!dcc->expect_init) { - spice_warning("unexpected SPICE_MSGC_DISPLAY_INIT"); - return FALSE; - } - dcc->expect_init = FALSE; - return display_channel_init(dcc, (SpiceMsgcDisplayInit *)message); - case SPICE_MSGC_DISPLAY_STREAM_REPORT: - return display_channel_handle_stream_report(dcc, - (SpiceMsgcDisplayStreamReport *)message); - case SPICE_MSGC_DISPLAY_PREFERRED_COMPRESSION: - return display_channel_handle_preferred_compression(dcc, - (SpiceMsgcDisplayPreferredCompression *)message); - - default: - return red_channel_client_handle_message(rcc, size, type, message); - } -} - static int common_channel_config_socket(RedChannelClient *rcc) { RedClient *client = red_channel_client_get_client(rcc); @@ -5191,7 +4959,7 @@ static void display_channel_create(RedWorker *worker, int migrate, int stream_vi worker, sizeof(*display_channel), "display_channel", SPICE_CHANNEL_DISPLAY, SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER, - &cbs, display_channel_handle_message))) { + &cbs, dcc_handle_message))) { spice_warning("failed to create display channel"); return; } -- 2.4.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel