diff --git a/tests/reference/subsurface_empty_mapping-00.png b/tests/reference/subsurface_empty_mapping-00.png new file mode 100644 index 00000000..f127154c Binary files /dev/null and b/tests/reference/subsurface_empty_mapping-00.png differ diff --git a/tests/reference/subsurface_empty_mapping-01.png b/tests/reference/subsurface_empty_mapping-01.png new file mode 100644 index 00000000..19c603cc Binary files /dev/null and b/tests/reference/subsurface_empty_mapping-01.png differ diff --git a/tests/subsurface-shot-test.c b/tests/subsurface-shot-test.c index f9b967ea..16534497 100644 --- a/tests/subsurface-shot-test.c +++ b/tests/subsurface-shot-test.c @@ -280,3 +280,132 @@ TEST(subsurface_sync_damage_buffer) wl_subcompositor_destroy(subco); client_destroy(client); } + +TEST(subsurface_empty_mapping) +{ + struct client *client; + struct wl_subcompositor *subco; + struct wp_viewporter *viewporter; + struct buffer *bufs[3] = { 0 }; + struct wl_surface *surf[3] = { 0 }; + struct wl_subsurface *sub[3] = { 0 }; + struct wp_viewport *viewport; + struct rectangle clip = { 40, 40, 280, 200 }; + int fail = 0; + unsigned i; + pixman_color_t red; + pixman_color_t blue; + pixman_color_t green; + + color_rgb888(&red, 255, 0, 0); + color_rgb888(&blue, 0, 0, 255); + color_rgb888(&green, 0, 255, 0); + + client = create_client_and_test_surface(100, 50, 100, 100); + assert(client); + subco = get_subcompositor(client); + viewporter = bind_to_singleton_global(client, + &wp_viewporter_interface, 1); + + /* move the pointer clearly away from our screenshooting area */ + weston_test_move_pointer(client->test->weston_test, 0, 1, 0, 2, 30); + + /* make the parent surface red */ + surf[0] = client->surface->wl_surface; + client->surface->wl_surface = NULL; /* we stole it and destroy it */ + bufs[0] = surface_commit_color(client, surf[0], &red, 100, 100); + /* sub[0] is not used */ + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 0); + + /* create an empty subsurface on top */ + surf[1] = wl_compositor_create_surface(client->wl_compositor); + sub[1] = wl_subcompositor_get_subsurface(subco, surf[1], surf[0]); + wl_subsurface_set_desync (sub[1]); + + wl_subsurface_set_position(sub[1], 20, 20); + wl_surface_commit(surf[0]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 1); + + /* create a green subsurface on top */ + surf[2] = wl_compositor_create_surface(client->wl_compositor); + sub[2] = wl_subcompositor_get_subsurface(subco, surf[2], surf[1]); + wl_subsurface_set_desync (sub[2]); + bufs[2] = surface_commit_color(client, surf[2], &green, 100, 100); + + wl_subsurface_set_position(sub[2], 20, 20); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 2); + + wl_surface_attach(surf[1], NULL, 0, 0); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 3); + + wl_surface_set_buffer_scale (surf[1], 1); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 4); + + viewport = wp_viewporter_get_viewport(viewporter, surf[1]); + wp_viewport_set_destination(viewport, 5, 5); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 5); + + wp_viewport_set_destination(viewport, -1, -1); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 6); + + /* map the previously empty middle surface with a blue buffer */ + bufs[1] = surface_commit_color(client, surf[1], &blue, 100, 100); + + fail += check_screen(client, "subsurface_empty_mapping", 1, &clip, 7); + + /* try to trigger a recomputation of the buffer size with the + * shm-buffer potentially being released already */ + wl_surface_set_buffer_scale (surf[1], 1); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 1, &clip, 8); + + /* try more */ + wp_viewport_set_destination(viewport, 100, 100); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 1, &clip, 9); + + /* unmap the middle surface again to ensure recursive unmapping */ + wl_surface_attach(surf[1], NULL, 0, 0); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 10); + + /* remap middle surface to ensure recursive mapping */ + bufs[1] = surface_commit_color(client, surf[1], &blue, 100, 100); + + fail += check_screen(client, "subsurface_empty_mapping", 1, &clip, 11); + + assert(fail == 0); + + wp_viewport_destroy(viewport); + + for (i = 0; i < ARRAY_LENGTH(sub); i++) + if (sub[i]) + wl_subsurface_destroy(sub[i]); + + for (i = 0; i < ARRAY_LENGTH(surf); i++) + if (surf[i]) + wl_surface_destroy(surf[i]); + + for (i = 0; i < ARRAY_LENGTH(bufs); i++) + if (bufs[i]) + buffer_destroy(bufs[i]); + + wp_viewporter_destroy(viewporter); + wl_subcompositor_destroy(subco); + client_destroy(client); +}