The new _ASYNC io's in qxl_dev listed at the end get six new api functions, and an additional callback function "async_complete". When the async version of a specific io is used, completion is notified by calling async_complete, and no READY message is written or expected by the dispatcher.
update_area has been changed to push QXLRects to the worker thread, where the conversion to SpiceRect takes place. Added api: QXLWorker: update_area_async add_memslot_async destroy_surfaces_async destroy_primary_surface_async create_primary_surface_async destroy_surface_wait_async oom_async QXLInterface: async_complete --- server/red_dispatcher.c | 179 ++++++++++++++++++++++++++++++++++++++--------- server/red_parse_qxl.c | 2 +- server/red_parse_qxl.h | 2 +- server/red_worker.c | 80 ++++++++++++++------- server/red_worker.h | 8 ++ server/spice.h | 12 +++ 6 files changed, 221 insertions(+), 62 deletions(-) diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c index 56446ab..74c7af2 100644 --- a/server/red_dispatcher.c +++ b/server/red_dispatcher.c @@ -209,38 +209,49 @@ static void update_client_mouse_allowed(void) } } -static void qxl_worker_update_area(QXLWorker *qxl_worker, uint32_t surface_id, +static void qxl_worker_update_area_helper(QXLWorker *qxl_worker, uint32_t surface_id, QXLRect *qxl_area, QXLRect *qxl_dirty_rects, - uint32_t num_dirty_rects, uint32_t clear_dirty_region) + uint32_t num_dirty_rects, uint32_t clear_dirty_region, + int async) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; - RedWorkerMessage message = RED_WORKER_MESSAGE_UPDATE; - SpiceRect *dirty_rects = spice_new0(SpiceRect, num_dirty_rects); - SpiceRect *area = spice_new0(SpiceRect, 1); - int i; - - red_get_rect_ptr(area, qxl_area); + RedWorkerMessage message; + if (async) { + message = RED_WORKER_MESSAGE_UPDATE_ASYNC; + } else { + message = RED_WORKER_MESSAGE_UPDATE; + } write_message(dispatcher->channel, &message); send_data(dispatcher->channel, &surface_id, sizeof(uint32_t)); - send_data(dispatcher->channel, &area, sizeof(SpiceRect *)); - send_data(dispatcher->channel, &dirty_rects, sizeof(SpiceRect *)); + send_data(dispatcher->channel, &qxl_area, sizeof(QXLRect *)); + send_data(dispatcher->channel, &qxl_dirty_rects, sizeof(QXLRect *)); send_data(dispatcher->channel, &num_dirty_rects, sizeof(uint32_t)); send_data(dispatcher->channel, &clear_dirty_region, sizeof(uint32_t)); + if (async) { + return; + } read_message(dispatcher->channel, &message); ASSERT(message == RED_WORKER_MESSAGE_READY); +} - for (i = 0; i < num_dirty_rects; i++) { - qxl_dirty_rects[i].top = dirty_rects[i].top; - qxl_dirty_rects[i].left = dirty_rects[i].left; - qxl_dirty_rects[i].bottom = dirty_rects[i].bottom; - qxl_dirty_rects[i].right = dirty_rects[i].right; - } +static void qxl_worker_update_area(QXLWorker *qxl_worker, uint32_t surface_id, + QXLRect *qxl_area, QXLRect *qxl_dirty_rects, + uint32_t num_dirty_rects, uint32_t clear_dirty_region) +{ + qxl_worker_update_area_helper(qxl_worker, surface_id, qxl_area, qxl_dirty_rects, num_dirty_rects, + clear_dirty_region, 0); +} - free(dirty_rects); - free(area); +static void qxl_worker_update_area_async(QXLWorker *qxl_worker, uint32_t surface_id, + QXLRect *qxl_area, QXLRect *qxl_dirty_rects, + uint32_t num_dirty_rects, uint32_t clear_dirty_region) +{ + qxl_worker_update_area_helper(qxl_worker, surface_id, qxl_area, qxl_dirty_rects, num_dirty_rects, + clear_dirty_region, 1); } + static void qxl_worker_add_memslot(QXLWorker *qxl_worker, QXLDevMemSlot *mem_slot) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; @@ -252,6 +263,15 @@ static void qxl_worker_add_memslot(QXLWorker *qxl_worker, QXLDevMemSlot *mem_slo ASSERT(message == RED_WORKER_MESSAGE_READY); } +static void qxl_worker_add_memslot_async(QXLWorker *qxl_worker, QXLDevMemSlot *mem_slot) +{ + RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; + RedWorkerMessage message = RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC; + + write_message(dispatcher->channel, &message); + send_data(dispatcher->channel, mem_slot, sizeof(QXLDevMemSlot)); +} + static void qxl_worker_del_memslot(QXLWorker *qxl_worker, uint32_t slot_group_id, uint32_t slot_id) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; @@ -272,16 +292,34 @@ static void qxl_worker_destroy_surfaces(QXLWorker *qxl_worker) ASSERT(message == RED_WORKER_MESSAGE_READY); } -static void qxl_worker_destroy_primary(QXLWorker *qxl_worker, uint32_t surface_id) +static void qxl_worker_destroy_surfaces_async(QXLWorker *qxl_worker) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; - RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE; + RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC; + + write_message(dispatcher->channel, &message); +} + +static void qxl_worker_destroy_primary_surface_helper(QXLWorker *qxl_worker, uint32_t surface_id, + int async) +{ + RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; + RedWorkerMessage message; + + if (async) { + message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC; + } else { + message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE; + } write_message(dispatcher->channel, &message); send_data(dispatcher->channel, &surface_id, sizeof(uint32_t)); - read_message(dispatcher->channel, &message); - ASSERT(message == RED_WORKER_MESSAGE_READY); + if (!async) { + read_message(dispatcher->channel, &message); + ASSERT(message == RED_WORKER_MESSAGE_READY); + } + /* in async case this is set before primary is destroyed in worker */ dispatcher->x_res = 0; dispatcher->y_res = 0; dispatcher->use_hardware_cursor = FALSE; @@ -290,11 +328,27 @@ static void qxl_worker_destroy_primary(QXLWorker *qxl_worker, uint32_t surface_i update_client_mouse_allowed(); } -static void qxl_worker_create_primary(QXLWorker *qxl_worker, uint32_t surface_id, - QXLDevSurfaceCreate *surface) +static void qxl_worker_destroy_primary_surface(QXLWorker *qxl_worker, uint32_t surface_id) +{ + qxl_worker_destroy_primary_surface_helper(qxl_worker, surface_id, 0); +} + +static void qxl_worker_destroy_primary_surface_async(QXLWorker *qxl_worker, uint32_t surface_id) +{ + qxl_worker_destroy_primary_surface_helper(qxl_worker, surface_id, 1); +} + +static void qxl_worker_create_primary_surface_helper(QXLWorker *qxl_worker, uint32_t surface_id, + QXLDevSurfaceCreate *surface, int async) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; - RedWorkerMessage message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE; + RedWorkerMessage message; + + if (async) { + message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC; + } else { + message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE; + } dispatcher->x_res = surface->width; dispatcher->y_res = surface->height; @@ -304,12 +358,26 @@ static void qxl_worker_create_primary(QXLWorker *qxl_worker, uint32_t surface_id write_message(dispatcher->channel, &message); send_data(dispatcher->channel, &surface_id, sizeof(uint32_t)); send_data(dispatcher->channel, surface, sizeof(QXLDevSurfaceCreate)); - read_message(dispatcher->channel, &message); - ASSERT(message == RED_WORKER_MESSAGE_READY); + if (!async) { + read_message(dispatcher->channel, &message); + ASSERT(message == RED_WORKER_MESSAGE_READY); + } update_client_mouse_allowed(); } +static void qxl_worker_create_primary_surface(QXLWorker *qxl_worker, uint32_t surface_id, + QXLDevSurfaceCreate *surface) +{ + qxl_worker_create_primary_surface_helper(qxl_worker, surface_id, surface, 0); +} + +static void qxl_worker_create_primary_surface_async(QXLWorker *qxl_worker, uint32_t surface_id, + QXLDevSurfaceCreate *surface) +{ + qxl_worker_create_primary_surface_helper(qxl_worker, surface_id, surface, 1); +} + static void qxl_worker_reset_image_cache(QXLWorker *qxl_worker) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; @@ -330,17 +398,37 @@ static void qxl_worker_reset_cursor(QXLWorker *qxl_worker) ASSERT(message == RED_WORKER_MESSAGE_READY); } -static void qxl_worker_destroy_surface_wait(QXLWorker *qxl_worker, uint32_t surface_id) +static void qxl_worker_destroy_surface_wait_helper(QXLWorker *qxl_worker, uint32_t surface_id, + int async) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; - RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT; + RedWorkerMessage message; + + if (async ) { + message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC; + } else { + message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT; + } write_message(dispatcher->channel, &message); send_data(dispatcher->channel, &surface_id, sizeof(uint32_t)); + if (async) { + return; + } read_message(dispatcher->channel, &message); ASSERT(message == RED_WORKER_MESSAGE_READY); } +static void qxl_worker_destroy_surface_wait(QXLWorker *qxl_worker, uint32_t surface_id) +{ + qxl_worker_destroy_surface_wait_helper(qxl_worker, surface_id, 0); +} + +static void qxl_worker_destroy_surface_wait_async(QXLWorker *qxl_worker, uint32_t surface_id) +{ + qxl_worker_destroy_surface_wait_helper(qxl_worker, surface_id, 1); +} + static void qxl_worker_reset_memslots(QXLWorker *qxl_worker) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; @@ -360,16 +448,32 @@ static void qxl_worker_wakeup(QXLWorker *qxl_worker) } } -static void qxl_worker_oom(QXLWorker *qxl_worker) +static void qxl_worker_oom_helper(QXLWorker *qxl_worker, int async) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; + RedWorkerMessage message; + if (!test_bit(RED_WORKER_PENDING_OOM, dispatcher->pending)) { - RedWorkerMessage message = RED_WORKER_MESSAGE_OOM; + if (async) { + message = RED_WORKER_MESSAGE_OOM_ASYNC; + } else { + message = RED_WORKER_MESSAGE_OOM; + } set_bit(RED_WORKER_PENDING_OOM, &dispatcher->pending); write_message(dispatcher->channel, &message); } } +static void qxl_worker_oom(QXLWorker *qxl_worker) +{ + qxl_worker_oom_helper(qxl_worker, 0); +} + +static void qxl_worker_oom_async(QXLWorker *qxl_worker) +{ + qxl_worker_oom_helper(qxl_worker, 1); +} + static void qxl_worker_start(QXLWorker *qxl_worker) { RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker; @@ -530,14 +634,23 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl) dispatcher->base.del_memslot = qxl_worker_del_memslot; dispatcher->base.reset_memslots = qxl_worker_reset_memslots; dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces; - dispatcher->base.create_primary_surface = qxl_worker_create_primary; - dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary; + dispatcher->base.create_primary_surface = qxl_worker_create_primary_surface; + dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary_surface; dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache; dispatcher->base.reset_cursor = qxl_worker_reset_cursor; dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait; dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands; + dispatcher->base.update_area_async = qxl_worker_update_area_async; + dispatcher->base.add_memslot_async = qxl_worker_add_memslot_async; + dispatcher->base.reset_memslots = qxl_worker_reset_memslots; + dispatcher->base.destroy_surfaces_async = qxl_worker_destroy_surfaces_async; + dispatcher->base.destroy_primary_surface_async = qxl_worker_destroy_primary_surface_async; + dispatcher->base.create_primary_surface_async = qxl_worker_create_primary_surface_async; + dispatcher->base.destroy_surface_wait_async = qxl_worker_destroy_surface_wait_async; + dispatcher->base.oom_async = qxl_worker_oom_async; + qxl->st->qif->get_init_info(qxl, &init_info); init_data.memslot_id_bits = init_info.memslot_id_bits; diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c index 258a541..7737c04 100644 --- a/server/red_parse_qxl.c +++ b/server/red_parse_qxl.c @@ -148,7 +148,7 @@ static void red_get_point16_ptr(SpicePoint16 *red, QXLPoint16 *qxl) red->y = qxl->y; } -void red_get_rect_ptr(SpiceRect *red, QXLRect *qxl) +void red_get_rect_ptr(SpiceRect *red, const QXLRect *qxl) { red->top = qxl->top; red->left = qxl->left; diff --git a/server/red_parse_qxl.h b/server/red_parse_qxl.h index 5de0325..a713dcf 100644 --- a/server/red_parse_qxl.h +++ b/server/red_parse_qxl.h @@ -110,7 +110,7 @@ typedef struct RedCursorCmd { uint8_t *device_data; } RedCursorCmd; -void red_get_rect_ptr(SpiceRect *red, QXLRect *qxl); +void red_get_rect_ptr(SpiceRect *red, const QXLRect *qxl); void red_get_drawable(RedMemSlotInfo *slots, int group_id, RedDrawable *red, QXLPHYSICAL addr, uint32_t flags); diff --git a/server/red_worker.c b/server/red_worker.c index 9a61e86..1480218 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -9417,20 +9417,24 @@ static void red_wait_pipe_item_sent(RedChannel *channel, PipeItem *item) static inline void handle_dev_update(RedWorker *worker) { - RedWorkerMessage message; - const SpiceRect *rect; + const QXLRect *qxl_rect; + SpiceRect *rect = spice_new0(SpiceRect, 1); + QXLRect *qxl_dirty_rects; SpiceRect *dirty_rects; RedSurface *surface; uint32_t num_dirty_rects; uint32_t surface_id; uint32_t clear_dirty_region; + int i; receive_data(worker->channel, &surface_id, sizeof(uint32_t)); - receive_data(worker->channel, &rect, sizeof(SpiceRect *)); - receive_data(worker->channel, &dirty_rects, sizeof(SpiceRect *)); + receive_data(worker->channel, &qxl_rect, sizeof(QXLRect *)); + receive_data(worker->channel, &qxl_dirty_rects, sizeof(QXLRect *)); receive_data(worker->channel, &num_dirty_rects, sizeof(uint32_t)); receive_data(worker->channel, &clear_dirty_region, sizeof(uint32_t)); + dirty_rects = spice_new0(SpiceRect, num_dirty_rects); + red_get_rect_ptr(rect, qxl_rect); flush_display_commands(worker); ASSERT(worker->running); @@ -9444,15 +9448,17 @@ static inline void handle_dev_update(RedWorker *worker) if (clear_dirty_region) { region_clear(&surface->draw_dirty_region); } - - message = RED_WORKER_MESSAGE_READY; - write_message(worker->channel, &message); + for (i = 0; i < num_dirty_rects; i++) { + qxl_dirty_rects[i].top = dirty_rects[i].top; + qxl_dirty_rects[i].left = dirty_rects[i].left; + qxl_dirty_rects[i].bottom = dirty_rects[i].bottom; + qxl_dirty_rects[i].right = dirty_rects[i].right; + } } static inline void handle_dev_add_memslot(RedWorker *worker) { - RedWorkerMessage message; QXLDevMemSlot dev_slot; receive_data(worker->channel, &dev_slot, sizeof(QXLDevMemSlot)); @@ -9460,9 +9466,6 @@ static inline void handle_dev_add_memslot(RedWorker *worker) red_memslot_info_add_slot(&worker->mem_slots, dev_slot.slot_group_id, dev_slot.slot_id, dev_slot.addr_delta, dev_slot.virt_start, dev_slot.virt_end, dev_slot.generation); - - message = RED_WORKER_MESSAGE_READY; - write_message(worker->channel, &message); } static inline void handle_dev_del_memslot(RedWorker *worker) @@ -9498,7 +9501,6 @@ static inline void destroy_surface_wait(RedWorker *worker, int surface_id) static inline void handle_dev_destroy_surface_wait(RedWorker *worker) { - RedWorkerMessage message; uint32_t surface_id; receive_data(worker->channel, &surface_id, sizeof(uint32_t)); @@ -9510,9 +9512,6 @@ static inline void handle_dev_destroy_surface_wait(RedWorker *worker) if (worker->surfaces[0].context.canvas) { destroy_surface_wait(worker, 0); } - - message = RED_WORKER_MESSAGE_READY; - write_message(worker->channel, &message); } static inline void red_cursor_reset(RedWorker *worker) @@ -9540,7 +9539,6 @@ static inline void red_cursor_reset(RedWorker *worker) static inline void handle_dev_destroy_surfaces(RedWorker *worker) { int i; - RedWorkerMessage message; red_printf(""); flush_all_qxl_commands(worker); //to handle better @@ -9563,14 +9561,10 @@ static inline void handle_dev_destroy_surfaces(RedWorker *worker) red_display_clear_glz_drawables(worker->display_channel); red_cursor_reset(worker); - - message = RED_WORKER_MESSAGE_READY; - write_message(worker->channel, &message); } static inline void handle_dev_create_primary_surface(RedWorker *worker) { - RedWorkerMessage message; uint32_t surface_id; QXLDevSurfaceCreate surface; uint8_t *line_0; @@ -9600,14 +9594,10 @@ static inline void handle_dev_create_primary_surface(RedWorker *worker) if (worker->cursor_channel) { red_channel_pipe_add_type(&worker->cursor_channel->common.base, PIPE_ITEM_TYPE_CURSOR_INIT); } - - message = RED_WORKER_MESSAGE_READY; - write_message(worker->channel, &message); } static inline void handle_dev_destroy_primary_surface(RedWorker *worker) { - RedWorkerMessage message; uint32_t surface_id; receive_data(worker->channel, &surface_id, sizeof(uint32_t)); @@ -9623,9 +9613,6 @@ static inline void handle_dev_destroy_primary_surface(RedWorker *worker) ASSERT(!worker->surfaces[surface_id].context.canvas); red_cursor_reset(worker); - - message = RED_WORKER_MESSAGE_READY; - write_message(worker->channel, &message); } static void handle_dev_input(EventListener *listener, uint32_t events) @@ -9635,10 +9622,36 @@ static void handle_dev_input(EventListener *listener, uint32_t events) RedChannel *cursor_red_channel = &worker->cursor_channel->common.base; RedChannel *display_red_channel = &worker->display_channel->common.base; int ring_is_empty; + int async = 0; + int write_ready = 0; read_message(worker->channel, &message); + /* for async messages we do the common work in the handler, and + * send a ready or call async_complete from here, hence the added switch. */ switch (message) { + case RED_WORKER_MESSAGE_UPDATE_ASYNC: + case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC: + case RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC: + case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC: + case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC: + case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC: + case RED_WORKER_MESSAGE_OOM_ASYNC: + async = 1; + break; + case RED_WORKER_MESSAGE_UPDATE: + case RED_WORKER_MESSAGE_ADD_MEMSLOT: + case RED_WORKER_MESSAGE_DESTROY_SURFACES: + case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE: + case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE: + case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT: + write_ready = 1; + default: + break; + } + + switch (message) { + case RED_WORKER_MESSAGE_UPDATE_ASYNC: case RED_WORKER_MESSAGE_UPDATE: handle_dev_update(worker); break; @@ -9646,6 +9659,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events) clear_bit(RED_WORKER_PENDING_WAKEUP, worker->pending); stat_inc_counter(worker->wakeup_counter, 1); break; + case RED_WORKER_MESSAGE_OOM_ASYNC: case RED_WORKER_MESSAGE_OOM: ASSERT(worker->running); while (red_process_commands(worker, MAX_PIPE_SIZE, &ring_is_empty)) { @@ -9670,15 +9684,19 @@ static void handle_dev_input(EventListener *listener, uint32_t events) message = RED_WORKER_MESSAGE_READY; write_message(worker->channel, &message); break; + case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC: case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT: handle_dev_destroy_surface_wait(worker); break; + case RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC: case RED_WORKER_MESSAGE_DESTROY_SURFACES: handle_dev_destroy_surfaces(worker); break; + case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC: case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE: handle_dev_create_primary_surface(worker); break; + case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC: case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE: handle_dev_destroy_primary_surface(worker); break; @@ -9805,6 +9823,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events) receive_data(worker->channel, &worker->mouse_mode, sizeof(uint32_t)); red_printf("mouse mode %u", worker->mouse_mode); break; + case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC: case RED_WORKER_MESSAGE_ADD_MEMSLOT: handle_dev_add_memslot(worker); break; @@ -9850,6 +9869,13 @@ static void handle_dev_input(EventListener *listener, uint32_t events) default: red_error("message error"); } + if (async) { + worker->qxl->st->qif->async_complete(worker->qxl); + } + if (write_ready) { + message = RED_WORKER_MESSAGE_READY; + write_message(worker->channel, &message); + } } static void handle_dev_free(EventListener *ctx) diff --git a/server/red_worker.h b/server/red_worker.h index b4e2ed2..9ed7156 100644 --- a/server/red_worker.h +++ b/server/red_worker.h @@ -70,6 +70,14 @@ enum { RED_WORKER_MESSAGE_RESET_IMAGE_CACHE, RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT, RED_WORKER_MESSAGE_LOADVM_COMMANDS, + /* async commands */ + RED_WORKER_MESSAGE_UPDATE_ASYNC, + RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC, + RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC, + RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC, + RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC, + RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC, + RED_WORKER_MESSAGE_OOM_ASYNC, }; typedef uint32_t RedWorkerMessage; diff --git a/server/spice.h b/server/spice.h index f64ff41..f0d5685 100644 --- a/server/spice.h +++ b/server/spice.h @@ -122,6 +122,17 @@ struct QXLWorker { void (*reset_cursor)(QXLWorker *worker); void (*destroy_surface_wait)(QXLWorker *worker, uint32_t surface_id); void (*loadvm_commands)(QXLWorker *worker, struct QXLCommandExt *ext, uint32_t count); + /* async versions of commands. when complete spice calls async_complete */ + void (*update_area_async)(QXLWorker *qxl_worker, uint32_t surface_id, + struct QXLRect *area, struct QXLRect *dirty_rects, + uint32_t num_dirty_rects, uint32_t clear_dirty_region); + void (*add_memslot_async)(QXLWorker *worker, QXLDevMemSlot *slot); + void (*destroy_surfaces_async)(QXLWorker *worker); + void (*destroy_primary_surface_async)(QXLWorker *worker, uint32_t surface_id); + void (*create_primary_surface_async)(QXLWorker *worker, uint32_t surface_id, + QXLDevSurfaceCreate *surface); + void (*destroy_surface_wait_async)(QXLWorker *worker, uint32_t surface_id); + void (*oom_async)(QXLWorker *worker); }; typedef struct QXLDrawArea { @@ -192,6 +203,7 @@ struct QXLInterface { int (*req_cursor_notification)(QXLInstance *qin); void (*notify_update)(QXLInstance *qin, uint32_t update_id); int (*flush_resources)(QXLInstance *qin); + void (*async_complete)(QXLInstance *qin); }; struct QXLInstance { -- 1.7.5.4 _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/spice-devel