diff options
author | Yonit Halperin <yhalperi@redhat.com> | 2010-06-03 10:05:06 +0300 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2010-06-09 11:43:31 +0200 |
commit | 3d7c1eaa185f91d597ccbe732aa9eff8e5336a62 (patch) | |
tree | 3fb745c654f58b57c9ee9bc856cb56583316d7d1 /server/red_worker.c | |
parent | 8b023600330588b959b151a1242b05f385633f90 (diff) | |
download | spice-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.c | 96 |
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); } |