backends/native: Avoid duplicating or losing KMS property sets
When triple buffering, `meta_onscreen_native_prepare_frame` for the next frame is called before `notify_view_crtc_presented` for the previous frame. So our booleans were unfortunately still TRUE in the second prepare_frame, resulting in two frames with the same property updates. When double buffering, having roughly one frame interval between `meta_onscreen_native_prepare_frame` and `notify_view_crtc_presented` meant that property updates signalled between the swap and presentation wouldn't get attached to a KMS update, and would be forgotten when `notify_view_crtc_presented` resets the flags to FALSE. To solve these we now keep a separate flag and counter per property, tracking invalidation and pending updates respectively. The latter is a counter rather than a boolean in support of triple buffering where two updates may be pending concurrently (next and posted). Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3912>
This commit is contained in:
parent
cdbe0a27a2
commit
a04d90d9e7
1 changed files with 79 additions and 37 deletions
|
@ -84,6 +84,13 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
|
||||||
MetaSharedFramebufferImportStatus import_status;
|
MetaSharedFramebufferImportStatus import_status;
|
||||||
} MetaOnscreenNativeSecondaryGpuState;
|
} MetaOnscreenNativeSecondaryGpuState;
|
||||||
|
|
||||||
|
typedef struct _KmsProperty
|
||||||
|
{
|
||||||
|
gboolean invalidated;
|
||||||
|
int64_t target_frame_counter;
|
||||||
|
gulong signal_handler_id;
|
||||||
|
} KmsProperty;
|
||||||
|
|
||||||
struct _MetaOnscreenNative
|
struct _MetaOnscreenNative
|
||||||
{
|
{
|
||||||
CoglOnscreenEgl parent;
|
CoglOnscreenEgl parent;
|
||||||
|
@ -115,15 +122,15 @@ struct _MetaOnscreenNative
|
||||||
|
|
||||||
MetaRendererView *view;
|
MetaRendererView *view;
|
||||||
|
|
||||||
gboolean is_gamma_lut_invalid;
|
union {
|
||||||
gboolean is_privacy_screen_invalid;
|
struct {
|
||||||
gboolean is_color_space_invalid;
|
KmsProperty gamma_lut;
|
||||||
gboolean is_hdr_metadata_invalid;
|
KmsProperty privacy_screen;
|
||||||
|
KmsProperty color_space;
|
||||||
gulong gamma_lut_changed_handler_id;
|
KmsProperty hdr_metadata;
|
||||||
gulong privacy_screen_changed_handler_id;
|
} property;
|
||||||
gulong color_space_changed_handler_id;
|
KmsProperty properties[4];
|
||||||
gulong hdr_metadata_changed_handler_id;
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native,
|
G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native,
|
||||||
|
@ -213,15 +220,21 @@ notify_view_crtc_presented (MetaRendererView *view,
|
||||||
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
||||||
CoglFrameInfo *frame_info;
|
CoglFrameInfo *frame_info;
|
||||||
MetaCrtc *crtc;
|
MetaCrtc *crtc;
|
||||||
|
int64_t frame_counter;
|
||||||
|
|
||||||
frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
||||||
|
|
||||||
g_return_if_fail (frame_info != NULL);
|
g_return_if_fail (frame_info != NULL);
|
||||||
|
|
||||||
onscreen_native->is_gamma_lut_invalid = FALSE;
|
frame_counter = cogl_frame_info_get_frame_counter (frame_info);
|
||||||
onscreen_native->is_privacy_screen_invalid = FALSE;
|
|
||||||
onscreen_native->is_color_space_invalid = FALSE;
|
for (int i = 0; i < G_N_ELEMENTS (onscreen_native->properties); i++)
|
||||||
onscreen_native->is_hdr_metadata_invalid = FALSE;
|
{
|
||||||
|
KmsProperty *prop = &onscreen_native->properties[i];
|
||||||
|
|
||||||
|
if (frame_counter >= prop->target_frame_counter)
|
||||||
|
prop->target_frame_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
crtc = META_CRTC (meta_crtc_kms_from_kms_crtc (kms_crtc));
|
crtc = META_CRTC (meta_crtc_kms_from_kms_crtc (kms_crtc));
|
||||||
maybe_update_frame_info (crtc, frame_info, time_us, flags, sequence);
|
maybe_update_frame_info (crtc, frame_info, time_us, flags, sequence);
|
||||||
|
@ -318,7 +331,9 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc,
|
||||||
CoglFramebuffer *framebuffer =
|
CoglFramebuffer *framebuffer =
|
||||||
clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view));
|
clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view));
|
||||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||||
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
||||||
CoglFrameInfo *frame_info;
|
CoglFrameInfo *frame_info;
|
||||||
|
int64_t frame_counter;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Page flipping failed, but we want to fail gracefully, so to avoid freezing
|
* Page flipping failed, but we want to fail gracefully, so to avoid freezing
|
||||||
|
@ -334,6 +349,20 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc,
|
||||||
frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
||||||
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
||||||
|
|
||||||
|
frame_counter = cogl_frame_info_get_frame_counter (frame_info);
|
||||||
|
|
||||||
|
for (int i = 0; i < G_N_ELEMENTS (onscreen_native->properties); i++)
|
||||||
|
{
|
||||||
|
KmsProperty *prop = &onscreen_native->properties[i];
|
||||||
|
|
||||||
|
if (prop->target_frame_counter != 0 &&
|
||||||
|
frame_counter >= prop->target_frame_counter)
|
||||||
|
{
|
||||||
|
prop->invalidated = TRUE;
|
||||||
|
prop->target_frame_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
meta_onscreen_native_notify_frame_complete (onscreen);
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
||||||
meta_onscreen_native_clear_next_fb (onscreen);
|
meta_onscreen_native_clear_next_fb (onscreen);
|
||||||
}
|
}
|
||||||
|
@ -1747,8 +1776,9 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen,
|
||||||
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
||||||
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);;
|
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);;
|
||||||
MetaFrameNative *frame_native = meta_frame_native_from_frame (frame);
|
MetaFrameNative *frame_native = meta_frame_native_from_frame (frame);
|
||||||
|
int64_t target_frame_counter = cogl_onscreen_get_frame_counter (onscreen);
|
||||||
|
|
||||||
if (onscreen_native->is_gamma_lut_invalid)
|
if (onscreen_native->property.gamma_lut.invalidated)
|
||||||
{
|
{
|
||||||
const MetaGammaLut *gamma;
|
const MetaGammaLut *gamma;
|
||||||
MetaKmsUpdate *kms_update;
|
MetaKmsUpdate *kms_update;
|
||||||
|
@ -1758,9 +1788,12 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen,
|
||||||
|
|
||||||
gamma = meta_crtc_kms_peek_gamma_lut (crtc_kms);
|
gamma = meta_crtc_kms_peek_gamma_lut (crtc_kms);
|
||||||
meta_kms_update_set_crtc_gamma (kms_update, kms_crtc, gamma);
|
meta_kms_update_set_crtc_gamma (kms_update, kms_crtc, gamma);
|
||||||
|
onscreen_native->property.gamma_lut.invalidated = FALSE;
|
||||||
|
onscreen_native->property.gamma_lut.target_frame_counter =
|
||||||
|
target_frame_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onscreen_native->is_privacy_screen_invalid)
|
if (onscreen_native->property.privacy_screen.invalidated)
|
||||||
{
|
{
|
||||||
MetaKmsConnector *kms_connector =
|
MetaKmsConnector *kms_connector =
|
||||||
meta_output_kms_get_kms_connector (output_kms);
|
meta_output_kms_get_kms_connector (output_kms);
|
||||||
|
@ -1772,9 +1805,12 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen,
|
||||||
|
|
||||||
enabled = meta_output_is_privacy_screen_enabled (onscreen_native->output);
|
enabled = meta_output_is_privacy_screen_enabled (onscreen_native->output);
|
||||||
meta_kms_update_set_privacy_screen (kms_update, kms_connector, enabled);
|
meta_kms_update_set_privacy_screen (kms_update, kms_connector, enabled);
|
||||||
|
onscreen_native->property.privacy_screen.invalidated = FALSE;
|
||||||
|
onscreen_native->property.privacy_screen.target_frame_counter =
|
||||||
|
target_frame_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onscreen_native->is_color_space_invalid)
|
if (onscreen_native->property.color_space.invalidated)
|
||||||
{
|
{
|
||||||
MetaKmsConnector *kms_connector =
|
MetaKmsConnector *kms_connector =
|
||||||
meta_output_kms_get_kms_connector (output_kms);
|
meta_output_kms_get_kms_connector (output_kms);
|
||||||
|
@ -1786,9 +1822,12 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen,
|
||||||
|
|
||||||
color_space = meta_output_peek_color_space (onscreen_native->output);
|
color_space = meta_output_peek_color_space (onscreen_native->output);
|
||||||
meta_kms_update_set_color_space (kms_update, kms_connector, color_space);
|
meta_kms_update_set_color_space (kms_update, kms_connector, color_space);
|
||||||
|
onscreen_native->property.color_space.invalidated = FALSE;
|
||||||
|
onscreen_native->property.color_space.target_frame_counter =
|
||||||
|
target_frame_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onscreen_native->is_hdr_metadata_invalid)
|
if (onscreen_native->property.hdr_metadata.invalidated)
|
||||||
{
|
{
|
||||||
MetaKmsConnector *kms_connector =
|
MetaKmsConnector *kms_connector =
|
||||||
meta_output_kms_get_kms_connector (output_kms);
|
meta_output_kms_get_kms_connector (output_kms);
|
||||||
|
@ -1800,6 +1839,9 @@ meta_onscreen_native_prepare_frame (CoglOnscreen *onscreen,
|
||||||
|
|
||||||
metadata = meta_output_peek_hdr_metadata (onscreen_native->output);
|
metadata = meta_output_peek_hdr_metadata (onscreen_native->output);
|
||||||
meta_kms_update_set_hdr_metadata (kms_update, kms_connector, metadata);
|
meta_kms_update_set_hdr_metadata (kms_update, kms_connector, metadata);
|
||||||
|
onscreen_native->property.hdr_metadata.invalidated = FALSE;
|
||||||
|
onscreen_native->property.hdr_metadata.target_frame_counter =
|
||||||
|
target_frame_counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2647,15 +2689,15 @@ meta_onscreen_native_invalidate (MetaOnscreenNative *onscreen_native)
|
||||||
meta_output_get_info (onscreen_native->output);
|
meta_output_get_info (onscreen_native->output);
|
||||||
|
|
||||||
if (meta_crtc_get_gamma_lut_size (onscreen_native->crtc) > 0)
|
if (meta_crtc_get_gamma_lut_size (onscreen_native->crtc) > 0)
|
||||||
onscreen_native->is_gamma_lut_invalid = TRUE;
|
onscreen_native->property.gamma_lut.invalidated = TRUE;
|
||||||
if (output_info->supports_privacy_screen)
|
if (output_info->supports_privacy_screen)
|
||||||
onscreen_native->is_privacy_screen_invalid = TRUE;
|
onscreen_native->property.privacy_screen.invalidated = TRUE;
|
||||||
if (output_info->supported_color_spaces &
|
if (output_info->supported_color_spaces &
|
||||||
(1 << META_OUTPUT_COLORSPACE_DEFAULT))
|
(1 << META_OUTPUT_COLORSPACE_DEFAULT))
|
||||||
onscreen_native->is_color_space_invalid = TRUE;
|
onscreen_native->property.color_space.invalidated = TRUE;
|
||||||
if (output_info->supported_hdr_eotfs &
|
if (output_info->supported_hdr_eotfs &
|
||||||
(1 << META_OUTPUT_HDR_METADATA_EOTF_TRADITIONAL_GAMMA_SDR))
|
(1 << META_OUTPUT_HDR_METADATA_EOTF_TRADITIONAL_GAMMA_SDR))
|
||||||
onscreen_native->is_hdr_metadata_invalid = TRUE;
|
onscreen_native->property.hdr_metadata.invalidated = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2664,7 +2706,7 @@ on_gamma_lut_changed (MetaCrtc *crtc,
|
||||||
{
|
{
|
||||||
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
||||||
|
|
||||||
onscreen_native->is_gamma_lut_invalid = TRUE;
|
onscreen_native->property.gamma_lut.invalidated = TRUE;
|
||||||
clutter_stage_view_schedule_update (stage_view);
|
clutter_stage_view_schedule_update (stage_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2675,7 +2717,7 @@ on_privacy_screen_enabled_changed (MetaOutput *output,
|
||||||
{
|
{
|
||||||
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
||||||
|
|
||||||
onscreen_native->is_privacy_screen_invalid = TRUE;
|
onscreen_native->property.privacy_screen.invalidated = TRUE;
|
||||||
clutter_stage_view_schedule_update (stage_view);
|
clutter_stage_view_schedule_update (stage_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2685,7 +2727,7 @@ on_color_space_changed (MetaOutput *output,
|
||||||
{
|
{
|
||||||
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
||||||
|
|
||||||
onscreen_native->is_color_space_invalid = TRUE;
|
onscreen_native->property.color_space.invalidated = TRUE;
|
||||||
clutter_stage_view_schedule_update (stage_view);
|
clutter_stage_view_schedule_update (stage_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2695,7 +2737,7 @@ on_hdr_metadata_changed (MetaOutput *output,
|
||||||
{
|
{
|
||||||
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
||||||
|
|
||||||
onscreen_native->is_hdr_metadata_invalid = TRUE;
|
onscreen_native->property.hdr_metadata.invalidated = TRUE;
|
||||||
clutter_stage_view_schedule_update (stage_view);
|
clutter_stage_view_schedule_update (stage_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2730,8 +2772,8 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native,
|
||||||
|
|
||||||
if (meta_crtc_get_gamma_lut_size (crtc) > 0)
|
if (meta_crtc_get_gamma_lut_size (crtc) > 0)
|
||||||
{
|
{
|
||||||
onscreen_native->is_gamma_lut_invalid = TRUE;
|
onscreen_native->property.gamma_lut.invalidated = TRUE;
|
||||||
onscreen_native->gamma_lut_changed_handler_id =
|
onscreen_native->property.gamma_lut.signal_handler_id =
|
||||||
g_signal_connect (crtc, "gamma-lut-changed",
|
g_signal_connect (crtc, "gamma-lut-changed",
|
||||||
G_CALLBACK (on_gamma_lut_changed),
|
G_CALLBACK (on_gamma_lut_changed),
|
||||||
onscreen_native);
|
onscreen_native);
|
||||||
|
@ -2739,8 +2781,8 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native,
|
||||||
|
|
||||||
if (output_info->supports_privacy_screen)
|
if (output_info->supports_privacy_screen)
|
||||||
{
|
{
|
||||||
onscreen_native->is_privacy_screen_invalid = TRUE;
|
onscreen_native->property.privacy_screen.invalidated = TRUE;
|
||||||
onscreen_native->privacy_screen_changed_handler_id =
|
onscreen_native->property.privacy_screen.signal_handler_id =
|
||||||
g_signal_connect (output, "notify::is-privacy-screen-enabled",
|
g_signal_connect (output, "notify::is-privacy-screen-enabled",
|
||||||
G_CALLBACK (on_privacy_screen_enabled_changed),
|
G_CALLBACK (on_privacy_screen_enabled_changed),
|
||||||
onscreen_native);
|
onscreen_native);
|
||||||
|
@ -2749,8 +2791,8 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native,
|
||||||
if (output_info->supported_color_spaces &
|
if (output_info->supported_color_spaces &
|
||||||
(1 << META_OUTPUT_COLORSPACE_DEFAULT))
|
(1 << META_OUTPUT_COLORSPACE_DEFAULT))
|
||||||
{
|
{
|
||||||
onscreen_native->is_color_space_invalid = TRUE;
|
onscreen_native->property.color_space.invalidated = TRUE;
|
||||||
onscreen_native->color_space_changed_handler_id =
|
onscreen_native->property.color_space.signal_handler_id =
|
||||||
g_signal_connect (output, "color-space-changed",
|
g_signal_connect (output, "color-space-changed",
|
||||||
G_CALLBACK (on_color_space_changed),
|
G_CALLBACK (on_color_space_changed),
|
||||||
onscreen_native);
|
onscreen_native);
|
||||||
|
@ -2759,8 +2801,8 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native,
|
||||||
if (output_info->supported_hdr_eotfs &
|
if (output_info->supported_hdr_eotfs &
|
||||||
(1 << META_OUTPUT_HDR_METADATA_EOTF_TRADITIONAL_GAMMA_SDR))
|
(1 << META_OUTPUT_HDR_METADATA_EOTF_TRADITIONAL_GAMMA_SDR))
|
||||||
{
|
{
|
||||||
onscreen_native->is_hdr_metadata_invalid = TRUE;
|
onscreen_native->property.hdr_metadata.invalidated = TRUE;
|
||||||
onscreen_native->hdr_metadata_changed_handler_id =
|
onscreen_native->property.hdr_metadata.signal_handler_id =
|
||||||
g_signal_connect (output, "hdr-metadata-changed",
|
g_signal_connect (output, "hdr-metadata-changed",
|
||||||
G_CALLBACK (on_hdr_metadata_changed),
|
G_CALLBACK (on_hdr_metadata_changed),
|
||||||
onscreen_native);
|
onscreen_native);
|
||||||
|
@ -2772,13 +2814,13 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native,
|
||||||
static void
|
static void
|
||||||
clear_invalidation_handlers (MetaOnscreenNative *onscreen_native)
|
clear_invalidation_handlers (MetaOnscreenNative *onscreen_native)
|
||||||
{
|
{
|
||||||
g_clear_signal_handler (&onscreen_native->gamma_lut_changed_handler_id,
|
g_clear_signal_handler (&onscreen_native->property.gamma_lut.signal_handler_id,
|
||||||
onscreen_native->crtc);
|
onscreen_native->crtc);
|
||||||
g_clear_signal_handler (&onscreen_native->privacy_screen_changed_handler_id,
|
g_clear_signal_handler (&onscreen_native->property.privacy_screen.signal_handler_id,
|
||||||
onscreen_native->output);
|
onscreen_native->output);
|
||||||
g_clear_signal_handler (&onscreen_native->color_space_changed_handler_id,
|
g_clear_signal_handler (&onscreen_native->property.color_space.signal_handler_id,
|
||||||
onscreen_native->output);
|
onscreen_native->output);
|
||||||
g_clear_signal_handler (&onscreen_native->hdr_metadata_changed_handler_id,
|
g_clear_signal_handler (&onscreen_native->property.hdr_metadata.signal_handler_id,
|
||||||
onscreen_native->output);
|
onscreen_native->output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue