[mutter] tests: Add partial-overlapping scanout test



commit 6601c3b02ab9d3fddce71c26618138122bc3fe7e
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Sep 14 23:18:37 2022 +0200

    tests: Add partial-overlapping scanout test
    
    Make sure that if we wiggle a scan-out capable surface a bit, it won't
    scan out if it's not exactly in the right position. Do this by first
    making the window not fullscreen, then moving it back and forth,
    verifying the correct scanout state for each presented frame.
    
    This test addition reproduces the issue described in
    https://gitlab.gnome.org/GNOME/mutter/-/issues/2387.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2624>

 src/tests/native-kms-render.c                    | 70 ++++++++++++++++++++++--
 src/tests/wayland-test-clients/dma-buf-scanout.c | 46 +++++++++++++++-
 2 files changed, 109 insertions(+), 7 deletions(-)
---
diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c
index 278edf4bd2..6595eb5a29 100644
--- a/src/tests/native-kms-render.c
+++ b/src/tests/native-kms-render.c
@@ -32,6 +32,7 @@
 #include "core/display-private.h"
 #include "meta/meta-backend.h"
 #include "meta-test/meta-context-test.h"
+#include "tests/meta-test-utils.h"
 #include "tests/meta-wayland-test-driver.h"
 #include "tests/meta-wayland-test-utils.h"
 
@@ -44,6 +45,8 @@ typedef struct
     int n_paints;
     uint32_t fb_id;
   } scanout;
+
+  gboolean wait_for_scanout;
 } KmsRenderingTest;
 
 static MetaContext *test_context;
