summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2013-08-14 18:54:04 +0300
committerAlon Levy <alevy@redhat.com>2013-08-14 18:54:04 +0300
commit3e1a80c15cc1469005a0ecaa606595dede8db478 (patch)
treebb4297b758ac1192cac205c472af9889eb50c477
parent17d322d01d1312621a9de5ea4d0f376db84f466b (diff)
wip red_worker: batching for shared memorywip/shared-memory
-rw-r--r--server/red_worker.c71
1 files changed, 56 insertions, 15 deletions
diff --git a/server/red_worker.c b/server/red_worker.c
index 01a18035..338582c7 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -132,6 +132,8 @@
#define ZLIB_DEFAULT_COMPRESSION_LEVEL 3
#define MIN_GLZ_SIZE_FOR_ZLIB 100
+#define SHM_DAMAGE_TIMEOUT_MS 15 /* 66 fps */
+
typedef int64_t red_time_t;
#define VALIDATE_SURFACE_RET(worker, surface_id) \
@@ -1039,6 +1041,13 @@ typedef struct RedWorker {
int driver_cap_monitors_config;
int set_client_capabilities_pending;
+
+ struct {
+ QRegion damage;
+ SpiceTimer *damage_timer;
+ int damage_timer_pending;
+ unsigned damage_events;
+ } shm;
} RedWorker;
typedef enum {
@@ -1098,8 +1107,6 @@ static void cursor_channel_client_release_item_after_push(CursorChannelClient *c
static void red_push_monitors_config(DisplayChannelClient *dcc);
-static void push_shm_damage_from_drawable(DisplayChannelClient *dcc,
- Drawable *drawable);
static void push_shm_damage(DisplayChannelClient *dcc, SpiceRect *box,
SpiceClip *clip);
@@ -1577,11 +1584,42 @@ static inline void red_pipe_add_drawable(DisplayChannelClient *dcc, Drawable *dr
red_channel_client_pipe_add(&dcc->common.base, &dpi->dpi_pipe_item);
}
+static void shm_damage_timeout(void *opaque)
+{
+ RedWorker *worker = opaque;
+ RingItem *dcc_ring_item, *next;
+ DisplayChannelClient *dcc;
+ SpiceRect damage;
+
+ region_extents(&worker->shm.damage, &damage);
+ fprintf(stderr, "%s: #%d [%d,%d,%d,%d]\n", __func__,
+ worker->shm.damage_events,
+ damage.left, damage.top, damage.right,damage.bottom);
+
+ /* XXX: collect clips too? how do you use clips with bbox? */
+ red_update_area(worker, &damage, 0);
+
+ WORKER_FOREACH_DCC_SAFE(worker, dcc_ring_item, next, dcc) {
+ push_shm_damage(dcc, &damage, NULL);
+ }
+ region_init(&worker->shm.damage);
+ worker_core.timer_cancel(worker->shm.damage_timer);
+ worker->shm.damage_timer_pending = 0;
+ worker->shm.damage_events = 0;
+}
+
static inline void red_pipes_add_drawable(RedWorker *worker, Drawable *drawable)
{
DisplayChannelClient *dcc;
RingItem *dcc_ring_item, *next;
- int did_draw = 0;
+ int did_update = 0;
+ SpiceRect *bbox = &drawable->red_drawable->bbox;
+
+ if (bbox->left == bbox->right || bbox->top == bbox->bottom) {
+ spice_warning("driver sent a drawable with empty bbox [%d,%d,%d,%d]",
+ bbox->left, bbox->top, bbox->right, bbox->bottom);
+ return;
+ }
spice_warn_if(!ring_is_empty(&drawable->pipes));
WORKER_FOREACH_DCC_SAFE(worker, dcc_ring_item, next, dcc) {
@@ -1593,12 +1631,16 @@ static inline void red_pipes_add_drawable(RedWorker *worker, Drawable *drawable)
spice_debug("read a drawable before client replied to shm offer");
continue;
}
- /* TODO: rate limit */
- if (!did_draw) {
- red_update_area(worker, &drawable->red_drawable->bbox, 0);
- did_draw = 1;
+ if (!did_update) {
+ region_add(&worker->shm.damage, &drawable->red_drawable->bbox);
+ worker->shm.damage_events++;
+ if (!worker->shm.damage_timer_pending) {
+ worker_core.timer_start(worker->shm.damage_timer,
+ SHM_DAMAGE_TIMEOUT_MS);
+ worker->shm.damage_timer_pending = 1;
+ }
+ did_update = 1;
}
- push_shm_damage_from_drawable(dcc, drawable);
} else {
red_pipe_add_drawable(dcc, drawable);
}
@@ -9920,13 +9962,6 @@ static void push_shm_damage(DisplayChannelClient *dcc, SpiceRect *box,
red_channel_client_push(rcc);
}
-static void push_shm_damage_from_drawable(DisplayChannelClient *dcc,
- Drawable *drawable)
-{
- push_shm_damage(dcc, &drawable->red_drawable->bbox,
- &drawable->red_drawable->clip);
-}
-
static void push_shm_offer(DisplayChannelClient *dcc)
{
RedChannelClient *rcc = &dcc->common.base;
@@ -12227,6 +12262,11 @@ static void red_display_cc_free_glz_drawables(RedChannelClient *rcc)
red_display_handle_glz_drawables_to_free(dcc);
}
+static void red_init_shm(RedWorker *worker)
+{
+ worker->shm.damage_timer = worker_core.timer_add(shm_damage_timeout, worker);
+}
+
SPICE_GNUC_NORETURN void *red_worker_main(void *arg)
{
RedWorker *worker = spice_malloc(sizeof(RedWorker));
@@ -12246,6 +12286,7 @@ SPICE_GNUC_NORETURN void *red_worker_main(void *arg)
red_init_lz(worker);
red_init_jpeg(worker);
red_init_zlib(worker);
+ red_init_shm(worker);
worker->event_timeout = INF_EVENT_WAIT;
for (;;) {
int i, num_events;