cogl: Make presentation time always MONOTONIC

This concerns only the cases when the presentation timestamp is received
directly from the device (from KMS or from GLX). In the majority of
cases this timestamp is already MONOTONIC. When it isn't, after this
commit, the current value of the MONOTONIC clock is sampled instead.

The alternative is to store the clock id alongside the timestamp, with
possible values of MONOTONIC, REALTIME (from KMS) and GETTIMEOFDAY (from
GLX; this might be the same as REALTIME, I'm not sure), and then
"convert" the timestamp to MONOTONIC when needed. An example of such a
conversion was done in compositor.c (removed in this commit). It would
also be needed for the presentation-time Wayland protocol. However, it
seems that the vast majority of up-to-date systems are using MONOTONIC
anyway, making this effort not justified.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1484>
This commit is contained in:
Ivan Molodetskikh
2021-01-30 23:14:55 +03:00
committed by Marge Bot
parent d8606829c4
commit 4810164885
8 changed files with 72 additions and 57 deletions

View File

@@ -47,7 +47,7 @@ struct _CoglFrameInfo
CoglObject _parent;
int64_t frame_counter;
int64_t presentation_time_us;
int64_t presentation_time_us; /* CLOCK_MONOTONIC */
float refresh_rate;
int64_t global_frame_counter;

View File

@@ -97,11 +97,9 @@ int64_t cogl_frame_info_get_frame_counter (CoglFrameInfo *info);
* the frame became visible to the user.
*
* The presentation time measured in microseconds, is based on
* cogl_get_clock_time().
* CLOCK_MONOTONIC.
*
* <note>Linux kernel version less that 3.8 can result in
* non-monotonic timestamps being reported when using a drm based
* OpenGL driver. Also some buggy Mesa drivers up to 9.0.1 may also
* <note>Some buggy Mesa drivers up to 9.0.1 may
* incorrectly report non-monotonic timestamps.</note>
*
* Return value: the presentation time for the frame

View File

@@ -454,6 +454,17 @@ ust_to_microseconds (CoglRenderer *renderer,
return 0;
}
static gboolean
is_ust_monotonic (CoglRenderer *renderer,
GLXDrawable drawable)
{
CoglGLXRenderer *glx_renderer = renderer->winsys;
ensure_ust_type (renderer, drawable);
return (glx_renderer->ust_type == COGL_GLX_UST_IS_MONOTONIC_TIME);
}
static void
_cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen)
{
@@ -482,10 +493,19 @@ _cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen)
glx_renderer->glXWaitForMsc (xlib_renderer->xdpy, drawable,
0, 1, 0,
&ust, &msc, &sbc);
info->presentation_time_us = ust_to_microseconds (ctx->display->renderer,
drawable,
ust);
info->flags |= COGL_FRAME_INFO_FLAG_HW_CLOCK;
if (is_ust_monotonic (ctx->display->renderer, drawable))
{
info->presentation_time_us =
ust_to_microseconds (ctx->display->renderer,
drawable,
ust);
info->flags |= COGL_FRAME_INFO_FLAG_HW_CLOCK;
}
else
{
info->presentation_time_us = g_get_monotonic_time ();
}
}
else
{
@@ -962,16 +982,20 @@ cogl_onscreen_glx_notify_swap_buffers (CoglOnscreen *onscreen,
GLXBufferSwapComplete *swap_event)
{
CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *context = cogl_framebuffer_get_context (framebuffer);
gboolean ust_is_monotonic;
/* We only want to notify that the swap is complete when the
application calls cogl_context_dispatch so instead of immediately
notifying we'll set a flag to remember to notify later */
set_sync_pending (onscreen);
if (swap_event->ust != 0)
ust_is_monotonic = is_ust_monotonic (context->display->renderer,
onscreen_glx->glxwin);
if (swap_event->ust != 0 && ust_is_monotonic)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *context = cogl_framebuffer_get_context (framebuffer);
CoglFrameInfo *info;
info = cogl_onscreen_peek_head_frame_info (onscreen);