renderer-native: Fake page flipped if power saving when retrying

When we're in a page-flip retry loop due to the FIFO being full
(drmModePageFlip() failing with EBUSY), we should not continue to try
when starting to power save, as that means we're blocking new frames,
which itself blocks input events due to them being compressed using the
frame clock.

We'd also hit an assert assuming we only try to page flip when not power
saving.

Thus, fake we flipped if we ended up reaching a power saving state while
retrying.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/509

https://gitlab.gnome.org/GNOME/mutter/merge_requests/506
This commit is contained in:
Jonas Ådahl 2019-03-25 10:19:21 +01:00
parent 40e7e5d356
commit 53b59d8bff

View File

@ -1541,14 +1541,39 @@ retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data)
g_free (retry_page_flip_data); g_free (retry_page_flip_data);
} }
static void
retry_page_flip_data_fake_flipped (RetryPageFlipData *retry_page_flip_data,
MetaOnscreenNative *onscreen_native)
{
MetaCrtc *crtc = retry_page_flip_data->crtc;
MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
if (gpu_kms != onscreen_native->render_gpu)
{
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
secondary_gpu_state =
meta_onscreen_native_get_secondary_gpu_state (onscreen_native,
gpu_kms);
secondary_gpu_state->pending_flips--;
}
onscreen_native->total_pending_flips--;
}
static gboolean static gboolean
retry_page_flips (gpointer user_data) retry_page_flips (gpointer user_data)
{ {
MetaOnscreenNative *onscreen_native = user_data; MetaOnscreenNative *onscreen_native = user_data;
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
MetaMonitorManager *monitor_manager =
META_MONITOR_MANAGER (renderer_native->monitor_manager_kms);
uint64_t now_us; uint64_t now_us;
MetaPowerSave power_save_mode;
GList *l; GList *l;
now_us = g_source_get_time (onscreen_native->retry_page_flips_source); now_us = g_source_get_time (onscreen_native->retry_page_flips_source);
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
l = onscreen_native->pending_page_flip_retries; l = onscreen_native->pending_page_flip_retries;
while (l) while (l)
@ -1560,6 +1585,19 @@ retry_page_flips (gpointer user_data)
g_autoptr (GError) error = NULL; g_autoptr (GError) error = NULL;
gboolean did_flip; gboolean did_flip;
if (power_save_mode != META_POWER_SAVE_ON)
{
onscreen_native->pending_page_flip_retries =
g_list_remove_link (onscreen_native->pending_page_flip_retries, l);
retry_page_flip_data_fake_flipped (retry_page_flip_data,
onscreen_native);
retry_page_flip_data_free (retry_page_flip_data);
l = l_next;
continue;
}
if (is_timestamp_earlier_than (now_us, if (is_timestamp_earlier_than (now_us,
retry_page_flip_data->retry_time_us)) retry_page_flip_data->retry_time_us))
{ {
@ -1591,17 +1629,8 @@ retry_page_flips (gpointer user_data)
G_IO_ERROR_PERMISSION_DENIED)) G_IO_ERROR_PERMISSION_DENIED))
g_critical ("Failed to page flip: %s", error->message); g_critical ("Failed to page flip: %s", error->message);
if (gpu_kms != onscreen_native->render_gpu) retry_page_flip_data_fake_flipped (retry_page_flip_data,
{ onscreen_native);
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
secondary_gpu_state =
meta_onscreen_native_get_secondary_gpu_state (onscreen_native,
gpu_kms);
secondary_gpu_state->pending_flips--;
}
onscreen_native->total_pending_flips--;
} }
retry_page_flip_data_free (retry_page_flip_data); retry_page_flip_data_free (retry_page_flip_data);