summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Gilg <subdiff@gmail.com>2018-03-13 16:00:54 +0100
committerAdam Jackson <ajax@redhat.com>2018-03-28 14:36:55 -0400
commit86df366973de1c10da5fbdc57d1ff12b681c321f (patch)
tree47fd7e780bda847407af73cf00e0a78680bed349
parent0fb2cca193e60b731c8e75a2a7e795477fb5fd8f (diff)
xwayland: Add fallback timer for msc counting
When the compositor is not sending frame callbacks while we still wait on buffer release events fake a continuous msc counter with a timer. Having this timer is a prerequisite for queuing events. Signed-off-by: Roman Gilg <subdiff@gmail.com> Reviewed-by: Adam Jackson <ajax@redhat.com>
-rw-r--r--hw/xwayland/xwayland-present.c70
-rw-r--r--hw/xwayland/xwayland.h3
2 files changed, 73 insertions, 0 deletions
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index f41e864b3..a8cc02449 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -27,6 +27,34 @@
#include <present.h>
+#define TIMER_LEN_FLIP 1000 // 1fps
+
+static void
+xwl_present_free_timer(struct xwl_window *xwl_window)
+{
+ TimerFree(xwl_window->present_timer);
+ xwl_window->present_timer = NULL;
+}
+
+static CARD32
+xwl_present_timer_callback(OsTimerPtr timer,
+ CARD32 time,
+ void *arg);
+
+static void
+xwl_present_reset_timer(struct xwl_window *xwl_window)
+{
+ if ( !xorg_list_is_empty(&xwl_window->present_release_queue) ) {
+ xwl_window->present_timer = TimerSet(xwl_window->present_timer,
+ 0,
+ TIMER_LEN_FLIP,
+ &xwl_present_timer_callback,
+ xwl_window);
+ } else {
+ xwl_present_free_timer(xwl_window);
+ }
+}
+
void
xwl_present_cleanup(WindowPtr window)
{
@@ -51,6 +79,10 @@ xwl_present_cleanup(WindowPtr window)
event->abort = TRUE;
}
}
+
+ /* Clear timer */
+ if ( xorg_list_is_empty(&xwl_window->present_release_queue) )
+ xwl_present_free_timer(xwl_window);
}
static void
@@ -90,6 +122,27 @@ static const struct wl_buffer_listener xwl_present_release_listener = {
xwl_present_buffer_release
};
+CARD32
+xwl_present_timer_callback(OsTimerPtr timer,
+ CARD32 time,
+ void *arg)
+{
+ struct xwl_window *xwl_window = arg;
+
+ xwl_window->present_timer_firing = TRUE;
+ xwl_window->present_msc++;
+ xwl_window->present_ust = GetTimeInMicros();
+
+ if ( !xorg_list_is_empty(&xwl_window->present_release_queue) ) {
+ /* Still events, restart timer */
+ return TIMER_LEN_FLIP;
+ } else {
+ /* No more events, do not restart timer and delete it instead */
+ xwl_present_free_timer(xwl_window);
+ return 0;
+ }
+}
+
static void
xwl_present_frame_callback(void *data,
struct wl_callback *callback,
@@ -100,8 +153,18 @@ xwl_present_frame_callback(void *data,
wl_callback_destroy(xwl_window->present_frame_callback);
xwl_window->present_frame_callback = NULL;
+ if (xwl_window->present_timer_firing) {
+ /* If the timer is firing, this frame callback is too late */
+ return;
+ }
+
xwl_window->present_msc++;
xwl_window->present_ust = GetTimeInMicros();
+
+ /* we do not need the timer anymore for this frame,
+ * reset it for potentially the next one
+ */
+ xwl_present_reset_timer(xwl_window);
}
static const struct wl_callback_listener xwl_present_frame_listener = {
@@ -308,6 +371,13 @@ xwl_present_flip(WindowPtr present_window,
/* We can flip directly to the main surface (full screen window without clips) */
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
+ if (!xwl_window->present_timer ||
+ xwl_window->present_timer_firing) {
+ /* Realign timer */
+ xwl_window->present_timer_firing = FALSE;
+ xwl_present_reset_timer(xwl_window);
+ }
+
if (!xwl_window->present_frame_callback) {
xwl_window->present_frame_callback = wl_surface_frame(xwl_window->surface);
wl_callback_add_listener(xwl_window->present_frame_callback,
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index dd7d1c685..e6cec18b8 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -135,6 +135,9 @@ struct xwl_window {
uint64_t present_msc;
uint64_t present_ust;
+ OsTimerPtr present_timer;
+ Bool present_timer_firing;
+
struct wl_callback *present_frame_callback;
struct wl_callback *present_sync_callback;
struct xorg_list present_release_queue;