[Spice-devel] [PATCH server 0.8 2/3] server: spice_qxl_update_area_dirty_async
Alon Levy
alevy at redhat.com
Sun Oct 9 07:29:47 PDT 2011
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.
Bumping SPICE_INTERFACE_QXL_MINOR to 2 for a compile time check.
---
server/red_dispatcher.c | 33 ++++++++++++++++++++++++++++++++-
server/red_worker.c | 42 ++++++++++++++++++++++++++++++------------
server/red_worker.h | 2 ++
server/spice-server.syms | 5 +++++
server/spice.h | 6 +++++-
5 files changed, 74 insertions(+), 14 deletions(-)
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index f846a8c..a998238 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -230,7 +230,7 @@ static RedWorkerMessage red_dispatcher_async_start(RedDispatcher *dispatcher,
pthread_mutex_lock(&dispatcher->async_lock);
if (dispatcher->async_message != RED_WORKER_MESSAGE_NOP) {
red_warn("warning: async clash. have %d, ignoring %d",
- dispatcher->async_message, message);
+ dispatcher->async_message, message);
pthread_mutex_unlock(&dispatcher->async_lock);
return RED_WORKER_MESSAGE_NOP;
}
@@ -259,6 +259,27 @@ static void red_dispatcher_update_area_async(RedDispatcher *dispatcher,
send_data(dispatcher->channel, &clear_dirty_region, sizeof(uint32_t));
}
+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_dispatcher_async_start(
+ dispatcher, RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC);
+
+ if (message == RED_WORKER_MESSAGE_NOP) {
+ return;
+ }
+
+ write_message(dispatcher->channel, &message);
+ send_data(dispatcher->channel, &cookie, sizeof(cookie));
+ send_data(dispatcher->channel, &surface_id, sizeof(uint32_t));
+ 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));
+}
+
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)
@@ -768,6 +789,15 @@ void spice_qxl_update_area_async(QXLInstance *instance, uint32_t surface_id, QXL
}
SPICE_GNUC_VISIBLE
+void spice_qxl_update_area_dirty_async(QXLInstance *instance, uint32_t surface_id,
+ QXLRect *qxl_area, struct QXLRect *qxl_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,
+ qxl_dirty_rects, num_dirty_rects, clear_dirty_region, cookie);
+}
+
+SPICE_GNUC_VISIBLE
void spice_qxl_add_memslot_async(QXLInstance *instance, QXLDevMemSlot *slot, uint64_t cookie)
{
red_dispatcher_add_memslot_async(instance->st->dispatcher, slot, cookie);
@@ -809,6 +839,7 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t co
pthread_mutex_lock(&dispatcher->async_lock);
switch (dispatcher->async_message) {
case RED_WORKER_MESSAGE_UPDATE_ASYNC:
+ case RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC:
break;
case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC:
break;
diff --git a/server/red_worker.c b/server/red_worker.c
index 0d67586..e74f3a4 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -30,6 +30,7 @@
#include <netinet/tcp.h>
#include <setjmp.h>
#include <openssl/ssl.h>
+#include <inttypes.h>
#include <spice/qxl_dev.h>
#include "spice.h"
@@ -9665,18 +9666,23 @@ static void surface_dirty_region_to_rects(RedSurface *surface,
free(dirty_rects);
}
-static inline void handle_dev_update_async(RedWorker *worker)
+static inline void handle_dev_update_async(RedWorker *worker, int with_dirty)
{
QXLRect qxl_rect;
SpiceRect rect;
uint32_t surface_id;
uint32_t clear_dirty_region;
- QXLRect *qxl_dirty_rects;
+ QXLRect *qxl_dirty_rects = NULL;
uint32_t num_dirty_rects;
RedSurface *surface;
+ red_log(2, "");
receive_data(worker->channel, &surface_id, sizeof(uint32_t));
receive_data(worker->channel, &qxl_rect, sizeof(QXLRect));
+ if (with_dirty) {
+ 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));
red_get_rect_ptr(&rect, &qxl_rect);
@@ -9686,20 +9692,27 @@ static inline void handle_dev_update_async(RedWorker *worker)
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 && !with_dirty) {
return;
}
surface = &worker->surfaces[surface_id];
- num_dirty_rects = pixman_region32_n_rects(&surface->draw_dirty_region);
- if (num_dirty_rects == 0) {
- return;
+ if (!with_dirty) {
+ 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);
+ }
}
- 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 (!with_dirty) {
+ free(qxl_dirty_rects);
+ }
}
static inline void handle_dev_update(RedWorker *worker)
@@ -9950,6 +9963,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
* 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_UPDATE_DIRTY_ASYNC:
case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC:
case RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC:
case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC:
@@ -9958,6 +9972,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
call_async_complete = 1;
receive_data(worker->channel, &cookie, sizeof(cookie));
+ red_log(2, "got cookie: %"PRIu64"", cookie);
break;
case RED_WORKER_MESSAGE_UPDATE:
case RED_WORKER_MESSAGE_ADD_MEMSLOT:
@@ -9975,8 +9990,11 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
}
switch (message) {
+ case RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC:
+ handle_dev_update_async(worker, 1);
+ break;
case RED_WORKER_MESSAGE_UPDATE_ASYNC:
- handle_dev_update_async(worker);
+ handle_dev_update_async(worker, 0);
break;
case RED_WORKER_MESSAGE_UPDATE:
handle_dev_update(worker);
diff --git a/server/red_worker.h b/server/red_worker.h
index e65ab19..1787f13 100644
--- a/server/red_worker.h
+++ b/server/red_worker.h
@@ -77,6 +77,8 @@ enum {
RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC,
/* suspend/windows resolution change command */
RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC,
+ /* support monitor async screen dump */
+ RED_WORKER_MESSAGE_UPDATE_DIRTY_ASYNC,
};
typedef uint32_t RedWorkerMessage;
diff --git a/server/spice-server.syms b/server/spice-server.syms
index 62cdc18..5cb63fa 100644
--- a/server/spice-server.syms
+++ b/server/spice-server.syms
@@ -85,3 +85,8 @@ global:
SPICE_SERVER_0.8.3 {
spice_server_migrate_connect;
} SPICE_SERVER_0.8.2;
+
+SPICE_SERVER_0.8.4 {
+global:
+ spice_qxl_update_area_dirty_async;
+} SPICE_SERVER_0.8.3;
diff --git a/server/spice.h b/server/spice.h
index ce2d149..967fc1e 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -90,7 +90,7 @@ struct SpiceCoreInterface {
#define SPICE_INTERFACE_QXL "qxl"
#define SPICE_INTERFACE_QXL_MAJOR 3
-#define SPICE_INTERFACE_QXL_MINOR 1
+#define SPICE_INTERFACE_QXL_MINOR 2
typedef struct QXLInterface QXLInterface;
typedef struct QXLInstance QXLInstance;
typedef struct QXLState QXLState;
@@ -147,6 +147,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 *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.6.4
More information about the Spice-devel
mailing list