mutter/2624.patch

427 lines
15 KiB
Diff
Raw Normal View History

From 41f488a65ca67ee7e83a952c02af2fae60cc7583 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 14 Sep 2022 23:12:00 +0200
Subject: [PATCH 1/3] tests/wayland-unit: Move out sync point wait helper
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2624>
---
src/tests/meta-wayland-test-driver.c | 25 +++++++++++++++++++++++++
src/tests/meta-wayland-test-driver.h | 3 +++
src/tests/wayland-unit-tests.c | 20 +-------------------
3 files changed, 29 insertions(+), 19 deletions(-)
diff --git a/src/tests/meta-wayland-test-driver.c b/src/tests/meta-wayland-test-driver.c
index d418fa14f3..a9bb251234 100644
--- a/src/tests/meta-wayland-test-driver.c
+++ b/src/tests/meta-wayland-test-driver.c
@@ -331,3 +331,28 @@ meta_wayland_test_driver_set_property (MetaWaylandTestDriver *test_driver,
g_strdup (name),
g_strdup (value));
}
+
+static void
+on_sync_point (MetaWaylandTestDriver *test_driver,
+ unsigned int sequence,
+ struct wl_resource *surface_resource,
+ struct wl_client *wl_client,
+ unsigned int *latest_sequence)
+{
+ *latest_sequence = sequence;
+}
+
+void
+meta_wayland_test_driver_wait_for_sync_point (MetaWaylandTestDriver *test_driver,
+ unsigned int sync_point)
+{
+ gulong handler_id;
+ unsigned int latest_sequence = sync_point - 1;
+
+ handler_id = g_signal_connect (test_driver, "sync-point",
+ G_CALLBACK (on_sync_point),
+ &latest_sequence);
+ while (latest_sequence != sync_point)
+ g_main_context_iteration (NULL, TRUE);
+ g_signal_handler_disconnect (test_driver, handler_id);
+}
diff --git a/src/tests/meta-wayland-test-driver.h b/src/tests/meta-wayland-test-driver.h
index b20af74496..dbd6ab82ba 100644
--- a/src/tests/meta-wayland-test-driver.h
+++ b/src/tests/meta-wayland-test-driver.h
@@ -34,4 +34,7 @@ void meta_wayland_test_driver_set_property (MetaWaylandTestDriver *test_driver,
const char *name,
const char *value);
+void meta_wayland_test_driver_wait_for_sync_point (MetaWaylandTestDriver *test_driver,
+ unsigned int sync_point);
+
#endif /* META_WAYLAND_TEST_DRIVER_H */
diff --git a/src/tests/wayland-unit-tests.c b/src/tests/wayland-unit-tests.c
index 12dc6d8d36..2dc2f43815 100644
--- a/src/tests/wayland-unit-tests.c
+++ b/src/tests/wayland-unit-tests.c
@@ -385,28 +385,10 @@ toplevel_activation (void)
meta_wayland_test_client_finish (data.wayland_test_client);
}
-static void
-on_sync_point (MetaWaylandTestDriver *test_driver,
- unsigned int sequence,
- struct wl_resource *surface_resource,
- struct wl_client *wl_client,
- unsigned int *latest_sequence)
-{
- *latest_sequence = sequence;
-}
-
static void
wait_for_sync_point (unsigned int sync_point)
{
- gulong handler_id;
- unsigned int latest_sequence = 0;
-
- handler_id = g_signal_connect (test_driver, "sync-point",
- G_CALLBACK (on_sync_point),
- &latest_sequence);
- while (latest_sequence != sync_point)
- g_main_context_iteration (NULL, TRUE);
- g_signal_handler_disconnect (test_driver, handler_id);
+ meta_wayland_test_driver_wait_for_sync_point (test_driver, sync_point);
}
static gboolean
--
GitLab
From 85ef0d1a46b9c8d179f33208b5396b6a1f4225c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 14 Sep 2022 23:12:52 +0200
Subject: [PATCH 2/3] compositor-view/native: Check that the actor covers the
the view
If we have a window that match the size (i.e. will pass the "fits
framebuffer" low level check), that doesn't mean it matches the
position. For example, if we have two monitors 2K monitors, with two 2K
sized windows, one on monitor A, and one on monitor both monitor A and
B, overlapping both, if the latter window is above the former, it'll end
up bing scanned out on both if it ends up fitting all the other
requirements.
Fix this by checking that the paint box matches the stage view layout,
as that makes sure the actor we're painting isn't just partially on the
right view.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2387
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2624>
---
clutter/clutter/clutter-mutter.h | 5 +++++
src/compositor/meta-compositor-view-native.c | 17 +++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h
index b383ff518c..04efa5d86d 100644
--- a/clutter/clutter/clutter-mutter.h
+++ b/clutter/clutter/clutter-mutter.h
@@ -38,6 +38,11 @@
#include "clutter-stage-view-private.h"
#include "clutter.h"
+/* An epsilon larger than FLT_EPSILON that is useful when comparing coordinates
+ * while ignoring floating point precision loss that might happen during
+ * various matrix calculations. */
+#define CLUTTER_COORDINATE_EPSILON (1.0 / 256.0)
+
typedef struct _ClutterMainContext ClutterContext;
typedef ClutterBackend * (* ClutterBackendConstructor) (gpointer user_data);
diff --git a/src/compositor/meta-compositor-view-native.c b/src/compositor/meta-compositor-view-native.c
index 932d43a3b9..4c7e7f7a89 100644
--- a/src/compositor/meta-compositor-view-native.c
+++ b/src/compositor/meta-compositor-view-native.c
@@ -83,6 +83,8 @@ find_scanout_candidate (MetaCompositorView *compositor_view,
CoglFramebuffer *framebuffer;
MetaWindowActor *window_actor;
MetaWindow *window;
+ MetaRectangle view_rect;
+ ClutterActorBox actor_box;
MetaSurfaceActor *surface_actor;
MetaSurfaceActorWayland *surface_actor_wayland;
MetaWaylandSurface *surface;
@@ -126,6 +128,21 @@ find_scanout_candidate (MetaCompositorView *compositor_view,
if (meta_surface_actor_is_obscured (surface_actor))
return FALSE;
+ if (!clutter_actor_get_paint_box (CLUTTER_ACTOR (surface_actor),
+ &actor_box))
+ return FALSE;
+
+ clutter_stage_view_get_layout (stage_view, &view_rect);
+ if (!G_APPROX_VALUE (actor_box.x1, view_rect.x,
+ CLUTTER_COORDINATE_EPSILON) ||
+ !G_APPROX_VALUE (actor_box.y1, view_rect.y,
+ CLUTTER_COORDINATE_EPSILON) ||
+ !G_APPROX_VALUE (actor_box.x2, view_rect.x + view_rect.width,
+ CLUTTER_COORDINATE_EPSILON) ||
+ !G_APPROX_VALUE (actor_box.y2, view_rect.y + view_rect.height,
+ CLUTTER_COORDINATE_EPSILON))
+ return FALSE;
+
surface_actor_wayland = META_SURFACE_ACTOR_WAYLAND (surface_actor);
surface = meta_surface_actor_wayland_get_surface (surface_actor_wayland);
if (!surface)
--
GitLab
From 6601c3b02ab9d3fddce71c26618138122bc3fe7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 14 Sep 2022 23:18:37 +0200
Subject: [PATCH 3/3] 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 +++++++++++++++++--
.../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);
}
--
GitLab