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>
This commit is contained in:
parent
0fb2cca193
commit
86df366973
|
@ -27,6 +27,34 @@
|
||||||
|
|
||||||
#include <present.h>
|
#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
|
void
|
||||||
xwl_present_cleanup(WindowPtr window)
|
xwl_present_cleanup(WindowPtr window)
|
||||||
{
|
{
|
||||||
|
@ -51,6 +79,10 @@ xwl_present_cleanup(WindowPtr window)
|
||||||
event->abort = TRUE;
|
event->abort = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear timer */
|
||||||
|
if ( xorg_list_is_empty(&xwl_window->present_release_queue) )
|
||||||
|
xwl_present_free_timer(xwl_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -90,6 +122,27 @@ static const struct wl_buffer_listener xwl_present_release_listener = {
|
||||||
xwl_present_buffer_release
|
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
|
static void
|
||||||
xwl_present_frame_callback(void *data,
|
xwl_present_frame_callback(void *data,
|
||||||
struct wl_callback *callback,
|
struct wl_callback *callback,
|
||||||
|
@ -100,8 +153,18 @@ xwl_present_frame_callback(void *data,
|
||||||
wl_callback_destroy(xwl_window->present_frame_callback);
|
wl_callback_destroy(xwl_window->present_frame_callback);
|
||||||
xwl_window->present_frame_callback = NULL;
|
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_msc++;
|
||||||
xwl_window->present_ust = GetTimeInMicros();
|
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 = {
|
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) */
|
/* We can flip directly to the main surface (full screen window without clips) */
|
||||||
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
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) {
|
if (!xwl_window->present_frame_callback) {
|
||||||
xwl_window->present_frame_callback = wl_surface_frame(xwl_window->surface);
|
xwl_window->present_frame_callback = wl_surface_frame(xwl_window->surface);
|
||||||
wl_callback_add_listener(xwl_window->present_frame_callback,
|
wl_callback_add_listener(xwl_window->present_frame_callback,
|
||||||
|
|
|
@ -135,6 +135,9 @@ struct xwl_window {
|
||||||
uint64_t present_msc;
|
uint64_t present_msc;
|
||||||
uint64_t present_ust;
|
uint64_t present_ust;
|
||||||
|
|
||||||
|
OsTimerPtr present_timer;
|
||||||
|
Bool present_timer_firing;
|
||||||
|
|
||||||
struct wl_callback *present_frame_callback;
|
struct wl_callback *present_frame_callback;
|
||||||
struct wl_callback *present_sync_callback;
|
struct wl_callback *present_sync_callback;
|
||||||
struct xorg_list present_release_queue;
|
struct xorg_list present_release_queue;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user