示例#1
0
文件: lz.c 项目: Fantu/spice-common
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;
}
示例#2
0
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);
}
示例#3
0
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);
}
示例#4
0
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);
}
示例#5
0
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);
}
示例#6
0
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);
    }
}
示例#7
0
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);
}
示例#8
0
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);

}
示例#9
0
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);
        }
    }
}
示例#10
0
void cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32_t mode)
{
    spice_return_if_fail(cursor);

    cursor->mouse_mode = mode;
}
示例#11
0
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());
}