diff options
author | Alon Levy <alevy@redhat.com> | 2013-08-14 18:54:04 +0300 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2013-08-14 18:54:04 +0300 |
commit | 3e1a80c15cc1469005a0ecaa606595dede8db478 (patch) | |
tree | bb4297b758ac1192cac205c472af9889eb50c477 | |
parent | 17d322d01d1312621a9de5ea4d0f376db84f466b (diff) |
wip red_worker: batching for shared memorywip/shared-memory
-rw-r--r-- | server/red_worker.c | 71 |
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; |