summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/display-channel.c156
-rw-r--r--server/red_worker.c155
2 files changed, 156 insertions, 155 deletions
diff --git a/server/display-channel.c b/server/display-channel.c
index 5e750193..d54f7256 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1261,3 +1261,159 @@ void drawable_draw(DisplayChannel *display, Drawable *drawable)
spice_warning("invalid type");
}
}
+
+static void surface_update_dest(RedSurface *surface, const SpiceRect *area)
+{
+ SpiceCanvas *canvas = surface->context.canvas;
+ int stride = surface->context.stride;
+ uint8_t *line_0 = surface->context.line_0;
+
+ if (surface->context.canvas_draws_on_surface)
+ return;
+
+ int h = area->bottom - area->top;
+ if (h == 0)
+ return;
+
+ spice_return_if_fail(stride < 0);
+
+ uint8_t *dest = line_0 + (area->top * stride) + area->left * sizeof(uint32_t);
+ dest += (h - 1) * stride;
+ canvas->ops->read_bits(canvas, dest, -stride, area);
+}
+
+/*
+ * Renders drawables for updating the requested area, but only drawables that are older
+ * than 'last' (exclusive).
+ * FIXME: merge with display_channel_draw()?
+ */
+void display_channel_draw_till(DisplayChannel *display, const SpiceRect *area, int surface_id,
+ Drawable *last)
+{
+ RedSurface *surface;
+ Drawable *surface_last = NULL;
+ Ring *ring;
+ RingItem *ring_item;
+ Drawable *now;
+ QRegion rgn;
+
+ spice_assert(last);
+ spice_assert(ring_item_is_linked(&last->list_link));
+
+ surface = &display->surfaces[surface_id];
+
+ if (surface_id != last->surface_id) {
+ // find the nearest older drawable from the appropriate surface
+ ring = &display->current_list;
+ ring_item = &last->list_link;
+ while ((ring_item = ring_next(ring, ring_item))) {
+ now = SPICE_CONTAINEROF(ring_item, Drawable, list_link);
+ if (now->surface_id == surface_id) {
+ surface_last = now;
+ break;
+ }
+ }
+ } else {
+ ring_item = ring_next(&surface->current_list, &last->surface_list_link);
+ if (ring_item) {
+ surface_last = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
+ }
+ }
+
+ if (!surface_last) {
+ return;
+ }
+
+ ring = &surface->current_list;
+ ring_item = &surface_last->surface_list_link;
+
+ region_init(&rgn);
+ region_add(&rgn, area);
+
+ // find the first older drawable that intersects with the area
+ do {
+ now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
+ if (region_intersects(&rgn, &now->tree_item.base.rgn)) {
+ surface_last = now;
+ break;
+ }
+ } while ((ring_item = ring_next(ring, ring_item)));
+
+ region_destroy(&rgn);
+
+ if (!surface_last) {
+ return;
+ }
+
+ do {
+ Container *container;
+
+ ring_item = ring_get_tail(&surface->current_list);
+ now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
+ now->refs++;
+ container = now->tree_item.base.container;
+ current_remove_drawable(display, now);
+ container_cleanup(container);
+ /* drawable_draw may call display_channel_draw for the surfaces 'now' depends on. Notice,
+ that it is valid to call display_channel_draw in this case and not display_channel_draw_till:
+ It is impossible that there was newer item then 'last' in one of the surfaces
+ that display_channel_draw is called for, Otherwise, 'now' would have already been rendered.
+ See the call for red_handle_depends_on_target_surface in red_process_draw */
+ drawable_draw(display, now);
+ display_channel_drawable_unref(display, now);
+ } while (now != surface_last);
+ surface_update_dest(surface, area);
+}
+
+void display_channel_draw(DisplayChannel *display, const SpiceRect *area, int surface_id)
+{
+ RedSurface *surface;
+ Ring *ring;
+ RingItem *ring_item;
+ QRegion rgn;
+ Drawable *last;
+ Drawable *now;
+ spice_debug("surface %d: area ==>", surface_id);
+ rect_debug(area);
+
+ spice_return_if_fail(surface_id >= 0 && surface_id < NUM_SURFACES);
+ spice_return_if_fail(area);
+ spice_return_if_fail(area->left >= 0 && area->top >= 0 &&
+ area->left < area->right && area->top < area->bottom);
+
+ surface = &display->surfaces[surface_id];
+
+ last = NULL;
+ ring = &surface->current_list;
+ ring_item = ring;
+
+ region_init(&rgn);
+ region_add(&rgn, area);
+ while ((ring_item = ring_next(ring, ring_item))) {
+ now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
+ if (region_intersects(&rgn, &now->tree_item.base.rgn)) {
+ last = now;
+ break;
+ }
+ }
+ region_destroy(&rgn);
+
+ if (!last) {
+ surface_update_dest(surface, area);
+ return;
+ }
+
+ do {
+ Container *container;
+
+ ring_item = ring_get_tail(&surface->current_list);
+ now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
+ now->refs++;
+ container = now->tree_item.base.container;
+ current_remove_drawable(display, now);
+ container_cleanup(container);
+ drawable_draw(display, now);
+ display_channel_drawable_unref(display, now);
+ } while (now != last);
+ surface_update_dest(surface, area);
+}
diff --git a/server/red_worker.c b/server/red_worker.c
index 235b6eec..19ee4e67 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -936,161 +936,6 @@ static void image_surface_init(DisplayChannel *display)
display->image_surfaces.ops = &image_surfaces_ops;
}
-static void surface_update_dest(RedSurface *surface, const SpiceRect *area)
-{
- SpiceCanvas *canvas = surface->context.canvas;
- int stride = surface->context.stride;
- uint8_t *line_0 = surface->context.line_0;
-
- if (surface->context.canvas_draws_on_surface)
- return;
-
- int h = area->bottom - area->top;
- if (h == 0)
- return;
-
- spice_return_if_fail(stride < 0);
-
- uint8_t *dest = line_0 + (area->top * stride) + area->left * sizeof(uint32_t);
- dest += (h - 1) * stride;
- canvas->ops->read_bits(canvas, dest, -stride, area);
-}
-
-/*
- Renders drawables for updating the requested area, but only drawables that are older
- than 'last' (exclusive).
-*/
-void display_channel_draw_till(DisplayChannel *display, const SpiceRect *area, int surface_id,
- Drawable *last)
-{
- RedSurface *surface;
- Drawable *surface_last = NULL;
- Ring *ring;
- RingItem *ring_item;
- Drawable *now;
- QRegion rgn;
-
- spice_assert(last);
- spice_assert(ring_item_is_linked(&last->list_link));
-
- surface = &display->surfaces[surface_id];
-
- if (surface_id != last->surface_id) {
- // find the nearest older drawable from the appropriate surface
- ring = &display->current_list;
- ring_item = &last->list_link;
- while ((ring_item = ring_next(ring, ring_item))) {
- now = SPICE_CONTAINEROF(ring_item, Drawable, list_link);
- if (now->surface_id == surface_id) {
- surface_last = now;
- break;
- }
- }
- } else {
- ring_item = ring_next(&surface->current_list, &last->surface_list_link);
- if (ring_item) {
- surface_last = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
- }
- }
-
- if (!surface_last) {
- return;
- }
-
- ring = &surface->current_list;
- ring_item = &surface_last->surface_list_link;
-
- region_init(&rgn);
- region_add(&rgn, area);
-
- // find the first older drawable that intersects with the area
- do {
- now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
- if (region_intersects(&rgn, &now->tree_item.base.rgn)) {
- surface_last = now;
- break;
- }
- } while ((ring_item = ring_next(ring, ring_item)));
-
- region_destroy(&rgn);
-
- if (!surface_last) {
- return;
- }
-
- do {
- Container *container;
-
- ring_item = ring_get_tail(&surface->current_list);
- now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
- now->refs++;
- container = now->tree_item.base.container;
- current_remove_drawable(display, now);
- container_cleanup(container);
- /* drawable_draw may call display_channel_draw for the surfaces 'now' depends on. Notice,
- that it is valid to call display_channel_draw in this case and not display_channel_draw_till:
- It is impossible that there was newer item then 'last' in one of the surfaces
- that display_channel_draw is called for, Otherwise, 'now' would have already been rendered.
- See the call for red_handle_depends_on_target_surface in red_process_draw */
- drawable_draw(display, now);
- display_channel_drawable_unref(display, now);
- } while (now != surface_last);
- surface_update_dest(surface, area);
-}
-
-void display_channel_draw(DisplayChannel *display, const SpiceRect *area, int surface_id)
-{
- RedSurface *surface;
- Ring *ring;
- RingItem *ring_item;
- QRegion rgn;
- Drawable *last;
- Drawable *now;
- spice_debug("surface %d: area ==>", surface_id);
- rect_debug(area);
-
- spice_return_if_fail(surface_id >= 0 && surface_id < NUM_SURFACES);
- spice_return_if_fail(area);
- spice_return_if_fail(area->left >= 0 && area->top >= 0 &&
- area->left < area->right && area->top < area->bottom);
-
- surface = &display->surfaces[surface_id];
-
- last = NULL;
- ring = &surface->current_list;
- ring_item = ring;
-
- region_init(&rgn);
- region_add(&rgn, area);
- while ((ring_item = ring_next(ring, ring_item))) {
- now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
- if (region_intersects(&rgn, &now->tree_item.base.rgn)) {
- last = now;
- break;
- }
- }
- region_destroy(&rgn);
-
- if (!last) {
- surface_update_dest(surface, area);
- return;
- }
-
- do {
- Container *container;
-
- ring_item = ring_get_tail(&surface->current_list);
- now = SPICE_CONTAINEROF(ring_item, Drawable, surface_list_link);
- now->refs++;
- container = now->tree_item.base.container;
- current_remove_drawable(display, now);
- container_cleanup(container);
- drawable_draw(display, now);
- display_channel_drawable_unref(display, now);
- } while (now != last);
- surface_update_dest(surface, area);
-}
-
static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty)
{
QXLCommandExt ext_cmd;