[Spice-devel] [PATCH] server: spice_qxl_update_area_dirty_async
Alon Levy
alevy at redhat.com
Sun Feb 19 04:37:16 PST 2012
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
More information about the Spice-devel
mailing list