static inline void encode(Encoder *encoder, uint8_t byte) { if (encoder->io_now == encoder->io_end) { if (more_io_bytes(encoder) <= 0) { encoder->usr->error(encoder->usr, "%s: no more bytes\n", __FUNCTION__); } spice_return_if_fail(encoder->io_now); } spice_return_if_fail(encoder->io_now < encoder->io_end); *(encoder->io_now++) = byte; }
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_hold_pipe_item(RedChannelClient *rcc, PipeItem *item) { CursorPipeItem *cursor_pipe_item; spice_return_if_fail(item); cursor_pipe_item = SPICE_CONTAINEROF(item, CursorPipeItem, base); cursor_pipe_item_ref(cursor_pipe_item); }
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 (red_channel_is_connected(&cursor->common.base) && (cursor->mouse_mode == SPICE_MOUSE_MODE_SERVER || cursor_cmd->type != QXL_CURSOR_MOVE || cursor_show)) { red_channel_pipes_new_add(&cursor->common.base, new_cursor_pipe_item, cursor_item); } cursor_item_unref(cursor_item); }
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); }
static void cursor_marshall(RedChannelClient *rcc, SpiceMarshaller *m, CursorPipeItem *cursor_pipe_item) { CursorChannel *cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base); CursorChannelClient *ccc = RCC_TO_CCC(rcc); CursorItem *item = cursor_pipe_item->cursor_item; PipeItem *pipe_item = &cursor_pipe_item->base; RedCursorCmd *cmd; spice_return_if_fail(cursor_channel); 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_channel->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); } }
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); }
static 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); }
void cursor_channel_reset(CursorChannel *cursor) { RedChannel *channel = &cursor->common.base; 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(channel, PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE); if (!cursor->common.during_target_migrate) { red_pipes_add_verb(channel, SPICE_MSG_CURSOR_RESET); } if (!red_channel_wait_all_sent(&cursor->common.base, DISPLAY_CLIENT_TIMEOUT)) { red_channel_apply_clients(channel, red_channel_client_disconnect_if_pending_send); } } }
void cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32_t mode) { spice_return_if_fail(cursor); cursor->mouse_mode = mode; }
void red_dispatcher_init(QXLInstance *qxl) { RedDispatcher *red_dispatcher; RedWorkerMessage message; WorkerInitData init_data; QXLDevInitInfo init_info; int r; RedChannel *display_channel; RedChannel *cursor_channel; sigset_t thread_sig_mask; sigset_t curr_sig_mask; ClientCbs client_cbs = { NULL, }; spice_return_if_fail(qxl->st->dispatcher == NULL); quic_init(); sw_canvas_init(); #ifdef USE_OPENGL gl_canvas_init(); #endif // USE_OPENGL red_dispatcher = spice_new0(RedDispatcher, 1); ring_init(&red_dispatcher->async_commands); spice_debug("red_dispatcher->async_commands.next %p", red_dispatcher->async_commands.next); dispatcher_init(&red_dispatcher->dispatcher, RED_WORKER_MESSAGE_COUNT, NULL); init_data.qxl = red_dispatcher->qxl = qxl; init_data.id = qxl->id; init_data.red_dispatcher = red_dispatcher; init_data.pending = &red_dispatcher->pending; init_data.num_renderers = num_renderers; memcpy(init_data.renderers, renderers, sizeof(init_data.renderers)); pthread_mutex_init(&red_dispatcher->async_lock, NULL); init_data.image_compression = image_compression; init_data.jpeg_state = jpeg_state; init_data.zlib_glz_state = zlib_glz_state; init_data.streaming_video = streaming_video; red_dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR; red_dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR; red_dispatcher->base.wakeup = qxl_worker_wakeup; red_dispatcher->base.oom = qxl_worker_oom; red_dispatcher->base.start = qxl_worker_start; red_dispatcher->base.stop = qxl_worker_stop; red_dispatcher->base.update_area = qxl_worker_update_area; red_dispatcher->base.add_memslot = qxl_worker_add_memslot; red_dispatcher->base.del_memslot = qxl_worker_del_memslot; red_dispatcher->base.reset_memslots = qxl_worker_reset_memslots; red_dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces; red_dispatcher->base.create_primary_surface = qxl_worker_create_primary_surface; red_dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary_surface; red_dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache; red_dispatcher->base.reset_cursor = qxl_worker_reset_cursor; red_dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait; red_dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands; qxl->st->qif->get_init_info(qxl, &init_info); init_data.memslot_id_bits = init_info.memslot_id_bits; init_data.memslot_gen_bits = init_info.memslot_gen_bits; init_data.num_memslots = init_info.num_memslots; init_data.num_memslots_groups = init_info.num_memslots_groups; init_data.internal_groupslot_id = init_info.internal_groupslot_id; init_data.n_surfaces = init_info.n_surfaces; num_active_workers = 1; sigfillset(&thread_sig_mask); sigdelset(&thread_sig_mask, SIGILL); sigdelset(&thread_sig_mask, SIGFPE); sigdelset(&thread_sig_mask, SIGSEGV); pthread_sigmask(SIG_SETMASK, &thread_sig_mask, &curr_sig_mask); if ((r = pthread_create(&red_dispatcher->worker_thread, NULL, red_worker_main, &init_data))) { spice_error("create thread failed %d", r); } pthread_sigmask(SIG_SETMASK, &curr_sig_mask, NULL); read_message(red_dispatcher->dispatcher.send_fd, &message); spice_assert(message == RED_WORKER_MESSAGE_READY); display_channel = red_dispatcher_display_channel_create(red_dispatcher); if (display_channel) { client_cbs.connect = red_dispatcher_set_display_peer; client_cbs.disconnect = red_dispatcher_disconnect_display_peer; client_cbs.migrate = red_dispatcher_display_migrate; red_channel_register_client_cbs(display_channel, &client_cbs); red_channel_set_data(display_channel, red_dispatcher); red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG); red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_STREAM_REPORT); reds_register_channel(display_channel); } cursor_channel = red_dispatcher_cursor_channel_create(red_dispatcher); if (cursor_channel) { client_cbs.connect = red_dispatcher_set_cursor_peer; client_cbs.disconnect = red_dispatcher_disconnect_cursor_peer; client_cbs.migrate = red_dispatcher_cursor_migrate; red_channel_register_client_cbs(cursor_channel, &client_cbs); red_channel_set_data(cursor_channel, red_dispatcher); reds_register_channel(cursor_channel); } qxl->st->dispatcher = red_dispatcher; red_dispatcher->next = dispatchers; dispatchers = red_dispatcher; qxl->st->qif->attache_worker(qxl, &red_dispatcher->base); qxl->st->qif->set_compression_level(qxl, calc_compression_level()); }