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:

committed by
Marge Bot

parent
d8606829c4
commit
4810164885
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user