Bumps spice to 0.9.2, since it adds a new symbol. This will be 0.8.4 in 0.8 branch - the syms file is updated to contain 0.8.3 and 0.8.4.
Add an asynchronous version of update_area that updates the dirty rectangles, similarily to the sync one. The existing async version doesn't pass the dirty list at all, which is good for QXL_IO_UPDATE_AREA, but bad for the monitor command screen_dump and vnc/sdl interoperability. RHBZ: 747011 FDBZ: 41622 --- configure.ac | 2 +- server/red_dispatcher.c | 42 +++++++++++++++++++++++++++---- server/red_dispatcher.h | 9 +++++++ server/red_worker.c | 60 +++++++++++++++++++++++++++++++++------------- server/red_worker.h | 3 ++ server/spice-server.syms | 5 ++++ server/spice.h | 6 ++++- 7 files changed, 102 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index 1c15e74..a617096 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.57]) m4_define([SPICE_MAJOR], 0) m4_define([SPICE_MINOR], 10) -m4_define([SPICE_MICRO], 1) +m4_define([SPICE_MICRO], 2) AC_INIT(spice, [SPICE_MAJOR.SPICE_MINOR.SPICE_MICRO], [], spice) diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c index 321232b..5b8097c 100644 --- a/server/red_dispatcher.c +++ b/server/red_dispatcher.c @@ -334,6 +334,28 @@ static void red_dispatcher_update_area_async(RedDispatcher *dispatcher, &payload); } +static void red_dispatcher_update_area_dirty_async(RedDispatcher *dispatcher, + uint32_t surface_id, + struct QXLRect *qxl_area, + struct QXLRect *qxl_dirty_rects, + uint32_t num_dirty_rects, + uint32_t clear_dirty_region, + uint64_t cookie) +{ + RedWorkerMessage message = RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC; + RedWorkerMessageUpdateDirtyAsync payload; + + payload.base.cmd = async_command_alloc(dispatcher, message, cookie); + payload.surface_id = surface_id; + payload.qxl_area = *qxl_area; + payload.qxl_dirty_rects = qxl_dirty_rects; + payload.num_dirty_rects = num_dirty_rects; + payload.clear_dirty_region = clear_dirty_region; + dispatcher_send_message(&dispatcher->dispatcher, + message, + &payload); +} + 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) @@ -870,6 +892,17 @@ void spice_qxl_loadvm_commands(QXLInstance *instance, struct QXLCommandExt *ext, } SPICE_GNUC_VISIBLE +void spice_qxl_update_area_dirty_async(QXLInstance *instance, uint32_t surface_id, + struct QXLRect *qxl_area, struct QXLRect *dirty_rects, + uint32_t num_dirty_rects, uint32_t clear_dirty_region, + uint64_t cookie) +{ + red_dispatcher_update_area_dirty_async(instance->st->dispatcher, surface_id, qxl_area, + dirty_rects, num_dirty_rects, clear_dirty_region, + cookie); +} + +SPICE_GNUC_VISIBLE void spice_qxl_update_area_async(QXLInstance *instance, uint32_t surface_id, QXLRect *qxl_area, uint32_t clear_dirty_region, uint64_t cookie) { @@ -926,10 +959,11 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, pthread_mutex_unlock(&dispatcher->async_lock); switch (async_command->message) { case RED_WORKER_MESSAGE_UPDATE_ASYNC: - break; + case RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC: case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC: - break; case RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC: + case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC: + case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC: break; case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC: red_dispatcher_create_primary_surface_complete(dispatcher); @@ -937,10 +971,6 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC: red_dispatcher_destroy_primary_surface_complete(dispatcher); break; - case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC: - break; - case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC: - break; default: WARN("unexpected message"); } diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h index 36db4e3..8bf7433 100644 --- a/server/red_dispatcher.h +++ b/server/red_dispatcher.h @@ -89,6 +89,15 @@ typedef struct RedWorkerMessageUpdateAsync { uint32_t clear_dirty_region; } RedWorkerMessageUpdateAsync; +typedef struct RedWorkerMessageUpdateDirtyAsync { + RedWorkerMessageAsync base; + uint32_t surface_id; + QXLRect qxl_area; + QXLRect *qxl_dirty_rects; + uint32_t num_dirty_rects; + uint32_t clear_dirty_region; +} RedWorkerMessageUpdateDirtyAsync; + typedef struct RedWorkerMessageAddMemslot { QXLDevMemSlot mem_slot; } RedWorkerMessageAddMemslot; diff --git a/server/red_worker.c b/server/red_worker.c index 4c73952..19a0632 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -43,6 +43,7 @@ #include <netinet/tcp.h> #include <setjmp.h> #include <openssl/ssl.h> +#include <inttypes.h> #include <spice/qxl_dev.h> #include "spice.h" @@ -10237,17 +10238,12 @@ static void surface_dirty_region_to_rects(RedSurface *surface, free(dirty_rects); } -void handle_dev_update_async(void *opaque, void *payload) +void handle_dev_update_async_helper(RedWorker *worker, uint32_t surface_id, QXLRect qxl_area, + QXLRect *qxl_dirty_rects, uint32_t num_dirty_rects, uint32_t clear_dirty_region) { - RedWorker *worker = opaque; - RedWorkerMessageUpdateAsync *msg = payload; SpiceRect rect; - QXLRect *qxl_dirty_rects; - uint32_t num_dirty_rects; RedSurface *surface; - uint32_t surface_id = msg->surface_id; - QXLRect qxl_area = msg->qxl_area; - uint32_t clear_dirty_region = msg->clear_dirty_region; + int free_dirty = 0; red_get_rect_ptr(&rect, &qxl_area); flush_display_commands(worker); @@ -10256,20 +10252,45 @@ void handle_dev_update_async(void *opaque, void *payload) validate_surface(worker, surface_id); red_update_area(worker, &rect, surface_id); - if (!worker->qxl->st->qif->update_area_complete) { + if (!worker->qxl->st->qif->update_area_complete && !qxl_dirty_rects) { return; } + surface = &worker->surfaces[surface_id]; - num_dirty_rects = pixman_region32_n_rects(&surface->draw_dirty_region); - if (num_dirty_rects == 0) { - return; + if (!qxl_dirty_rects) { + num_dirty_rects = pixman_region32_n_rects(&surface->draw_dirty_region); + if (num_dirty_rects != 0) { + qxl_dirty_rects = spice_new0(QXLRect, num_dirty_rects); + free_dirty = 1; + } } - qxl_dirty_rects = spice_new0(QXLRect, num_dirty_rects); - surface_dirty_region_to_rects(surface, qxl_dirty_rects, num_dirty_rects, - clear_dirty_region); - worker->qxl->st->qif->update_area_complete(worker->qxl, surface_id, + if (num_dirty_rects > 0) { + surface_dirty_region_to_rects(surface, qxl_dirty_rects, num_dirty_rects, + clear_dirty_region); + } + if (worker->qxl->st->qif->update_area_complete) { + worker->qxl->st->qif->update_area_complete(worker->qxl, surface_id, qxl_dirty_rects, num_dirty_rects); - free(qxl_dirty_rects); + } + if (free_dirty) { + free(qxl_dirty_rects); + } +} + +void handle_dev_update_dirty_async(void *opaque, void *payload) +{ + RedWorkerMessageUpdateDirtyAsync *msg = payload; + + handle_dev_update_async_helper((RedWorker *)opaque, msg->surface_id, + msg->qxl_area, msg->qxl_dirty_rects, msg->num_dirty_rects, msg->clear_dirty_region); +} + +void handle_dev_update_async(void *opaque, void *payload) +{ + RedWorkerMessageUpdateAsync *msg = payload; + + handle_dev_update_async_helper((RedWorker *)opaque, msg->surface_id, + msg->qxl_area, NULL, 0, msg->clear_dirty_region); } void handle_dev_update(void *opaque, void *payload) @@ -10914,6 +10935,11 @@ static void register_callbacks(Dispatcher *dispatcher) sizeof(RedWorkerMessageUpdateAsync), DISPATCHER_ASYNC); dispatcher_register_handler(dispatcher, + RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC, + handle_dev_update_dirty_async, + sizeof(RedWorkerMessageUpdateDirtyAsync), + DISPATCHER_ASYNC); + dispatcher_register_handler(dispatcher, RED_WORKER_MESSAGE_ADD_MEMSLOT, handle_dev_add_memslot, sizeof(RedWorkerMessageAddMemslot), diff --git a/server/red_worker.h b/server/red_worker.h index 1f63d01..987563c 100644 --- a/server/red_worker.h +++ b/server/red_worker.h @@ -85,6 +85,9 @@ enum { RED_WORKER_MESSAGE_DISPLAY_CHANNEL_CREATE, RED_WORKER_MESSAGE_CURSOR_CHANNEL_CREATE, + /* support monitor async screen dump */ + RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC, + RED_WORKER_MESSAGE_COUNT // LAST }; diff --git a/server/spice-server.syms b/server/spice-server.syms index d9beec3..8b5a2ff 100644 --- a/server/spice-server.syms +++ b/server/spice-server.syms @@ -101,3 +101,8 @@ global: spice_server_add_client; spice_server_add_ssl_client; } SPICE_SERVER_0.10.0; + +SPICE_SERVER_0.10.2 { +global: + spice_qxl_update_area_dirty_async; +} SPICE_SERVER_0.10.1; diff --git a/server/spice.h b/server/spice.h index 7397655..a096fbc 100644 --- a/server/spice.h +++ b/server/spice.h @@ -22,7 +22,7 @@ #include <sys/socket.h> #include <spice/qxl_dev.h> -#define SPICE_SERVER_VERSION 0x000a01 /* release 0.10.1 */ +#define SPICE_SERVER_VERSION 0x000a02 /* release 0.10.2 */ /* interface base type */ @@ -153,6 +153,10 @@ void spice_qxl_loadvm_commands(QXLInstance *instance, struct QXLCommandExt *ext, /* async versions of commands. when complete spice calls async_complete */ void spice_qxl_update_area_async(QXLInstance *instance, uint32_t surface_id, QXLRect *qxl_area, uint32_t clear_dirty_region, uint64_t cookie); +void spice_qxl_update_area_dirty_async(QXLInstance *instance, uint32_t surface_id, + struct QXLRect *qxl_area, struct QXLRect *dirty_rects, + uint32_t num_dirty_rects, uint32_t clear_dirty_region, + uint64_t cookie); void spice_qxl_add_memslot_async(QXLInstance *instance, QXLDevMemSlot *slot, uint64_t cookie); void spice_qxl_destroy_surfaces_async(QXLInstance *instance, uint64_t cookie); void spice_qxl_destroy_primary_surface_async(QXLInstance *instance, uint32_t surface_id, uint64_t cookie); -- 1.7.9 _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/spice-devel