From c26d1c49397adfe9e5ad1c9f1a051d67dab17d64 Mon Sep 17 00:00:00 2001 From: hujianwei Date: Sat, 5 Nov 2022 10:45:39 +0000 Subject: [PATCH] Enable map/unmap optimizations for subsurfaces * subcompositor.c (ViewMap, ViewUnmap): Union view inferior bounds whenever possible, instead of garbaging the subcompositor. * tests/subsurface_test.c (enum test_kind): New test `SUBSURFACE_STACKING_1_KIND'. (test_names): Add new name. (LAST_TEST): Set to SUBSURFACE_STACKING_1_KIND. (test_single_step): Implement SUBSURFACE_STACKING_1_KIND. --- subcompositor.c | 28 ++++++++++++++++++---- tests/subsurface_test.c | 52 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/subcompositor.c b/subcompositor.c index 1761861..5205a6b 100644 --- a/subcompositor.c +++ b/subcompositor.c @@ -1793,19 +1793,29 @@ ViewMap (View *view) if (view->subcompositor && (view->link != view->inferior || view->buffer)) { - /* Garbage the subcompositor and recompute bounds, if something - is attached to the view or it is not empty. */ - SetGarbaged (view->subcompositor); + /* Recompute bounds, if something is attached to the view or it + is not empty. */ SubcompositorUpdateBounds (view->subcompositor, DoAll); + + /* Now, if the subcompositor is still not garbaged, damage each + inferior of the view. */ + if (!IsGarbaged (view->subcompositor)) + DamageIncludingInferiors (view); } } void ViewUnmap (View *view) { + pixman_region32_t damage; + if (IsViewUnmapped (view)) return; + /* Init the damage region. */ + pixman_region32_init (&damage); + ViewUnionInferiorBounds (view, &damage); + /* Mark the view as unmapped. */ SetUnmapped (view); @@ -1824,10 +1834,18 @@ ViewUnmap (View *view) SubcompositorUpdateBounds (view->subcompositor, DoAll); - /* Garbage the view's subcompositor. */ - SetGarbaged (view->subcompositor); + /* If the subcompositor is still not garbaged, then apply + the bounds of view and all its inferiors as extra + damage. */ + if (!IsGarbaged (view->subcompositor)) + pixman_region32_union (&view->subcompositor->additional_damage, + &view->subcompositor->additional_damage, + &damage); } } + + /* Finalize the damage region. */ + pixman_region32_fini (&damage); } void diff --git a/tests/subsurface_test.c b/tests/subsurface_test.c index 6866c46..12ad683 100644 --- a/tests/subsurface_test.c +++ b/tests/subsurface_test.c @@ -31,6 +31,7 @@ enum test_kind SUBSURFACE_STACKING_KIND, SUBSURFACE_TREE_KIND, SUBSURFACE_GROW_SHRINK_KIND, + SUBSURFACE_STACKING_1_KIND, }; static const char *test_names[] = @@ -42,6 +43,7 @@ static const char *test_names[] = "subsurface_stacking", "subsurface_tree", "subsurface_grow_shrink", + "subsurface_stacking_1", }; struct test_subsurface @@ -53,7 +55,7 @@ struct test_subsurface struct wl_surface *surface; }; -#define LAST_TEST SUBSURFACE_GROW_SHRINK_KIND +#define LAST_TEST SUBSURFACE_STACKING_1_KIND /* The display. */ static struct test_display *display; @@ -427,7 +429,6 @@ test_single_step (enum test_kind kind) disappear! */ wl_surface_attach (subsurfaces[1]->surface, NULL, 0, 0); wl_surface_commit (subsurfaces[1]->surface); - wl_surface_commit (subsurfaces[1]->surface); wait_frame_callback (wayland_surface); sleep_or_verify (); @@ -504,6 +505,53 @@ test_single_step (enum test_kind kind) wl_surface_commit (subsurfaces[1]->surface); wait_frame_callback (wayland_surface); sleep_or_verify (); + + test_single_step (SUBSURFACE_STACKING_1_KIND); + break; + + case SUBSURFACE_STACKING_1_KIND: + /* Move the second subsurface above the first. Then, move the + third subsurface above the fourth, and the fourth below the + second. */ + wl_subsurface_place_above (subsurfaces[1]->subsurface, + subsurfaces[0]->surface); + wl_subsurface_place_above (subsurfaces[2]->subsurface, + subsurfaces[3]->surface); + wl_subsurface_place_below (subsurfaces[3]->subsurface, + subsurfaces[1]->surface); + + /* Next, attach some buffers to the third and fourth + surface. */ + wl_surface_attach (subsurfaces[2]->surface, gradient_png, 0, 0); + wl_surface_attach (subsurfaces[3]->surface, cow_transparent_png, + 0, 0); + submit_surface_opaque_region (subsurfaces[2]->surface, 0, 0, + 100, 300); + wl_surface_commit (subsurfaces[2]->surface); + wl_surface_commit (subsurfaces[3]->surface); + + /* Commit the first subsurface. */ + wl_surface_commit (subsurfaces[1]->surface); + wait_frame_callback (wayland_surface); + + /* The result of the test should be as follows. Above the first + subsurface lies the fourth subsurface (cow_transparent.png), + above which is the second subsurface (small.png), above which + is the third subsurface (gradient.png). */ + sleep_or_verify (); + + /* Next, test moving the third subsurface immediately below the + fourth. */ + wl_subsurface_place_below (subsurfaces[2]->subsurface, + subsurfaces[3]->surface); + wl_surface_commit (subsurfaces[1]->surface); + wait_frame_callback (wayland_surface); + + /* The result of the test should be as follows. Above the first + subsurface lies the third subsurface (gradient.png), above + which lies the fourth subsurface (cow_transparent.png), and + finally the third (small.png). */ + sleep_or_verify (); break; }