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>
This commit is contained in:
parent
85ef0d1a46
commit
6601c3b02a
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user