From d3735feea6b50acef050a79fff5c4dd8143e3e38 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Mar 2010 12:55:32 +0200 Subject: QXL: redesign. --- server/red_dispatcher.c | 36 ++++++++++++++++++------------------ server/red_dispatcher.h | 2 +- server/red_worker.c | 38 +++++++++++++++++++------------------- server/red_worker.h | 2 +- server/reds.c | 20 +++++++++++--------- server/reds.h | 5 +++++ server/spice.h | 3 +-- server/vd_interface.h | 45 ++++++++++++++++++++++++++------------------- 8 files changed, 82 insertions(+), 69 deletions(-) diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c index f7c66464..3d1d6f98 100644 --- a/server/red_dispatcher.c +++ b/server/red_dispatcher.c @@ -40,7 +40,7 @@ static int num_active_workers = 0; typedef struct RedDispatcher RedDispatcher; struct RedDispatcher { QXLWorker base; - QXLInterface *qxl_interface; + QXLInstance *qxl; int channel; pthread_t worker_thread; uint32_t pending; @@ -387,7 +387,7 @@ void red_dispatcher_set_mm_time(uint32_t mm_time) { RedDispatcher *now = dispatchers; while (now) { - now->qxl_interface->set_mm_time(now->qxl_interface, mm_time); + now->qxl->st->qif->set_mm_time(now->qxl, mm_time); now = now->next; } } @@ -409,7 +409,7 @@ void red_dispatcher_on_ic_change() RedDispatcher *now = dispatchers; while (now) { RedWorkeMessage message = RED_WORKER_MESSAGE_SET_COMPRESSION; - now->qxl_interface->set_compression_level(now->qxl_interface, compression_level); + now->qxl->st->qif->set_compression_level(now->qxl, compression_level); write_message(now->channel, &message); send_data(now->channel, &image_compression, sizeof(spice_image_compression_t)); now = now->next; @@ -422,7 +422,7 @@ void red_dispatcher_on_sv_change() RedDispatcher *now = dispatchers; while (now) { RedWorkeMessage message = RED_WORKER_MESSAGE_SET_STREAMING_VIDEO; - now->qxl_interface->set_compression_level(now->qxl_interface, compression_level); + now->qxl->st->qif->set_compression_level(now->qxl, compression_level); write_message(now->channel, &message); send_data(now->channel, &streaming_video, sizeof(uint32_t)); now = now->next; @@ -458,11 +458,11 @@ uint32_t red_dispatcher_qxl_ram_size() if (!dispatchers) { return 0; } - dispatchers->qxl_interface->get_init_info(dispatchers->qxl_interface, &qxl_info); + dispatchers->qxl->st->qif->get_init_info(dispatchers->qxl, &qxl_info); return qxl_info.qxl_ram_size; } -RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id) +RedDispatcher *red_dispatcher_init(QXLInstance *qxl) { RedDispatcher *dispatcher; int channels[2]; @@ -475,9 +475,9 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id) sigset_t thread_sig_mask; sigset_t curr_sig_mask; - if (qxl_interface->pci_vendor != REDHAT_PCI_VENDOR_ID || - qxl_interface->pci_id != QXL_DEVICE_ID || - qxl_interface->pci_revision != QXL_REVISION) { + if (qxl->st->qif->pci_vendor != REDHAT_PCI_VENDOR_ID || + qxl->st->qif->pci_id != QXL_DEVICE_ID || + qxl->st->qif->pci_revision != QXL_REVISION) { red_printf("pci mismatch"); return NULL; } @@ -492,8 +492,8 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id) dispatcher = spice_new0(RedDispatcher, 1); dispatcher->channel = channels[0]; - init_data.qxl_interface = dispatcher->qxl_interface = qxl_interface; - init_data.id = id; + init_data.qxl = dispatcher->qxl = qxl; + init_data.id = qxl->id; init_data.channel = channels[1]; init_data.pending = &dispatcher->pending; init_data.num_renderers = num_renderers; @@ -502,8 +502,8 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id) init_data.image_compression = image_compression; init_data.streaming_video = streaming_video; - dispatcher->base.major_version = VD_INTERFACE_QXL_MAJOR; - dispatcher->base.major_version = VD_INTERFACE_QXL_MINOR; + dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR; + dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR; dispatcher->base.wakeup = qxl_worker_wakeup; dispatcher->base.oom = qxl_worker_oom; dispatcher->base.save = qxl_worker_save; @@ -522,7 +522,7 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id) dispatcher->base.reset_cursor = qxl_worker_reset_cursor; dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait; - qxl_interface->get_init_info(qxl_interface, &init_info); + 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; @@ -548,7 +548,7 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id) reds_channel = spice_new0(Channel, 1); reds_channel->type = SPICE_CHANNEL_DISPLAY; - reds_channel->id = id; + reds_channel->id = qxl->id; reds_channel->link = red_dispatcher_set_peer; reds_channel->shutdown = red_dispatcher_shutdown_peer; reds_channel->migrate = red_dispatcher_migrate; @@ -557,14 +557,14 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id) cursor_channel = spice_new0(Channel, 1); cursor_channel->type = SPICE_CHANNEL_CURSOR; - cursor_channel->id = id; + cursor_channel->id = qxl->id; cursor_channel->link = red_dispatcher_set_cursor_peer; cursor_channel->shutdown = red_dispatcher_shutdown_cursor_peer; cursor_channel->migrate = red_dispatcher_cursor_migrate; cursor_channel->data = dispatcher; reds_register_channel(cursor_channel); - qxl_interface->attache_worker(qxl_interface, &dispatcher->base); - qxl_interface->set_compression_level(qxl_interface, calc_compression_level()); + qxl->st->qif->attache_worker(qxl, &dispatcher->base); + qxl->st->qif->set_compression_level(qxl, calc_compression_level()); dispatcher->next = dispatchers; dispatchers = dispatcher; diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h index b0bc040f..7f8973a1 100644 --- a/server/red_dispatcher.h +++ b/server/red_dispatcher.h @@ -19,7 +19,7 @@ #define _H_RED_DISPATCHER -struct RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface, int id); +struct RedDispatcher *red_dispatcher_init(QXLInstance *qxl); void red_dispatcher_set_mm_time(uint32_t); void red_dispatcher_on_ic_change(); diff --git a/server/red_worker.c b/server/red_worker.c index 7499d8fc..b66d098c 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -921,7 +921,7 @@ typedef struct RedWorker { EventListener dev_listener; DisplayChannel *display_channel; CursorChannel *cursor_channel; - QXLInterface *qxl; + QXLInstance *qxl; int id; int channel; int running; @@ -1508,7 +1508,7 @@ static inline void red_destroy_surface(RedWorker *worker, uint32_t surface_id) release_info_ext.group_id = surface->release_group_id; release_info_ext.info = surface->release_info; - worker->qxl->release_resource(worker->qxl, release_info_ext); + worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext); } region_destroy(&surface->draw_dirty_region); @@ -1542,7 +1542,7 @@ static inline void free_qxl_drawable(RedWorker *worker, QXLDrawable *drawable, u } release_info_ext.group_id = group_id; release_info_ext.info = &drawable->release_info; - worker->qxl->release_resource(worker->qxl, release_info_ext); + worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext); } static void remove_depended_item(DependItem *item) @@ -3903,7 +3903,7 @@ static inline void red_process_surface(RedWorker *worker, QXLSurfaceCmd *surface height, stride, surface->u.surface_create.format, data); release_info_ext.group_id = group_id; release_info_ext.info = &surface->release_info; - worker->qxl->release_resource(worker->qxl, release_info_ext); + worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext); break; } case QXL_SURFACE_CMD_DESTROY: @@ -4730,7 +4730,7 @@ static void red_release_cursor(RedWorker *worker, CursorItem *cursor) cursor_cmd = cursor->qxl_cursor; release_info_ext.group_id = cursor->group_id; release_info_ext.info = &cursor_cmd->release_info; - worker->qxl->release_resource(worker->qxl, release_info_ext); + worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext); free_cursor_item(worker, cursor); } } @@ -4836,14 +4836,14 @@ static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size) int n = 0; while (!worker->cursor_channel || worker->cursor_channel->base.pipe_size <= max_pipe_size) { - if (!worker->qxl->get_cursor_command(worker->qxl, &ext_cmd)) { + if (!worker->qxl->st->qif->get_cursor_command(worker->qxl, &ext_cmd)) { if (worker->repoll_cursor_ring < CMD_RING_POLL_RETRIES) { worker->repoll_cursor_ring++; worker->epoll_timeout = MIN(worker->epoll_timeout, CMD_RING_POLL_TIMEOUT); break; } if (worker->repoll_cursor_ring > CMD_RING_POLL_RETRIES || - worker->qxl->req_cursor_notification(worker->qxl)) { + worker->qxl->st->qif->req_cursor_notification(worker->qxl)) { worker->repoll_cursor_ring++; break; } @@ -4873,14 +4873,14 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size) uint64_t start = red_now(); while (!worker->display_channel || worker->display_channel->base.pipe_size <= max_pipe_size) { - if (!worker->qxl->get_command(worker->qxl, &ext_cmd)) { + if (!worker->qxl->st->qif->get_command(worker->qxl, &ext_cmd)) { if (worker->repoll_cmd_ring < CMD_RING_POLL_RETRIES) { worker->repoll_cmd_ring++; worker->epoll_timeout = MIN(worker->epoll_timeout, CMD_RING_POLL_TIMEOUT); break; } if (worker->repoll_cmd_ring > CMD_RING_POLL_RETRIES || - worker->qxl->req_cmd_notification(worker->qxl)) { + worker->qxl->st->qif->req_cmd_notification(worker->qxl)) { worker->repoll_cmd_ring++; break; } @@ -4904,10 +4904,10 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size) surface_id = draw_cmd->surface_id; validate_surface(worker, surface_id); red_update_area(worker, &draw_cmd->area, draw_cmd->surface_id); - worker->qxl->notify_update(worker->qxl, draw_cmd->update_id); + worker->qxl->st->qif->notify_update(worker->qxl, draw_cmd->update_id); release_info_ext.group_id = ext_cmd.group_id; release_info_ext.info = &draw_cmd->release_info; - worker->qxl->release_resource(worker->qxl, release_info_ext); + worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext); break; } case QXL_CMD_MESSAGE: { @@ -4917,7 +4917,7 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size) red_printf("MESSAGE: %s", message->data); release_info_ext.group_id = ext_cmd.group_id; release_info_ext.info = &message->release_info; - worker->qxl->release_resource(worker->qxl, release_info_ext); + worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext); break; } case QXL_CMD_SURFACE: { @@ -8098,7 +8098,7 @@ static inline void flush_display_commands(RedWorker *worker) uint64_t end_time; red_process_commands(worker, MAX_PIPE_SIZE); - if (!worker->qxl->has_command(worker->qxl)) { + if (!worker->qxl->st->qif->has_command(worker->qxl)) { break; } @@ -8106,7 +8106,7 @@ static inline void flush_display_commands(RedWorker *worker) display_channel_push(worker); } - if (!worker->qxl->has_command(worker->qxl)) { + if (!worker->qxl->st->qif->has_command(worker->qxl)) { break; } end_time = red_now() + DISPLAY_CLIENT_TIMEOUT * 10; @@ -8869,7 +8869,7 @@ static void red_save_cursor(RedWorker *worker) cursor_data->data_size = local->data_size; cursor_data->_cursor.header = local->red_cursor.header; memcpy(cursor_data->_cursor.data, local->red_cursor.data, local->data_size); - worker->qxl->set_save_data(worker->qxl, cursor_data, size); + worker->qxl->st->qif->set_save_data(worker->qxl, cursor_data, size); } static LocalCursor *_new_local_cursor(SpiceCursorHeader *header, int data_size, SpicePoint16 position) @@ -8934,7 +8934,7 @@ static void red_cursor_flush(RedWorker *worker) static void red_save(RedWorker *worker) { if (!worker->cursor) { - worker->qxl->set_save_data(worker->qxl, NULL, 0); + worker->qxl->st->qif->set_save_data(worker->qxl, NULL, 0); return; } red_save_cursor(worker); @@ -8942,7 +8942,7 @@ static void red_save(RedWorker *worker) static void red_cursor_load(RedWorker *worker) { - CursorData *cursor_data = worker->qxl->get_save_data(worker->qxl); + CursorData *cursor_data = worker->qxl->st->qif->get_save_data(worker->qxl); LocalCursor *local; if (!cursor_data) { @@ -9228,7 +9228,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events) while (red_process_commands(worker, MAX_PIPE_SIZE)) { display_channel_push(worker); } - if (worker->qxl->flush_resources(worker->qxl) == 0) { + if (worker->qxl->st->qif->flush_resources(worker->qxl) == 0) { red_printf("oom current %u pipe %u", worker->current_size, worker->display_channel ? worker->display_channel->base.pipe_size : 0); red_free_some(worker); @@ -9437,7 +9437,7 @@ static void red_init(RedWorker *worker, WorkerInitData *init_data) ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE); memset(worker, 0, sizeof(RedWorker)); - worker->qxl = init_data->qxl_interface; + worker->qxl = init_data->qxl; worker->id = init_data->id; worker->channel = init_data->channel; worker->pending = init_data->pending; diff --git a/server/red_worker.h b/server/red_worker.h index 58072370..e53d5182 100644 --- a/server/red_worker.h +++ b/server/red_worker.h @@ -83,7 +83,7 @@ enum { }; typedef struct WorkerInitData { - struct QXLInterface *qxl_interface; + struct QXLInstance *qxl; int id; int channel; uint32_t *pending; diff --git a/server/reds.c b/server/reds.c index 8d6e14d1..ab1f6da9 100644 --- a/server/reds.c +++ b/server/reds.c @@ -4029,8 +4029,7 @@ static void attach_to_red_agent(VDIPortInterface *interface) } __visible__ int spice_server_add_interface(SpiceServer *s, - SpiceBaseInstance *sin, - int id) + SpiceBaseInstance *sin) { SpiceBaseInterface *interface = sin->sif; @@ -4083,17 +4082,20 @@ __visible__ int spice_server_add_interface(SpiceServer *s, red_error("migration register failed"); } - } else if (strcmp(interface->type, VD_INTERFACE_QXL) == 0) { - QXLInterface *qxl_interface; + } else if (strcmp(interface->type, SPICE_INTERFACE_QXL) == 0) { + QXLInstance *qxl; - red_printf("VD_INTERFACE_QXL"); - if (interface->major_version != VD_INTERFACE_QXL_MAJOR || - interface->minor_version < VD_INTERFACE_QXL_MINOR) { + red_printf("SPICE_INTERFACE_QXL"); + if (interface->major_version != SPICE_INTERFACE_QXL_MAJOR || + interface->minor_version < SPICE_INTERFACE_QXL_MINOR) { red_printf("unsuported qxl interface"); return -1; } - qxl_interface = (QXLInterface *)interface; - red_dispatcher_init(qxl_interface, id); + + qxl = SPICE_CONTAINEROF(sin, QXLInstance, base); + qxl->st = spice_new0(QXLState, 1); + qxl->st->qif = SPICE_CONTAINEROF(interface, QXLInterface, base); + qxl->st->dispatcher = red_dispatcher_init(qxl); } else if (strcmp(interface->type, VD_INTERFACE_TABLET) == 0) { red_printf("VD_INTERFACE_TABLET"); diff --git a/server/reds.h b/server/reds.h index 68359ae7..b3dcd4b6 100644 --- a/server/reds.h +++ b/server/reds.h @@ -66,6 +66,11 @@ struct SpiceMouseState { int dummy; }; +struct QXLState { + QXLInterface *qif; + struct RedDispatcher *dispatcher; +}; + void reds_desable_mm_timer(); void reds_enable_mm_timer(); void reds_update_mm_timer(uint32_t mm_time); diff --git a/server/spice.h b/server/spice.h index 8a7764e2..f1bc80da 100644 --- a/server/spice.h +++ b/server/spice.h @@ -41,8 +41,7 @@ int spice_server_set_tls(SpiceServer *s, int port, const char *dh_key_file, const char *ciphersuite); int spice_server_add_interface(SpiceServer *s, - SpiceBaseInstance *sin, - int id); + SpiceBaseInstance *sin); int spice_server_remove_interface(SpiceBaseInstance *sin); int spice_server_kbd_leds(SpiceKbdInstance *sin, int leds); diff --git a/server/vd_interface.h b/server/vd_interface.h index 1567b120..bbe84365 100644 --- a/server/vd_interface.h +++ b/server/vd_interface.h @@ -84,11 +84,12 @@ struct SpiceCoreInterface { }; -#define VD_INTERFACE_QXL "qxl" -#define VD_INTERFACE_QXL_MAJOR 3 -#define VD_INTERFACE_QXL_MINOR 0 +#define SPICE_INTERFACE_QXL "qxl" +#define SPICE_INTERFACE_QXL_MAJOR 3 +#define SPICE_INTERFACE_QXL_MINOR 0 typedef struct QXLInterface QXLInterface; -typedef void (*qxl_mode_change_notifier_t)(void *opaque); +typedef struct QXLInstance QXLInstance; +typedef struct QXLState QXLState; typedef struct QXLWorker QXLWorker; typedef struct QXLDevMemSlot QXLDevMemSlot; typedef struct QXLDevSurfaceCreate QXLDevSurfaceCreate; @@ -183,21 +184,27 @@ struct QXLInterface { uint16_t pci_id; uint8_t pci_revision; - void (*attache_worker)(QXLInterface *qxl, QXLWorker *qxl_worker); - void (*set_compression_level)(QXLInterface *qxl, int level); - void (*set_mm_time)(QXLInterface *qxl, uint32_t mm_time); - - void (*get_init_info)(QXLInterface *qxl, QXLDevInitInfo *info); - int (*get_command)(QXLInterface *qxl, struct QXLCommandExt *cmd); - int (*req_cmd_notification)(QXLInterface *qxl); - int (*has_command)(QXLInterface *qxl); - void (*release_resource)(QXLInterface *qxl, struct QXLReleaseInfoExt release_info); - int (*get_cursor_command)(QXLInterface *qxl, struct QXLCommandExt *cmd); - int (*req_cursor_notification)(QXLInterface *qxl); - void (*notify_update)(QXLInterface *qxl, uint32_t update_id); - void (*set_save_data)(QXLInterface *qxl, void *data, int size); - void *(*get_save_data)(QXLInterface *qxl); - int (*flush_resources)(QXLInterface *qxl); + void (*attache_worker)(QXLInstance *qin, QXLWorker *qxl_worker); + void (*set_compression_level)(QXLInstance *qin, int level); + void (*set_mm_time)(QXLInstance *qin, uint32_t mm_time); + + void (*get_init_info)(QXLInstance *qin, QXLDevInitInfo *info); + int (*get_command)(QXLInstance *qin, struct QXLCommandExt *cmd); + int (*req_cmd_notification)(QXLInstance *qin); + int (*has_command)(QXLInstance *qin); + void (*release_resource)(QXLInstance *qin, struct QXLReleaseInfoExt release_info); + int (*get_cursor_command)(QXLInstance *qin, struct QXLCommandExt *cmd); + int (*req_cursor_notification)(QXLInstance *qin); + void (*notify_update)(QXLInstance *qin, uint32_t update_id); + void (*set_save_data)(QXLInstance *qin, void *data, int size); + void *(*get_save_data)(QXLInstance *qin); + int (*flush_resources)(QXLInstance *qin); +}; + +struct QXLInstance { + SpiceBaseInstance base; + int id; + QXLState *st; }; #define SPICE_INTERFACE_KEYBOARD "keyboard" -- cgit