From 45df6087d6089e4b4433aa704acc0aa8597573f5 Mon Sep 17 00:00:00 2001 From: hujianwei Date: Wed, 9 Nov 2022 02:12:28 +0000 Subject: [PATCH] Update dmabuf and seat tests * tests/dmabuf_test.c (enum test_kind): Add XBGR888_KIND. (test_names): Add that test. (LAST_TEST): Set to XBGR888_KIND. (verify_single_step, test_single_step, test_next_step): Implement that test, but keep it disabled for now. * tests/seat_test.c (struct test_subsurface): New struct. (enum test_kind): Add TEST_GRAB_KIND. (test_names): Add that test kind. (LAST_TEST): Set to TEST_GRAB_KIND. (make_test_subsurface): New function. (run_grab_test): New functions. (test_single_step): Implement new test. (expect_enter_event): Accept surface arg. (expect_surface_enter): Adjust accordingly. (handle_wl_callback_done, wait_frame_callback): New functions. --- tests/dmabuf_test.c | 45 ++++++- tests/seat_test.c | 286 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 321 insertions(+), 10 deletions(-) diff --git a/tests/dmabuf_test.c b/tests/dmabuf_test.c index 7d0d902..65f0bac 100644 --- a/tests/dmabuf_test.c +++ b/tests/dmabuf_test.c @@ -34,15 +34,17 @@ enum test_kind { ARGB8888_KIND, ARGB8888_LINEAR_KIND, + XBGR8888_KIND, }; static const char *test_names[] = { "argb8888", "argb8888_linear", + "xbgr8888", }; -#define LAST_TEST ARGB8888_LINEAR_KIND +#define LAST_TEST XBGR8888_KIND struct test_params_data { @@ -148,6 +150,11 @@ verify_single_step (enum test_kind kind) "argb8888_linear.dump"); break; + case XBGR8888_KIND: + verify_image_data (display, test_surface_window, + "xbgr8888_implicit.dump"); + break; + default: break; } @@ -190,7 +197,7 @@ test_single_step (enum test_kind kind) { test_log ("skipping ARGB888 with linear modifier as" " that is not supported"); - test_complete (); + test_single_step (XBGR8888_KIND); } buffer = create_rainbow_buffer (GBM_FORMAT_ARGB8888, @@ -210,6 +217,36 @@ test_single_step (enum test_kind kind) wl_surface_commit (wayland_surface); wl_buffer_destroy (buffer); break; + + case XBGR8888_KIND: + + /* XBGR8888 currently does not work due to a bug in glamor. */ +#if 0 + if (!is_format_supported (DRM_FORMAT_XBGR8888, + DRM_FORMAT_MOD_INVALID)) +#endif + { + test_log ("skipping XBGR8888 with implicit modifier as" + " that is not supported"); + test_complete (); + } + + buffer = create_rainbow_buffer (GBM_FORMAT_XBGR8888, + DRM_FORMAT_MOD_INVALID, + 0x0000ff, + 0x00ff00, + 0xff0000); + + if (!buffer) + report_test_failure ("failed to create XBGR8888 buffer"); + + wl_surface_attach (wayland_surface, buffer, 0, 0); + submit_surface_damage (wayland_surface, 0, 0, + INT_MAX, INT_MAX); + submit_frame_callback (wayland_surface, kind); + wl_surface_commit (wayland_surface); + wl_buffer_destroy (buffer); + break; } } @@ -222,6 +259,10 @@ test_next_step (enum test_kind kind) test_single_step (ARGB8888_LINEAR_KIND); break; + case ARGB8888_LINEAR_KIND: + test_single_step (XBGR8888_KIND); + break; + default: break; } diff --git a/tests/seat_test.c b/tests/seat_test.c index 6fb045a..fe4c78d 100644 --- a/tests/seat_test.c +++ b/tests/seat_test.c @@ -82,11 +82,21 @@ struct test_recorded_button_event uint32_t button, state; }; +struct test_subsurface +{ + /* The subsurface itself. */ + struct wl_subsurface *subsurface; + + /* The associated surface. */ + struct wl_surface *surface; +}; + enum test_kind { MAP_WINDOW_KIND, TEST_ENTRY_KIND, TEST_CLICK_KIND, + TEST_GRAB_KIND, }; static const char *test_names[] = @@ -94,18 +104,22 @@ static const char *test_names[] = "map_window", "test_entry", "test_click", + "test_grab", }; -#define LAST_TEST TEST_CLICK_KIND +#define LAST_TEST TEST_GRAB_KIND #define TEST_SOURCE_DEVICE 4500000 /* The display. */ static struct test_display *display; +/* The subcompositor. */ +static struct wl_subcompositor *subcompositor; + /* Test interfaces. */ static struct test_interface test_interfaces[] = { - /* No interfaces yet. */ + { "wl_subcompositor", &subcompositor, &wl_subcompositor_interface, 1, }, }; /* The test surface window. */ @@ -125,11 +139,12 @@ static struct test_recorded_event *record_tail; /* Forward declarations. */ static void submit_surface_damage (struct wl_surface *, int, int, int, int); +static void wait_frame_callback (struct wl_surface *); static void expect_surface_enter (double, double); static void expect_surface_motion (double, double); static void record_events (void); static void expect_frame_event (void); -static void expect_enter_event (double, double); +static void expect_enter_event (struct wl_surface *, double, double); static void expect_motion_event (double, double); static void expect_leave_event (void); static void expect_button_event (int, int); @@ -161,6 +176,42 @@ test_get_root (void) +static struct test_subsurface * +make_test_subsurface (void) +{ + struct test_subsurface *subsurface; + + subsurface = malloc (sizeof *subsurface); + + if (!subsurface) + goto error_1; + + subsurface->surface + = wl_compositor_create_surface (display->compositor); + + if (!subsurface->surface) + goto error_2; + + subsurface->subsurface + = wl_subcompositor_get_subsurface (subcompositor, + subsurface->surface, + wayland_surface); + + if (!subsurface->subsurface) + goto error_3; + + return subsurface; + + error_3: + wl_surface_destroy (subsurface->surface); + error_2: + free (subsurface); + error_1: + return NULL; +} + + + static void run_click_test (struct test_XIButtonState *button_state) { @@ -296,11 +347,131 @@ run_click_test (struct test_XIButtonState *button_state) expect_no_events (); } +static void +run_grab_test (struct test_XIButtonState *button_state, + struct test_subsurface *child) +{ + /* First, get all events that should already have arrived. */ + wl_display_roundtrip (display->display); + + /* Next, dispatch all of the events. */ + test_seat_controller_dispatch_XI_Enter (display->seat->controller, + test_get_time (), + TEST_SOURCE_DEVICE, + XINotifyAncestor, + test_get_root (), + test_surface_window, + None, + wl_fixed_from_double (0.0), + wl_fixed_from_double (0.0), + wl_fixed_from_double (0.0), + wl_fixed_from_double (0.0), + XINotifyNormal, + False, True, NULL, NULL, + NULL); + test_seat_controller_dispatch_XI_Motion (display->seat->controller, + test_get_time (), + TEST_SOURCE_DEVICE, + 0, + test_get_root (), + test_surface_window, + None, + wl_fixed_from_double (0.0), + wl_fixed_from_double (0.0), + wl_fixed_from_double (0.0), + wl_fixed_from_double (0.0), + 0, + button_state, + NULL, NULL, NULL); + test_seat_controller_dispatch_XI_Motion (display->seat->controller, + test_get_time (), + TEST_SOURCE_DEVICE, + 0, + test_get_root (), + test_surface_window, + None, + wl_fixed_from_double (150.0), + wl_fixed_from_double (150.0), + wl_fixed_from_double (150.0), + wl_fixed_from_double (150.0), + 0, + button_state, + NULL, NULL, NULL); + test_seat_controller_dispatch_XI_ButtonPress (display->seat->controller, + test_get_time (), + TEST_SOURCE_DEVICE, + 1, + test_get_root (), + test_surface_window, + None, + wl_fixed_from_double (150.0), + wl_fixed_from_double (150.0), + wl_fixed_from_double (150.0), + wl_fixed_from_double (150.0), + 0, + button_state, + NULL, NULL, NULL); + test_XIButtonState_add_button (button_state, 1); + test_seat_controller_dispatch_XI_Motion (display->seat->controller, + test_get_time (), + TEST_SOURCE_DEVICE, + 0, + test_get_root (), + test_surface_window, + None, + wl_fixed_from_double (95.0), + wl_fixed_from_double (95.0), + wl_fixed_from_double (95.0), + wl_fixed_from_double (95.0), + 0, + button_state, + NULL, NULL, NULL); + test_seat_controller_dispatch_XI_ButtonRelease (display->seat->controller, + test_get_time (), + TEST_SOURCE_DEVICE, + 1, + test_get_root (), + test_surface_window, + None, + wl_fixed_from_double (95.0), + wl_fixed_from_double (90.0), + wl_fixed_from_double (95.0), + wl_fixed_from_double (95.0), + 0, + button_state, + NULL, NULL, NULL); + test_XIButtonState_remove_button (button_state, 1); + + /* Now, verify the events that arrive. */ + record_events (); + expect_frame_event (); + expect_enter_event (wayland_surface, 95.0, 95.0); + expect_frame_event (); + expect_leave_event (); + expect_frame_event (); + expect_button_event (BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); + expect_frame_event (); + expect_motion_event (-5.0, -5.0); + expect_frame_event (); + expect_button_event (BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); + expect_frame_event (); + expect_motion_event (50.0, 50.0); + expect_frame_event (); + expect_enter_event (child->surface, 50.0, 50.0); + expect_frame_event (); + expect_leave_event (); + expect_frame_event (); + expect_motion_event (0.0, 0.0); + expect_frame_event (); + expect_enter_event (wayland_surface, 0.0, 0.0); +} + static void test_single_step (enum test_kind kind) { - struct wl_buffer *buffer; + struct wl_buffer *buffer, *child_buffer; struct test_XIButtonState *button_state; + struct test_subsurface *child; again: test_log ("running test step: %s", test_names[kind]); @@ -316,7 +487,6 @@ test_single_step (enum test_kind kind) wl_surface_attach (wayland_surface, buffer, 0, 0); submit_surface_damage (wayland_surface, 0, 0, 500, 500); wl_surface_commit (wayland_surface); - wl_buffer_destroy (buffer); break; case TEST_ENTRY_KIND: @@ -390,6 +560,61 @@ test_single_step (enum test_kind kind) report_test_failure ("failed to obtain button state resource"); run_click_test (button_state); + kind = TEST_GRAB_KIND; + goto again; + + case TEST_GRAB_KIND: + /* Test subsurface grabbing. Create a 100x100 child of the + parent surface, and move it to 100, 100. Then, enter the + parent at 0, 0, and dispatch a motion event there. Dispatch + a motion event to 150, 150 (inside the child). Press button + 1. Dispatch a motion event to 95, 95. Finally, release + button 1. Verify that only the following events are sent in + the given order: + + enter (SERIAL, PARENT, 0.0, 0.0) + frame () + motion (TIME, 0.0, 0.0) + frame () + leave () + frame () + enter (SERIAL, CHILD, 50.0, 50.0) + frame () + motion (TIME, 50.0, 50.0) + frame () + button (SERIAL, TIME, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED) + frame () + motion (TIME, -5.0, -5.0) + frame () + button (SERIAL, TIME, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELASED) + frame () + leave () + frame () + enter (SERIAL, PARENT, 95.0, 95.0) + frame () */ + + child = make_test_subsurface (); + + if (!child) + report_test_failure ("failed to create test subsurface"); + + child_buffer = load_png_image (display, "seat_child.png"); + + if (!child_buffer) + report_test_failure ("failed to load seat_child.png"); + + wl_surface_attach (child->surface, child_buffer, 0, 0); + wl_surface_commit (child->surface); + wl_subsurface_set_position (child->subsurface, 100, 100); + + /* wait_frame_callback is necessary because input regions are + not updated until the update completes. */ + wait_frame_callback (wayland_surface); + + /* Run the test. */ + run_grab_test (button_state, child); + + break; } if (kind == LAST_TEST) @@ -428,7 +653,7 @@ expect_frame_event (void) } static void -expect_enter_event (double x, double y) +expect_enter_event (struct wl_surface *surface, double x, double y) { struct test_recorded_event *event; struct test_recorded_enter_event *enter; @@ -444,7 +669,8 @@ expect_enter_event (double x, double y) { enter = (struct test_recorded_enter_event *) event; - if (enter->x == x && enter->y == y) + if (enter->x == x && enter->y == y + && (!surface || (surface == enter->surface))) free (event); else report_test_failure ("expected enter event received " @@ -542,7 +768,7 @@ expect_surface_enter (double x, double y) /* Expect an enter event, followed by a frame event. */ expect_frame_event (); - expect_enter_event (x, y); + expect_enter_event (NULL, x, y); expect_no_events (); } @@ -814,6 +1040,50 @@ submit_surface_damage (struct wl_surface *surface, int x, int y, int width, wl_surface_damage (surface, x, y, width, height); } + + +static void +handle_wl_callback_done (void *data, struct wl_callback *callback, + uint32_t callback_data) +{ + bool *flag; + + wl_callback_destroy (callback); + + /* Now tell wait_frame_callback to break out of the loop. */ + flag = data; + *flag = true; +} + +static const struct wl_callback_listener wl_callback_listener = + { + handle_wl_callback_done, + }; + + + +static void +wait_frame_callback (struct wl_surface *surface) +{ + struct wl_callback *callback; + bool flag; + + /* Commit surface and wait for a frame callback. */ + + callback = wl_surface_frame (surface); + flag = false; + + wl_callback_add_listener (callback, &wl_callback_listener, + &flag); + wl_surface_commit (surface); + + while (!flag) + { + if (wl_display_dispatch (display->display) == -1) + die ("wl_display_dispatch"); + } +} + static void run_test (void) {