mirror of
https://github.com/brl/mutter.git
synced 2025-03-28 22:23:47 +00:00
210 lines
6.4 KiB
C
210 lines
6.4 KiB
C
#include "clutter/clutter.h"
|
|
#include "tests/clutter-test-utils.h"
|
|
|
|
static const float refresh_rate = 60.0;
|
|
|
|
static ClutterFrameResult
|
|
timeline_frame_clock_frame (ClutterFrameClock *frame_clock,
|
|
int64_t frame_count,
|
|
int64_t time_us,
|
|
gpointer user_data)
|
|
{
|
|
ClutterFrameInfo frame_info;
|
|
|
|
frame_info = (ClutterFrameInfo) {
|
|
.presentation_time = g_get_monotonic_time (),
|
|
.refresh_rate = refresh_rate,
|
|
.flags = CLUTTER_FRAME_INFO_FLAG_NONE,
|
|
.sequence = 0,
|
|
};
|
|
clutter_frame_clock_notify_presented (frame_clock, &frame_info);
|
|
clutter_frame_clock_schedule_update (frame_clock);
|
|
|
|
return CLUTTER_FRAME_RESULT_PENDING_PRESENTED;
|
|
}
|
|
|
|
static const ClutterFrameListenerIface timeline_frame_listener_iface = {
|
|
.frame = timeline_frame_clock_frame,
|
|
};
|
|
|
|
static void
|
|
on_marker_reached (ClutterTimeline *timeline,
|
|
const char *marker_name,
|
|
unsigned int frame_number,
|
|
gboolean *marker_reached)
|
|
{
|
|
*marker_reached = TRUE;
|
|
}
|
|
|
|
static void
|
|
on_timeline_new_frame (ClutterTimeline *timeline,
|
|
int time_ms,
|
|
int *frame_counter)
|
|
{
|
|
(*frame_counter)++;
|
|
}
|
|
|
|
static void
|
|
on_timeline_completed (ClutterTimeline *timeline,
|
|
GMainLoop *main_loop)
|
|
{
|
|
g_main_loop_quit (main_loop);
|
|
}
|
|
|
|
static void
|
|
frame_clock_timeline_basic (void)
|
|
{
|
|
GMainLoop *main_loop;
|
|
ClutterFrameClock *frame_clock;
|
|
ClutterTimeline *timeline;
|
|
gboolean marker1_reached;
|
|
int frame_counter;
|
|
int64_t before_us;
|
|
int64_t after_us;
|
|
|
|
main_loop = g_main_loop_new (NULL, FALSE);
|
|
frame_clock = clutter_frame_clock_new (refresh_rate,
|
|
0,
|
|
&timeline_frame_listener_iface,
|
|
NULL);
|
|
g_object_add_weak_pointer (G_OBJECT (frame_clock), (gpointer *) &frame_clock);
|
|
|
|
timeline = g_object_new (CLUTTER_TYPE_TIMELINE,
|
|
"duration", 1000,
|
|
"frame-clock", frame_clock,
|
|
NULL);
|
|
g_object_add_weak_pointer (G_OBJECT (timeline), (gpointer *) &timeline);
|
|
|
|
clutter_timeline_add_marker_at_time (timeline, "marker1", 500);
|
|
|
|
marker1_reached = FALSE;
|
|
frame_counter = 0;
|
|
|
|
g_signal_connect (timeline, "marker-reached::marker1",
|
|
G_CALLBACK (on_marker_reached),
|
|
&marker1_reached);
|
|
g_signal_connect (timeline, "new-frame",
|
|
G_CALLBACK (on_timeline_new_frame),
|
|
&frame_counter);
|
|
g_signal_connect (timeline, "completed",
|
|
G_CALLBACK (on_timeline_completed),
|
|
main_loop);
|
|
|
|
clutter_timeline_start (timeline);
|
|
|
|
before_us = g_get_monotonic_time ();
|
|
|
|
g_main_loop_run (main_loop);
|
|
|
|
after_us = g_get_monotonic_time ();
|
|
|
|
g_assert_cmpint (after_us - before_us,
|
|
>=,
|
|
ms2us (clutter_timeline_get_duration (timeline)));
|
|
|
|
g_assert_true (marker1_reached);
|
|
|
|
/* Just check that we got at least a few frames. Require too high and we'll be
|
|
* flaky.
|
|
*/
|
|
g_assert_cmpint (frame_counter, >, 20);
|
|
|
|
g_main_loop_unref (main_loop);
|
|
g_object_unref (timeline);
|
|
g_assert_null (timeline);
|
|
clutter_frame_clock_destroy (frame_clock);
|
|
g_assert_null (frame_clock);
|
|
}
|
|
|
|
static void
|
|
on_switch_reached (ClutterTimeline *timeline,
|
|
const char *marker_name,
|
|
unsigned int frame_number,
|
|
ClutterFrameClock *new_frame_clock)
|
|
{
|
|
ClutterFrameClock *old_frame_clock;
|
|
|
|
old_frame_clock = clutter_timeline_get_frame_clock (timeline);
|
|
clutter_frame_clock_inhibit (old_frame_clock);
|
|
|
|
clutter_timeline_set_frame_clock (timeline, new_frame_clock);
|
|
}
|
|
|
|
static void
|
|
frame_clock_timeline_switch (void)
|
|
{
|
|
GMainLoop *main_loop;
|
|
ClutterFrameClock *frame_clock2;
|
|
ClutterFrameClock *frame_clock1;
|
|
ClutterTimeline *timeline;
|
|
int frame_counter;
|
|
int64_t before_us;
|
|
int64_t after_us;
|
|
|
|
main_loop = g_main_loop_new (NULL, FALSE);
|
|
|
|
frame_clock1 = clutter_frame_clock_new (refresh_rate,
|
|
0,
|
|
&timeline_frame_listener_iface,
|
|
NULL);
|
|
g_object_add_weak_pointer (G_OBJECT (frame_clock1), (gpointer *) &frame_clock1);
|
|
frame_clock2 = clutter_frame_clock_new (refresh_rate,
|
|
0,
|
|
&timeline_frame_listener_iface,
|
|
NULL);
|
|
g_object_add_weak_pointer (G_OBJECT (frame_clock2), (gpointer *) &frame_clock2);
|
|
|
|
timeline = g_object_new (CLUTTER_TYPE_TIMELINE,
|
|
"duration", 1000,
|
|
"frame-clock", frame_clock1,
|
|
NULL);
|
|
g_object_add_weak_pointer (G_OBJECT (timeline), (gpointer *) &timeline);
|
|
|
|
clutter_timeline_add_marker_at_time (timeline, "switch", 500);
|
|
|
|
frame_counter = 0;
|
|
|
|
g_signal_connect (timeline, "marker-reached::switch",
|
|
G_CALLBACK (on_switch_reached),
|
|
frame_clock2);
|
|
g_signal_connect (timeline, "new-frame",
|
|
G_CALLBACK (on_timeline_new_frame),
|
|
&frame_counter);
|
|
g_signal_connect (timeline, "completed",
|
|
G_CALLBACK (on_timeline_completed),
|
|
main_loop);
|
|
|
|
clutter_timeline_start (timeline);
|
|
|
|
before_us = g_get_monotonic_time ();
|
|
|
|
g_main_loop_run (main_loop);
|
|
|
|
after_us = g_get_monotonic_time ();
|
|
|
|
g_assert_cmpint (after_us - before_us,
|
|
>=,
|
|
ms2us (clutter_timeline_get_duration (timeline)));
|
|
|
|
g_assert (clutter_timeline_get_frame_clock (timeline) == frame_clock2);
|
|
|
|
/* The duration is 1s, with a 60hz clock, and we switch after 0.5s. To verify
|
|
* we continued to get frames, check that we have a bit more than half of the
|
|
* frames accounted for.
|
|
*/
|
|
g_assert_cmpint (frame_counter, >, 35);
|
|
|
|
g_main_loop_unref (main_loop);
|
|
g_object_unref (timeline);
|
|
g_assert_null (timeline);
|
|
clutter_frame_clock_destroy (frame_clock1);
|
|
g_assert_null (frame_clock1);
|
|
clutter_frame_clock_destroy (frame_clock2);
|
|
g_assert_null (frame_clock2);
|
|
}
|
|
|
|
CLUTTER_TEST_SUITE (
|
|
CLUTTER_TEST_UNIT ("/frame-clock/timeline/basic", frame_clock_timeline_basic)
|
|
CLUTTER_TEST_UNIT ("/frame-clock/timeline/switch", frame_clock_timeline_switch)
|
|
)
|