> > From: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> > > Acked-by: Fabiano Fidêncio <fabiano@xxxxxxxxxxxx> > --- > server/dcc.c | 135 +++++++++++++++++++++++++++++++++++++++++++ > server/dcc.h | 5 ++ > server/red_worker.c | 161 > +--------------------------------------------------- > 3 files changed, 143 insertions(+), 158 deletions(-) > > diff --git a/server/dcc.c b/server/dcc.c > index 1c82139..5be3769 100644 > --- a/server/dcc.c > +++ b/server/dcc.c > @@ -1259,3 +1259,138 @@ int dcc_handle_message(RedChannelClient *rcc, > uint32_t size, uint16_t type, void > return red_channel_client_handle_message(rcc, size, type, msg); > } > } > + > +static int dcc_handle_migrate_glz_dictionary(DisplayChannelClient *dcc, > + SpiceMigrateDataDisplay > *migrate) > +{ > + 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_restore_glz_dictionary(dcc, > + migrate->glz_dict_id, > + &migrate->glz_dict_data); > + return dcc->glz_dict != NULL; > +} > + > +static int restore_surface(DisplayChannelClient *dcc, uint32_t surface_id) > +{ > + /* we don't process commands till we receive the migration data, thus, > + * we should have not sent any surface to the client. */ > + if (dcc->surface_client_created[surface_id]) { > + spice_warning("surface %u is already marked as client_created", > surface_id); > + return FALSE; > + } > + dcc->surface_client_created[surface_id] = TRUE; > + return TRUE; > +} > + > +static int restore_surfaces_lossless(DisplayChannelClient *dcc, > + > MigrateDisplaySurfacesAtClientLossless > *mig_surfaces) > +{ > + uint32_t i; > + > + spice_debug(NULL); > + for (i = 0; i < mig_surfaces->num_surfaces; i++) { > + uint32_t surface_id = mig_surfaces->surfaces[i].id; > + > + if (!restore_surface(dcc, surface_id)) > + return FALSE; > + } > + return TRUE; > +} > + > +static int restore_surfaces_lossy(DisplayChannelClient *dcc, > + MigrateDisplaySurfacesAtClientLossy > *mig_surfaces) > +{ > + uint32_t i; > + > + spice_debug(NULL); > + for (i = 0; i < mig_surfaces->num_surfaces; i++) { > + uint32_t surface_id = mig_surfaces->surfaces[i].id; > + SpiceMigrateDataRect *mig_lossy_rect; > + SpiceRect lossy_rect; > + > + if (!restore_surface(dcc, surface_id)) > + return FALSE; > + > + mig_lossy_rect = &mig_surfaces->surfaces[i].lossy_rect; > + lossy_rect.left = mig_lossy_rect->left; > + lossy_rect.top = mig_lossy_rect->top; > + lossy_rect.right = mig_lossy_rect->right; > + lossy_rect.bottom = mig_lossy_rect->bottom; > + region_init(&dcc->surface_client_lossy_region[surface_id]); > + region_add(&dcc->surface_client_lossy_region[surface_id], > &lossy_rect); > + } > + return TRUE; > +} > + > +int dcc_handle_migrate_data(DisplayChannelClient *dcc, uint32_t size, void > *message) > +{ > + DisplayChannel *display = DCC_TO_DC(dcc); > + int surfaces_restored = FALSE; > + SpiceMigrateDataHeader *header = (SpiceMigrateDataHeader *)message; > + SpiceMigrateDataDisplay *migrate_data = (SpiceMigrateDataDisplay > *)(header + 1); > + uint8_t *surfaces; > + int i; > + > + spice_return_val_if_fail( > + size >= (sizeof(*migrate_data) + sizeof(SpiceMigrateDataHeader)), > FALSE); > + spice_return_val_if_fail( > + migration_protocol_validate_header(header, > + SPICE_MIGRATE_DATA_DISPLAY_MAGIC, > SPICE_MIGRATE_DATA_DISPLAY_VERSION), FALSE); > + > + /* size is set to -1 in order to keep the cache frozen until the > original > + * channel client that froze the cache on the src size receives the > migrate > + * data and unfreezes the cache by setting its size > 0 and by > triggering > + * pixmap_cache_reset */ > + dcc->pixmap_cache = pixmap_cache_get(RED_CHANNEL_CLIENT(dcc)->client, > + migrate_data->pixmap_cache_id, -1); > + spice_return_val_if_fail(dcc->pixmap_cache, FALSE); > + > + pthread_mutex_lock(&dcc->pixmap_cache->lock); > + for (i = 0; i < MAX_CACHE_CLIENTS; i++) { > + dcc->pixmap_cache->sync[i] = MAX(dcc->pixmap_cache->sync[i], > + > migrate_data->pixmap_cache_clients[i]); > + } > + pthread_mutex_unlock(&dcc->pixmap_cache->lock); > + > + if (migrate_data->pixmap_cache_freezer) { > + /* activating the cache. The cache will start to be active after > + * pixmap_cache_reset is called, when handling > PIPE_ITEM_TYPE_PIXMAP_RESET */ > + dcc->pixmap_cache->size = migrate_data->pixmap_cache_size; > + red_channel_client_pipe_add_type(RED_CHANNEL_CLIENT(dcc), > PIPE_ITEM_TYPE_PIXMAP_RESET); > + } > + > + 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); > + } else { > + spice_critical("restoring global lz dictionary failed"); > + } > + > + dcc->common.is_low_bandwidth = migrate_data->low_bandwidth_setting; > + > + if (migrate_data->low_bandwidth_setting) { > + red_channel_client_ack_set_client_window(RED_CHANNEL_CLIENT(dcc), > WIDE_CLIENT_ACK_WINDOW); > + if (dcc->jpeg_state == SPICE_WAN_COMPRESSION_AUTO) { > + display->enable_jpeg = TRUE; > + } > + if (dcc->zlib_glz_state == SPICE_WAN_COMPRESSION_AUTO) { > + display->enable_zlib_glz_wrap = TRUE; > + } > + } > + > + surfaces = (uint8_t *)message + migrate_data->surfaces_at_client_ptr; > + surfaces_restored = display->enable_jpeg ? > + restore_surfaces_lossy(dcc, (MigrateDisplaySurfacesAtClientLossy > *)surfaces) : > + restore_surfaces_lossless(dcc, > (MigrateDisplaySurfacesAtClientLossless*)surfaces); > + > + spice_return_val_if_fail(surfaces_restored, FALSE); > + > + red_channel_client_pipe_add_type(RED_CHANNEL_CLIENT(dcc), > PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE); > + /* enable sending messages */ > + red_channel_client_ack_zero_messages_window(RED_CHANNEL_CLIENT(dcc)); > + return TRUE; > +} > diff --git a/server/dcc.h b/server/dcc.h > index 12bb38e..94b9195 100644 > --- a/server/dcc.h > +++ b/server/dcc.h > @@ -38,6 +38,9 @@ > /* Each drawable can refer to at most 3 images: src, brush and mask */ > #define MAX_DRAWABLE_PIXMAP_CACHE_ITEMS 3 > > +#define WIDE_CLIENT_ACK_WINDOW 40 > +#define NARROW_CLIENT_ACK_WINDOW 20 > + > typedef struct WaitForChannels { > SpiceMsgWaitForChannels header; > SpiceWaitForChannel buf[MAX_CACHE_CLIENTS]; > @@ -161,6 +164,8 @@ void dcc_start > (DisplayCha > int dcc_handle_message > (RedChannelClient *rcc, > uint32_t > size, > uint16_t > type, > void > *msg); > +int dcc_handle_migrate_data > (DisplayChannelClient *dcc, > + > uint32_t > size, void *message); > 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 e0fd6e5..5d32f4f 100644 > --- a/server/red_worker.c > +++ b/server/red_worker.c > @@ -85,9 +85,6 @@ struct SpiceWatch { > > #define MAX_PIPE_SIZE 50 > > -#define WIDE_CLIENT_ACK_WINDOW 40 > -#define NARROW_CLIENT_ACK_WINDOW 20 > - > typedef struct UpgradeItem { > PipeItem base; > int refs; > @@ -4254,20 +4251,6 @@ static inline void flush_all_qxl_commands(RedWorker > *worker) > flush_cursor_commands(worker); > } > > -static int dcc_handle_migrate_glz_dictionary(DisplayChannelClient *dcc, > - SpiceMigrateDataDisplay > *migrate) > -{ > - 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_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) > { > DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, > DisplayChannel, common.base); > @@ -4277,8 +4260,7 @@ static int > display_channel_handle_migrate_mark(RedChannelClient *rcc) > return TRUE; > } > > -static uint64_t display_channel_handle_migrate_data_get_serial( > - RedChannelClient *rcc, uint32_t size, void *message) > +static uint64_t > display_channel_handle_migrate_data_get_serial(RedChannelClient *rcc, > uint32_t size, void *message) > { > SpiceMigrateDataDisplay *migrate_data; > > @@ -4287,146 +4269,9 @@ static uint64_t > display_channel_handle_migrate_data_get_serial( > return migrate_data->message_serial; > } > > -static int display_channel_client_restore_surface(DisplayChannelClient *dcc, > uint32_t surface_id) > -{ > - /* we don't process commands till we receive the migration data, thus, > - * we should have not sent any surface to the client. */ > - if (dcc->surface_client_created[surface_id]) { > - spice_warning("surface %u is already marked as client_created", > surface_id); > - return FALSE; > - } > - dcc->surface_client_created[surface_id] = TRUE; > - return TRUE; > -} > - > -static int > display_channel_client_restore_surfaces_lossless(DisplayChannelClient *dcc, > - > MigrateDisplaySurfacesAtClientLossless > *mig_surfaces) > +static int display_channel_handle_migrate_data(RedChannelClient *rcc, > uint32_t size, void *message) > { > - uint32_t i; > - > - spice_debug(NULL); > - for (i = 0; i < mig_surfaces->num_surfaces; i++) { > - uint32_t surface_id = mig_surfaces->surfaces[i].id; > - > - if (!display_channel_client_restore_surface(dcc, surface_id)) { > - return FALSE; > - } > - } > - return TRUE; > -} > - > -static int > display_channel_client_restore_surfaces_lossy(DisplayChannelClient *dcc, > - > MigrateDisplaySurfacesAtClientLossy > *mig_surfaces) > -{ > - uint32_t i; > - > - spice_debug(NULL); > - for (i = 0; i < mig_surfaces->num_surfaces; i++) { > - uint32_t surface_id = mig_surfaces->surfaces[i].id; > - SpiceMigrateDataRect *mig_lossy_rect; > - SpiceRect lossy_rect; > - > - if (!display_channel_client_restore_surface(dcc, surface_id)) { > - return FALSE; > - } > - spice_assert(dcc->surface_client_created[surface_id]); > - > - mig_lossy_rect = &mig_surfaces->surfaces[i].lossy_rect; > - lossy_rect.left = mig_lossy_rect->left; > - lossy_rect.top = mig_lossy_rect->top; > - lossy_rect.right = mig_lossy_rect->right; > - lossy_rect.bottom = mig_lossy_rect->bottom; > - region_init(&dcc->surface_client_lossy_region[surface_id]); > - region_add(&dcc->surface_client_lossy_region[surface_id], > &lossy_rect); > - } > - return TRUE; > -} > -static int display_channel_handle_migrate_data(RedChannelClient *rcc, > uint32_t size, > - void *message) > -{ > - SpiceMigrateDataHeader *header; > - SpiceMigrateDataDisplay *migrate_data; > - DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, > DisplayChannel, common.base); > - DisplayChannelClient *dcc = RCC_TO_DCC(rcc); > - uint8_t *surfaces; > - int surfaces_restored = FALSE; > - int i; > - > - spice_debug(NULL); > - if (size < sizeof(*migrate_data) + sizeof(SpiceMigrateDataHeader)) { > - spice_error("bad message size"); > - return FALSE; > - } > - header = (SpiceMigrateDataHeader *)message; > - migrate_data = (SpiceMigrateDataDisplay *)(header + 1); > - if (!migration_protocol_validate_header(header, > - > SPICE_MIGRATE_DATA_DISPLAY_MAGIC, > - > SPICE_MIGRATE_DATA_DISPLAY_VERSION)) > { > - spice_error("bad header"); > - return FALSE; > - } > - /* size is set to -1 in order to keep the cache frozen until the > original > - * channel client that froze the cache on the src size receives the > migrate > - * data and unfreezes the cache by setting its size > 0 and by > triggering > - * pixmap_cache_reset */ > - dcc->pixmap_cache = pixmap_cache_get(RED_CHANNEL_CLIENT(dcc)->client, > - migrate_data->pixmap_cache_id, -1); > - if (!dcc->pixmap_cache) { > - return FALSE; > - } > - pthread_mutex_lock(&dcc->pixmap_cache->lock); > - for (i = 0; i < MAX_CACHE_CLIENTS; i++) { > - dcc->pixmap_cache->sync[i] = MAX(dcc->pixmap_cache->sync[i], > - > migrate_data->pixmap_cache_clients[i]); > - } > - pthread_mutex_unlock(&dcc->pixmap_cache->lock); > - > - if (migrate_data->pixmap_cache_freezer) { > - /* activating the cache. The cache will start to be active after > - * pixmap_cache_reset is called, when handling > PIPE_ITEM_TYPE_PIXMAP_RESET */ > - dcc->pixmap_cache->size = migrate_data->pixmap_cache_size; > - red_channel_client_pipe_add_type(rcc, > - PIPE_ITEM_TYPE_PIXMAP_RESET); > - } > - > - 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) { > - spice_critical("create global lz failed"); > - } > - } else { > - spice_critical("restoring global lz dictionary failed"); > - } > - > - dcc->common.is_low_bandwidth = migrate_data->low_bandwidth_setting; > - > - if (migrate_data->low_bandwidth_setting) { > - red_channel_client_ack_set_client_window(rcc, > WIDE_CLIENT_ACK_WINDOW); > - if (dcc->jpeg_state == SPICE_WAN_COMPRESSION_AUTO) { > - display_channel->enable_jpeg = TRUE; > - } > - if (dcc->zlib_glz_state == SPICE_WAN_COMPRESSION_AUTO) { > - display_channel->enable_zlib_glz_wrap = TRUE; > - } > - } > - > - surfaces = (uint8_t *)message + migrate_data->surfaces_at_client_ptr; > - if (display_channel->enable_jpeg) { > - surfaces_restored = > display_channel_client_restore_surfaces_lossy(dcc, > - (MigrateDisplaySurfacesAtClientLossy > *)surfaces); > - } else { > - surfaces_restored = > display_channel_client_restore_surfaces_lossless(dcc, > - > (MigrateDisplaySurfacesAtClientLossless*)surfaces); > - } > - > - if (!surfaces_restored) { > - return FALSE; > - } > - red_channel_client_pipe_add_type(rcc, > PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE); > - /* enable sending messages */ > - red_channel_client_ack_zero_messages_window(rcc); > - return TRUE; > + return dcc_handle_migrate_data(RCC_TO_DCC(rcc), size, message); > } > > static int common_channel_config_socket(RedChannelClient *rcc) > -- > 2.4.3 > Merged Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel