summaryrefslogtreecommitdiffstats
path: root/server/red_worker.c
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2010-06-03 10:05:06 +0300
committerAlexander Larsson <alexl@redhat.com>2010-06-09 11:43:31 +0200
commit3d7c1eaa185f91d597ccbe732aa9eff8e5336a62 (patch)
tree3fb745c654f58b57c9ee9bc856cb56583316d7d1 /server/red_worker.c
parent8b023600330588b959b151a1242b05f385633f90 (diff)
downloadspice-3d7c1eaa185f91d597ccbe732aa9eff8e5336a62.tar.gz
spice-3d7c1eaa185f91d597ccbe732aa9eff8e5336a62.tar.xz
spice-3d7c1eaa185f91d597ccbe732aa9eff8e5336a62.zip
server: optimize red_pipe_replace_rendered_drawables_with_images (lossy bitmaps support related)
Diffstat (limited to 'server/red_worker.c')
-rw-r--r--server/red_worker.c96
1 files changed, 90 insertions, 6 deletions
diff --git a/server/red_worker.c b/server/red_worker.c
index b1fb6429..efdfebc0 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -7110,6 +7110,64 @@ static inline int drawable_intersects_with_areas(Drawable *drawable, int surface
return FALSE;
}
+static inline int drawable_depends_on_areas(Drawable *drawable,
+ int surface_ids[],
+ SpiceRect surface_areas[],
+ int num_surfaces)
+{
+ int i;
+ QXLDrawable *qxl_drawable;
+ int drawable_has_shadow;
+ SpiceRect shadow_rect;
+
+ qxl_drawable = drawable->qxl_drawable;
+ drawable_has_shadow = has_shadow(qxl_drawable);
+
+ if (drawable_has_shadow) {
+ int delta_x = qxl_drawable->u.copy_bits.src_pos.x - qxl_drawable->bbox.left;
+ int delta_y = qxl_drawable->u.copy_bits.src_pos.y - qxl_drawable->bbox.top;
+
+ shadow_rect.left = qxl_drawable->u.copy_bits.src_pos.x;
+ shadow_rect.top = qxl_drawable->u.copy_bits.src_pos.y;
+ shadow_rect.right = qxl_drawable->bbox.right + delta_x;
+ shadow_rect.bottom = qxl_drawable->bbox.bottom + delta_y;
+ }
+
+ for (i = 0; i < num_surfaces; i++) {
+ int x;
+ int dep_surface_id;
+
+ for (x = 0; x < 3; ++x) {
+ dep_surface_id = drawable->surfaces_dest[x];
+ if (dep_surface_id == surface_ids[i]) {
+ if (rect_intersects(&surface_areas[i], &qxl_drawable->surfaces_rects[x])) {
+ return TRUE;
+ }
+ }
+ }
+
+ if (surface_ids[i] == qxl_drawable->surface_id) {
+ if (drawable_has_shadow) {
+ if (rect_intersects(&surface_areas[i], &shadow_rect)) {
+ return TRUE;
+ }
+ }
+
+ // not dependent on dest
+ if (qxl_drawable->effect == QXL_EFFECT_OPAQUE) {
+ continue;
+ }
+
+ if (rect_intersects(&surface_areas[i], &qxl_drawable->bbox)) {
+ return TRUE;
+ }
+ }
+
+ }
+ return FALSE;
+}
+
+
static int pipe_rendered_drawables_intersect_with_areas(RedWorker *worker,
DisplayChannel *display_channel,
int surface_ids[],
@@ -7144,17 +7202,26 @@ static int pipe_rendered_drawables_intersect_with_areas(RedWorker *worker,
}
static void red_pipe_replace_rendered_drawables_with_images(RedWorker *worker,
- DisplayChannel *display_channel)
+ DisplayChannel *display_channel,
+ int first_surface_id,
+ SpiceRect *first_area)
{
+ static int resent_surface_ids[MAX_PIPE_SIZE];
+ static SpiceRect resent_areas[MAX_PIPE_SIZE]; // not pointers since drawbales may be released
+ int num_resent;
PipeItem *pipe_item;
Ring *pipe;
+ resent_surface_ids[0] = first_surface_id;
+ resent_areas[0] = *first_area;
+ num_resent = 1;
+
pipe = &display_channel->base.pipe;
- // going from the newest to oldest
- for (pipe_item = (PipeItem *)ring_get_head(pipe);
- pipe_item;
- pipe_item = (PipeItem *)ring_next(pipe, &pipe_item->link)) {
+ // going from the oldest to the newest
+ for (pipe_item = (PipeItem *)ring_get_tail(pipe);
+ pipe_item;
+ pipe_item = (PipeItem *)ring_prev(pipe, &pipe_item->link)) {
Drawable *drawable;
ImageItem *image;
if (pipe_item->type != PIPE_ITEM_TYPE_DRAW)
@@ -7162,8 +7229,23 @@ static void red_pipe_replace_rendered_drawables_with_images(RedWorker *worker,
drawable = SPICE_CONTAINEROF(pipe_item, Drawable, pipe_item);
if (ring_item_is_linked(&drawable->list_link))
continue; // item hasn't been rendered
+
+ // When a drawable command, X, depends on bitmaps that were resent,
+ // these bitmaps state at the client might not be synchronized with X
+ // (i.e., the bitmaps can be more futuristic w.r.t X). Thus, X shouldn't
+ // be rendered at the client, and we replace it with an image as well.
+ if (!drawable_depends_on_areas(drawable,
+ resent_surface_ids,
+ resent_areas,
+ num_resent)) {
+ continue;
+ }
+
image = red_add_surface_area_image(worker, drawable->qxl_drawable->surface_id,
&drawable->qxl_drawable->bbox, pipe_item, TRUE);
+ resent_surface_ids[num_resent] = drawable->qxl_drawable->surface_id;
+ resent_areas[num_resent] = drawable->qxl_drawable->bbox;
+ num_resent++;
ASSERT(image);
red_pipe_remove_drawable(worker, drawable);
@@ -7230,7 +7312,9 @@ static void red_add_lossless_drawable_dependencies(RedWorker *worker,
drawable_surface_id,
drawable_bbox,
1)) {
- red_pipe_replace_rendered_drawables_with_images(worker, display_channel);
+ red_pipe_replace_rendered_drawables_with_images(worker, display_channel,
+ drawable->surface_id,
+ &drawable->bbox);
}