@@ -139,7 +142,7 @@ on_scanout_presented (ClutterStage     *stage,
   if (test->scanout.n_paints > 0)
     return;
 
-  if (test->scanout.fb_id == 0)
+  if (test->wait_for_scanout && test->scanout.fb_id == 0)
     return;
 
   device_pool = meta_backend_native_get_device_pool (backend_native);
@@ -159,7 +162,10 @@ on_scanout_presented (ClutterStage     *stage,
   drm_crtc = drmModeGetCrtc (meta_device_file_get_fd (device_file),
                              meta_kms_crtc_get_id (kms_crtc));
   g_assert_nonnull (drm_crtc);
-  g_assert_cmpuint (drm_crtc->buffer_id, ==, test->scanout.fb_id);
+  if (test->scanout.fb_id == 0)
+    g_assert_cmpuint (drm_crtc->buffer_id, !=, test->scanout.fb_id);
+  else
+    g_assert_cmpuint (drm_crtc->buffer_id, ==, test->scanout.fb_id);
   drmModeFreeCrtc (drm_crtc);
 
   meta_device_file_release (device_file);
@@ -167,13 +173,19 @@ on_scanout_presented (ClutterStage     *stage,
   g_main_loop_quit (test->loop);
 }
 
+typedef enum
+{
+  SCANOUT_WINDOW_STATE_NONE,
+  SCANOUT_WINDOW_STATE_FULLSCREEN,
+} ScanoutWindowState;
+
 static void
 meta_test_kms_render_client_scanout (void)
 {
   MetaBackend *backend = meta_context_get_backend (test_context);
   MetaWaylandCompositor *wayland_compositor =
     meta_context_get_wayland_compositor (test_context);
-  ClutterActor *stage = meta_backend_get_stage (backend);
+  ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
   MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend));
   MetaKmsDevice *kms_device = meta_kms_get_devices (kms)->data;
   KmsRenderingTest test;
@@ -183,6 +195,9 @@ meta_test_kms_render_client_scanout (void)
   gulong before_paint_handler_id;
   gulong paint_view_handler_id;
   gulong presented_handler_id;
+  MetaWindow *window;
+  MetaRectangle view_rect;
+  MetaRectangle buffer_rect;
 
   test_driver = meta_wayland_test_driver_new (wayland_compositor);
   meta_wayland_test_driver_set_property (test_driver,
@@ -195,8 +210,15 @@ meta_test_kms_render_client_scanout (void)
 
   test = (KmsRenderingTest) {
     .loop = g_main_loop_new (NULL, FALSE),
+    .wait_for_scanout = TRUE,
   };
 
+  g_assert_cmpuint (g_list_length (clutter_stage_peek_stage_views (stage)),
+                    ==,
+                    1);
+  clutter_stage_view_get_layout (clutter_stage_peek_stage_views (stage)->data,
+                                 &view_rect);
+
   paint_view_handler_id =
     g_signal_connect (stage, "paint-view",
                       G_CALLBACK (on_scanout_paint_view), &test);
@@ -212,7 +234,46 @@ meta_test_kms_render_client_scanout (void)
 
   clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
   g_main_loop_run (test.loop);
-  g_main_loop_unref (test.loop);
+
+  g_assert_cmpuint (test.scanout.fb_id, >, 0);
+
+  g_debug ("Unmake fullscreen");
+  window = meta_find_window_from_title (test_context, "dma-buf-scanout-test");
+  g_assert_true (meta_window_is_fullscreen (window));
+  meta_window_unmake_fullscreen (window);
+
+  g_debug ("Wait for fullscreen");
+  meta_wayland_test_driver_wait_for_sync_point (test_driver,
+                                                SCANOUT_WINDOW_STATE_NONE);
+  g_assert_false (meta_window_is_fullscreen (window));
+
+  g_debug ("Moving to 10, 10");
+  meta_window_move_frame (window, TRUE, 10, 10);
+
+  meta_window_get_buffer_rect (window, &buffer_rect);
+  g_assert_cmpint (buffer_rect.width, ==, view_rect.width);
+  g_assert_cmpint (buffer_rect.height, ==, view_rect.height);
+  g_assert_cmpint (buffer_rect.x, ==, 10);
+  g_assert_cmpint (buffer_rect.y, ==, 10);
+
+  test.wait_for_scanout = FALSE;
+  clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
+  g_main_loop_run (test.loop);
+
+  g_assert_cmpuint (test.scanout.fb_id, ==, 0);
+
+  g_debug ("Moving back to 0, 0");
+  meta_window_move_frame (window, TRUE, 0, 0);
+
+  meta_window_get_buffer_rect (window, &buffer_rect);
+  g_assert_cmpint (buffer_rect.width, ==, view_rect.width);
+  g_assert_cmpint (buffer_rect.height, ==, view_rect.height);
+  g_assert_cmpint (buffer_rect.x, ==, 0);
+  g_assert_cmpint (buffer_rect.y, ==, 0);
+
+  test.wait_for_scanout = TRUE;
+  clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
+  g_main_loop_run (test.loop);
 
   g_assert_cmpuint (test.scanout.fb_id, >, 0);
 
@@ -223,6 +284,7 @@ meta_test_kms_render_client_scanout (void)
 
   meta_wayland_test_driver_emit_sync_event (test_driver, 0);
   meta_wayland_test_client_finish (wayland_test_client);
+  g_main_loop_unref (test.loop);
 }
 
 static void
diff --git a/src/tests/wayland-test-clients/dma-buf-scanout.c 
b/src/tests/wayland-test-clients/dma-buf-scanout.c
index 25b9066965..273413f43f 100644
--- a/src/tests/wayland-test-clients/dma-buf-scanout.c
+++ b/src/tests/wayland-test-clients/dma-buf-scanout.c
@@ -53,6 +53,12 @@
 
 #include "linux-dmabuf-unstable-v1-client-protocol.h"
 
+typedef enum
+{
+  WINDOW_STATE_NONE,
+  WINDOW_STATE_FULLSCREEN,
+} WindowState;
+
 typedef struct _Buffer
 {
   struct wl_buffer *buffer;
@@ -78,6 +84,10 @@ struct gbm_device *gbm_device;
 
 static GList *active_buffers;
 
+static int prev_width;
+static int prev_height;
+static WindowState window_state;
+
 static struct
 {
   uint32_t format;
@@ -214,15 +224,44 @@ draw_main (int width,
   wl_surface_attach (surface, buffer->buffer, 0, 0);
 }
 
+static WindowState
+parse_xdg_toplevel_state (struct wl_array *states)
+{
+  uint32_t *state_ptr;
+
+  wl_array_for_each (state_ptr, states)
+    {
+      uint32_t state = *state_ptr;
+
+      if (state == XDG_TOPLEVEL_STATE_FULLSCREEN)
+        return WINDOW_STATE_FULLSCREEN;
+    }
+
+  return WINDOW_STATE_NONE;
+}
+
 static void
 handle_xdg_toplevel_configure (void                *user_data,
                                struct xdg_toplevel *xdg_toplevel,
                                int32_t              width,
                                int32_t              height,
-                               struct wl_array     *state)
+                               struct wl_array     *states)
 {
-  g_assert_cmpint (width, >, 0);
-  g_assert_cmpint (height, >, 0);
+  g_assert (width > 0 || prev_width > 0);
+  g_assert (height > 0 || prev_width > 0);
+
+  if (width > 0 && height > 0)
+    {
+      prev_width = width;
+      prev_height = height;
+    }
+  else
+    {
+      width = prev_width;
+      height = prev_height;
+    }
+
+  window_state = parse_xdg_toplevel_state (states);
 
   draw_main (width, height);
 }
@@ -270,6 +309,7 @@ handle_xdg_surface_configure (void               *user_data,
   frame_callback = wl_surface_frame (surface);
   wl_callback_add_listener (frame_callback, &frame_listener, NULL);
   wl_surface_commit (surface);
+  test_driver_sync_point (display->test_driver, window_state, NULL);
   wl_display_flush (display->display);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]