tests/native-kms-render: Fix failing client-scanout test
It was assuming an immediate transition from compositing (triple buffering) to direct scanout (double buffering), whereas there is a one frame delay in that transition as the buffer queue shrinks. We don't lose any frames in the transition. Signed-off-by: Mingi Sung <sungmg@saltyming.net>
This commit is contained in:
parent
e0da5bbb65
commit
1243cbbe84
1 changed files with 87 additions and 19 deletions
|
@ -39,6 +39,8 @@
|
||||||
#include "tests/meta-wayland-test-driver.h"
|
#include "tests/meta-wayland-test-driver.h"
|
||||||
#include "tests/meta-wayland-test-utils.h"
|
#include "tests/meta-wayland-test-utils.h"
|
||||||
|
|
||||||
|
#define N_FRAMES_PER_TEST 30
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int number_of_frames_left;
|
int number_of_frames_left;
|
||||||
|
@ -46,12 +48,15 @@ typedef struct
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int n_paints;
|
int n_paints;
|
||||||
uint32_t fb_id;
|
int n_presentations;
|
||||||
|
int n_direct_scanouts;
|
||||||
|
GList *fb_ids;
|
||||||
} scanout;
|
} scanout;
|
||||||
|
|
||||||
gboolean wait_for_scanout;
|
gboolean wait_for_scanout;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
int scanouts_attempted;
|
||||||
gboolean scanout_sabotaged;
|
gboolean scanout_sabotaged;
|
||||||
gboolean fallback_painted;
|
gboolean fallback_painted;
|
||||||
guint repaint_guard_id;
|
guint repaint_guard_id;
|
||||||
|
@ -101,7 +106,7 @@ meta_test_kms_render_basic (void)
|
||||||
gulong handler_id;
|
gulong handler_id;
|
||||||
|
|
||||||
test = (KmsRenderingTest) {
|
test = (KmsRenderingTest) {
|
||||||
.number_of_frames_left = 10,
|
.number_of_frames_left = N_FRAMES_PER_TEST,
|
||||||
.loop = g_main_loop_new (NULL, FALSE),
|
.loop = g_main_loop_new (NULL, FALSE),
|
||||||
};
|
};
|
||||||
handler_id = g_signal_connect (stage, "after-update",
|
handler_id = g_signal_connect (stage, "after-update",
|
||||||
|
@ -123,7 +128,6 @@ on_scanout_before_update (ClutterStage *stage,
|
||||||
KmsRenderingTest *test)
|
KmsRenderingTest *test)
|
||||||
{
|
{
|
||||||
test->scanout.n_paints = 0;
|
test->scanout.n_paints = 0;
|
||||||
test->scanout.fb_id = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -135,6 +139,7 @@ on_scanout_before_paint (ClutterStage *stage,
|
||||||
CoglScanout *scanout;
|
CoglScanout *scanout;
|
||||||
CoglScanoutBuffer *scanout_buffer;
|
CoglScanoutBuffer *scanout_buffer;
|
||||||
MetaDrmBuffer *buffer;
|
MetaDrmBuffer *buffer;
|
||||||
|
uint32_t fb_id;
|
||||||
|
|
||||||
scanout = clutter_stage_view_peek_scanout (stage_view);
|
scanout = clutter_stage_view_peek_scanout (stage_view);
|
||||||
if (!scanout)
|
if (!scanout)
|
||||||
|
@ -143,8 +148,13 @@ on_scanout_before_paint (ClutterStage *stage,
|
||||||
scanout_buffer = cogl_scanout_get_buffer (scanout);
|
scanout_buffer = cogl_scanout_get_buffer (scanout);
|
||||||
g_assert_true (META_IS_DRM_BUFFER (scanout_buffer));
|
g_assert_true (META_IS_DRM_BUFFER (scanout_buffer));
|
||||||
buffer = META_DRM_BUFFER (scanout_buffer);
|
buffer = META_DRM_BUFFER (scanout_buffer);
|
||||||
test->scanout.fb_id = meta_drm_buffer_get_fb_id (buffer);
|
fb_id = meta_drm_buffer_get_fb_id (buffer);
|
||||||
g_assert_cmpuint (test->scanout.fb_id, >, 0);
|
g_assert_cmpuint (fb_id, >, 0);
|
||||||
|
test->scanout.fb_ids = g_list_append (test->scanout.fb_ids,
|
||||||
|
GUINT_TO_POINTER (fb_id));
|
||||||
|
|
||||||
|
/* Triple buffering, but no higher */
|
||||||
|
g_assert_cmpuint (g_list_length (test->scanout.fb_ids), <=, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -173,12 +183,12 @@ on_scanout_presented (ClutterStage *stage,
|
||||||
MetaDeviceFile *device_file;
|
MetaDeviceFile *device_file;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
drmModeCrtc *drm_crtc;
|
drmModeCrtc *drm_crtc;
|
||||||
|
uint32_t first_fb_id_expected;
|
||||||
|
|
||||||
if (test->wait_for_scanout && test->scanout.n_paints > 0)
|
if (test->wait_for_scanout && test->scanout.fb_ids == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (test->wait_for_scanout && test->scanout.fb_id == 0)
|
test->scanout.n_presentations++;
|
||||||
return;
|
|
||||||
|
|
||||||
device_pool = meta_backend_native_get_device_pool (backend_native);
|
device_pool = meta_backend_native_get_device_pool (backend_native);
|
||||||
|
|
||||||
|
@ -197,15 +207,41 @@ on_scanout_presented (ClutterStage *stage,
|
||||||
drm_crtc = drmModeGetCrtc (meta_device_file_get_fd (device_file),
|
drm_crtc = drmModeGetCrtc (meta_device_file_get_fd (device_file),
|
||||||
meta_kms_crtc_get_id (kms_crtc));
|
meta_kms_crtc_get_id (kms_crtc));
|
||||||
g_assert_nonnull (drm_crtc);
|
g_assert_nonnull (drm_crtc);
|
||||||
if (test->scanout.fb_id == 0)
|
|
||||||
g_assert_cmpuint (drm_crtc->buffer_id, !=, test->scanout.fb_id);
|
if (test->scanout.fb_ids)
|
||||||
|
{
|
||||||
|
test->scanout.n_direct_scanouts++;
|
||||||
|
first_fb_id_expected = GPOINTER_TO_UINT (test->scanout.fb_ids->data);
|
||||||
|
test->scanout.fb_ids = g_list_delete_link (test->scanout.fb_ids,
|
||||||
|
test->scanout.fb_ids);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
g_assert_cmpuint (drm_crtc->buffer_id, ==, test->scanout.fb_id);
|
{
|
||||||
|
first_fb_id_expected = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The buffer ID won't match on the first frame because switching from
|
||||||
|
* triple buffered compositing to double buffered direct scanout takes
|
||||||
|
* an extra frame to drain the queue. Thereafter we are in direct scanout
|
||||||
|
* mode and expect the buffer IDs to match.
|
||||||
|
*/
|
||||||
|
if (test->scanout.n_presentations > 1)
|
||||||
|
{
|
||||||
|
if (first_fb_id_expected == 0)
|
||||||
|
g_assert_cmpuint (drm_crtc->buffer_id, !=, first_fb_id_expected);
|
||||||
|
else
|
||||||
|
g_assert_cmpuint (drm_crtc->buffer_id, ==, first_fb_id_expected);
|
||||||
|
}
|
||||||
|
|
||||||
drmModeFreeCrtc (drm_crtc);
|
drmModeFreeCrtc (drm_crtc);
|
||||||
|
|
||||||
meta_device_file_release (device_file);
|
meta_device_file_release (device_file);
|
||||||
|
|
||||||
|
test->number_of_frames_left--;
|
||||||
|
if (test->number_of_frames_left <= 0)
|
||||||
g_main_loop_quit (test->loop);
|
g_main_loop_quit (test->loop);
|
||||||
|
else
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -244,7 +280,9 @@ meta_test_kms_render_client_scanout (void)
|
||||||
g_assert_nonnull (wayland_test_client);
|
g_assert_nonnull (wayland_test_client);
|
||||||
|
|
||||||
test = (KmsRenderingTest) {
|
test = (KmsRenderingTest) {
|
||||||
|
.number_of_frames_left = N_FRAMES_PER_TEST,
|
||||||
.loop = g_main_loop_new (NULL, FALSE),
|
.loop = g_main_loop_new (NULL, FALSE),
|
||||||
|
.scanout = {0},
|
||||||
.wait_for_scanout = TRUE,
|
.wait_for_scanout = TRUE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -270,7 +308,8 @@ meta_test_kms_render_client_scanout (void)
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
g_main_loop_run (test.loop);
|
g_main_loop_run (test.loop);
|
||||||
|
|
||||||
g_assert_cmpuint (test.scanout.fb_id, >, 0);
|
g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST);
|
||||||
|
g_assert_cmpint (test.scanout.n_direct_scanouts, ==, N_FRAMES_PER_TEST);
|
||||||
|
|
||||||
g_debug ("Unmake fullscreen");
|
g_debug ("Unmake fullscreen");
|
||||||
window = meta_find_window_from_title (test_context, "dma-buf-scanout-test");
|
window = meta_find_window_from_title (test_context, "dma-buf-scanout-test");
|
||||||
|
@ -292,10 +331,15 @@ meta_test_kms_render_client_scanout (void)
|
||||||
g_assert_cmpint (buffer_rect.y, ==, 10);
|
g_assert_cmpint (buffer_rect.y, ==, 10);
|
||||||
|
|
||||||
test.wait_for_scanout = FALSE;
|
test.wait_for_scanout = FALSE;
|
||||||
|
test.number_of_frames_left = N_FRAMES_PER_TEST;
|
||||||
|
test.scanout.n_presentations = 0;
|
||||||
|
test.scanout.n_direct_scanouts = 0;
|
||||||
|
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
g_main_loop_run (test.loop);
|
g_main_loop_run (test.loop);
|
||||||
|
|
||||||
g_assert_cmpuint (test.scanout.fb_id, ==, 0);
|
g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST);
|
||||||
|
g_assert_cmpint (test.scanout.n_direct_scanouts, ==, 0);
|
||||||
|
|
||||||
g_debug ("Moving back to 0, 0");
|
g_debug ("Moving back to 0, 0");
|
||||||
meta_window_move_frame (window, TRUE, 0, 0);
|
meta_window_move_frame (window, TRUE, 0, 0);
|
||||||
|
@ -307,10 +351,15 @@ meta_test_kms_render_client_scanout (void)
|
||||||
g_assert_cmpint (buffer_rect.y, ==, 0);
|
g_assert_cmpint (buffer_rect.y, ==, 0);
|
||||||
|
|
||||||
test.wait_for_scanout = TRUE;
|
test.wait_for_scanout = TRUE;
|
||||||
|
test.number_of_frames_left = N_FRAMES_PER_TEST;
|
||||||
|
test.scanout.n_presentations = 0;
|
||||||
|
test.scanout.n_direct_scanouts = 0;
|
||||||
|
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
g_main_loop_run (test.loop);
|
g_main_loop_run (test.loop);
|
||||||
|
|
||||||
g_assert_cmpuint (test.scanout.fb_id, >, 0);
|
g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST);
|
||||||
|
g_assert_cmpint (test.scanout.n_direct_scanouts, ==, N_FRAMES_PER_TEST);
|
||||||
|
|
||||||
g_signal_handler_disconnect (stage, before_update_handler_id);
|
g_signal_handler_disconnect (stage, before_update_handler_id);
|
||||||
g_signal_handler_disconnect (stage, before_paint_handler_id);
|
g_signal_handler_disconnect (stage, before_paint_handler_id);
|
||||||
|
@ -364,6 +413,15 @@ on_scanout_fallback_before_paint (ClutterStage *stage,
|
||||||
if (!scanout)
|
if (!scanout)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
test->scanout_fallback.scanouts_attempted++;
|
||||||
|
|
||||||
|
/* The first scanout candidate frame will get composited due to triple
|
||||||
|
* buffering draining the queue to drop to double buffering. So don't
|
||||||
|
* sabotage that first frame.
|
||||||
|
*/
|
||||||
|
if (test->scanout_fallback.scanouts_attempted < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
g_assert_false (test->scanout_fallback.scanout_sabotaged);
|
g_assert_false (test->scanout_fallback.scanout_sabotaged);
|
||||||
|
|
||||||
if (is_atomic_mode_setting (kms_device))
|
if (is_atomic_mode_setting (kms_device))
|
||||||
|
@ -401,6 +459,15 @@ on_scanout_fallback_paint_view (ClutterStage *stage,
|
||||||
g_clear_handle_id (&test->scanout_fallback.repaint_guard_id,
|
g_clear_handle_id (&test->scanout_fallback.repaint_guard_id,
|
||||||
g_source_remove);
|
g_source_remove);
|
||||||
test->scanout_fallback.fallback_painted = TRUE;
|
test->scanout_fallback.fallback_painted = TRUE;
|
||||||
|
test->scanout_fallback.scanout_sabotaged = FALSE;
|
||||||
|
}
|
||||||
|
else if (test->scanout_fallback.scanouts_attempted == 1)
|
||||||
|
{
|
||||||
|
/* Now that we've seen the first scanout attempt that was inhibited by
|
||||||
|
* triple buffering, try a second frame. The second one should scanout
|
||||||
|
* and will be sabotaged.
|
||||||
|
*/
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,11 +477,11 @@ on_scanout_fallback_presented (ClutterStage *stage,
|
||||||
ClutterFrameInfo *frame_info,
|
ClutterFrameInfo *frame_info,
|
||||||
KmsRenderingTest *test)
|
KmsRenderingTest *test)
|
||||||
{
|
{
|
||||||
if (!test->scanout_fallback.scanout_sabotaged)
|
if (test->scanout_fallback.fallback_painted)
|
||||||
return;
|
|
||||||
|
|
||||||
g_assert_true (test->scanout_fallback.fallback_painted);
|
|
||||||
g_main_loop_quit (test->loop);
|
g_main_loop_quit (test->loop);
|
||||||
|
|
||||||
|
test->number_of_frames_left--;
|
||||||
|
g_assert_cmpint (test->number_of_frames_left, >, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -443,6 +510,7 @@ meta_test_kms_render_client_scanout_fallback (void)
|
||||||
g_assert_nonnull (wayland_test_client);
|
g_assert_nonnull (wayland_test_client);
|
||||||
|
|
||||||
test = (KmsRenderingTest) {
|
test = (KmsRenderingTest) {
|
||||||
|
.number_of_frames_left = N_FRAMES_PER_TEST,
|
||||||
.loop = g_main_loop_new (NULL, FALSE),
|
.loop = g_main_loop_new (NULL, FALSE),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue