diff options
author | Yonit Halperin <yhalperi@redhat.com> | 2010-04-28 18:26:43 +0300 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2010-05-03 16:40:37 +0200 |
commit | 66a7c4a5e5c01623fd77e4ffc51c244a91d4b3cf (patch) | |
tree | 2e2541f91eacac09e231873becadd0fa1390c411 | |
parent | 270328e5c011c877d174ef22449175a143610baa (diff) | |
download | spice-66a7c4a5e5c01623fd77e4ffc51c244a91d4b3cf.tar.gz spice-66a7c4a5e5c01623fd77e4ffc51c244a91d4b3cf.tar.xz spice-66a7c4a5e5c01623fd77e4ffc51c244a91d4b3cf.zip |
server: fix invalid self loop in surfaces dependencies.
Cyclic dependencies between surfaces mustn't occur. They can cause invalid rendering -
recent drawables might be rendered before older ones.
-rw-r--r-- | server/red_worker.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/server/red_worker.c b/server/red_worker.c index 59cca3d1..7499d8fc 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -57,6 +57,7 @@ //#define RED_WORKER_STAT //#define DRAW_ALL //#define COMPRESS_DEBUG +//#define ACYCLIC_SURFACE_DEBUG //#define UPDATE_AREA_BY_TREE @@ -883,7 +884,9 @@ typedef struct RedSurface { Ring current; Ring current_list; Ring glz_drawables; +#ifdef ACYCLIC_SURFACE_DEBUG int current_gn; +#endif DrawContext context; Ring depend_on_me; @@ -3767,8 +3770,12 @@ static inline int red_handle_surfaces_dependencies(RedWorker *worker, Drawable * int x; for (x = 0; x < 3; ++x) { - add_to_surface_dependency(worker, drawable->surfaces_dest[x], - &drawable->depend_items[x], drawable); + // surface self dependency is handled by shadows in "current", or by + // handle_self_bitmap + if (drawable->surfaces_dest[x] != drawable->surface_id) { + add_to_surface_dependency(worker, drawable->surfaces_dest[x], + &drawable->depend_items[x], drawable); + } } return TRUE; @@ -3824,7 +3831,12 @@ static inline void red_process_drawable(RedWorker *worker, QXLDrawable *drawable printf("TEST: DRAWABLE: QXL_CLIP_TYPE_PATH\n"); #endif } - + /* + surface->refs is affected by a drawable (that is + dependent on the surface) as long as the drawable is alive. + However, surfce->depend_on_me is affected by a drawable only + as long as it is in the current tree (hasn't been rendered yet). + */ red_inc_surfaces_drawable_dependencies(worker, item); if (region_is_empty(&item->tree_item.base.rgn)) { @@ -4649,13 +4661,16 @@ static void red_update_area(RedWorker *worker, const SpiceRect *area, int surfac QRegion rgn; Drawable *last; Drawable *now; +#ifdef ACYCLIC_SURFACE_DEBUG int gn; +#endif surface = &worker->surfaces[surface_id]; -start_again: last = NULL; +#ifdef ACYCLIC_SURFACE_DEBUG gn = ++surface->current_gn; +#endif ring = &surface->current_list; ring_item = ring; @@ -4686,9 +4701,11 @@ start_again: container_cleanup(worker, container); red_draw_drawable(worker, now); release_drawable(worker, now); +#ifdef ACYCLIC_SURFACE_DEBUG if (gn != surface->current_gn) { - goto start_again; + red_error("cyclic surface dependencies"); } +#endif } while (now != last); validate_area(worker, area, surface_id); } |