onscreen/native: Allow requesting frame synchronization

Frame synchronization is enabled for a view as long as it's
applicable to be enabled. It is considered applicable if it's both
requested for the onscreen and if the onscreen uses a CRTC which is
configured with a variable refresh rate mode.

When frame synchronization is enabled, it enables both the the variable
scheduling mode of ClutterFrameClock and the variable refresh rate
property for the CRTC.

Changes in the frame synchronization mode are applied asynchronously,
before the next frame is drawn.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1154>
This commit is contained in:
Dor Askayo 2020-07-04 22:13:55 +03:00 committed by Marge Bot
parent 732f5afe13
commit fee3329997
2 changed files with 115 additions and 0 deletions

View File

@ -83,6 +83,13 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
MetaSharedFramebufferImportStatus import_status; MetaSharedFramebufferImportStatus import_status;
} MetaOnscreenNativeSecondaryGpuState; } MetaOnscreenNativeSecondaryGpuState;
typedef enum _MetaFrameSyncMode
{
META_FRAME_SYNC_MODE_INIT,
META_FRAME_SYNC_MODE_ENABLED,
META_FRAME_SYNC_MODE_DISABLED,
} MetaFrameSyncMode;
struct _MetaOnscreenNative struct _MetaOnscreenNative
{ {
CoglOnscreenEgl parent; CoglOnscreenEgl parent;
@ -110,6 +117,9 @@ struct _MetaOnscreenNative
} egl; } egl;
#endif #endif
MetaFrameSyncMode requested_frame_sync_mode;
MetaFrameSyncMode frame_sync_mode;
MetaRendererView *view; MetaRendererView *view;
gboolean is_gamma_lut_invalid; gboolean is_gamma_lut_invalid;
@ -1666,6 +1676,103 @@ add_onscreen_frame_info (MetaCrtc *crtc)
CLUTTER_STAGE_VIEW (view)); CLUTTER_STAGE_VIEW (view));
} }
void
meta_onscreen_native_request_frame_sync (MetaOnscreenNative *onscreen_native,
gboolean enabled)
{
onscreen_native->requested_frame_sync_mode =
enabled
? META_FRAME_SYNC_MODE_ENABLED
: META_FRAME_SYNC_MODE_DISABLED;
}
gboolean
meta_onscreen_native_is_frame_sync_enabled (MetaOnscreenNative *onscreen_native)
{
return onscreen_native->frame_sync_mode == META_FRAME_SYNC_MODE_ENABLED;
}
static void
update_frame_sync_mode (MetaOnscreenNative *onscreen_native,
ClutterFrame *frame,
MetaFrameSyncMode sync_mode)
{
MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
MetaFrameNative *frame_native;
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
MetaKmsUpdate *kms_update;
ClutterFrameClock *frame_clock;
frame_native = meta_frame_native_from_frame (frame);
frame_clock =
clutter_stage_view_get_frame_clock (CLUTTER_STAGE_VIEW (onscreen_native->view));
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
kms_device = meta_kms_crtc_get_device (kms_crtc);
kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device);
switch (sync_mode)
{
case META_FRAME_SYNC_MODE_ENABLED:
clutter_frame_clock_set_mode (frame_clock,
CLUTTER_FRAME_CLOCK_MODE_VARIABLE);
meta_kms_update_set_vrr (kms_update,
kms_crtc,
TRUE);
break;
case META_FRAME_SYNC_MODE_DISABLED:
clutter_frame_clock_set_mode (frame_clock,
CLUTTER_FRAME_CLOCK_MODE_FIXED);
meta_kms_update_set_vrr (kms_update,
kms_crtc,
FALSE);
break;
case META_FRAME_SYNC_MODE_INIT:
g_assert_not_reached ();
}
onscreen_native->frame_sync_mode = sync_mode;
}
static MetaFrameSyncMode
get_applicable_sync_mode (MetaOnscreenNative *onscreen_native)
{
const MetaCrtcConfig *crtc_config;
const MetaCrtcModeInfo *crtc_mode_info;
crtc_config = meta_crtc_get_config (onscreen_native->crtc);
g_assert (crtc_config != NULL);
g_assert (crtc_config->mode != NULL);
crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode);
g_assert (crtc_mode_info != NULL);
if (crtc_mode_info->refresh_rate_mode ==
META_CRTC_REFRESH_RATE_MODE_FIXED)
return META_FRAME_SYNC_MODE_DISABLED;
return onscreen_native->requested_frame_sync_mode;
}
static void
maybe_update_frame_sync_mode (MetaOnscreenNative *onscreen_native,
ClutterFrame *frame)
{
MetaFrameSyncMode applicable_sync_mode;
applicable_sync_mode = get_applicable_sync_mode (onscreen_native);
if (G_LIKELY (applicable_sync_mode == onscreen_native->frame_sync_mode))
return;
update_frame_sync_mode (onscreen_native,
frame,
applicable_sync_mode);
}
void void
meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, meta_onscreen_native_before_redraw (CoglOnscreen *onscreen,
ClutterFrame *frame) ClutterFrame *frame)
@ -1676,6 +1783,7 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen,
meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc), meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc),
kms_crtc); kms_crtc);
maybe_update_frame_sync_mode (onscreen_native, frame);
} }
void void
@ -2774,6 +2882,8 @@ meta_onscreen_native_dispose (GObject *object)
static void static void
meta_onscreen_native_init (MetaOnscreenNative *onscreen_native) meta_onscreen_native_init (MetaOnscreenNative *onscreen_native)
{ {
onscreen_native->requested_frame_sync_mode = META_FRAME_SYNC_MODE_DISABLED;
onscreen_native->frame_sync_mode = META_FRAME_SYNC_MODE_INIT;
} }
static void static void

View File

@ -65,3 +65,8 @@ MetaCrtc * meta_onscreen_native_get_crtc (MetaOnscreenNative *onscreen_native);
void meta_onscreen_native_invalidate (MetaOnscreenNative *onscreen_native); void meta_onscreen_native_invalidate (MetaOnscreenNative *onscreen_native);
void meta_onscreen_native_detach (MetaOnscreenNative *onscreen_native); void meta_onscreen_native_detach (MetaOnscreenNative *onscreen_native);
void meta_onscreen_native_request_frame_sync (MetaOnscreenNative *onscreen_native,
gboolean enabled);
gboolean meta_onscreen_native_is_frame_sync_enabled (MetaOnscreenNative *onscreen_native);