kms: Post pending updates per device

Instead of a "post all pending updates", pass an update specific to a
single device. This gets rid of the awkward "combine feedback" function,
and makes it possible to queue updates to a multiple devices without
always posting them together.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This commit is contained in:
Jonas Ådahl 2020-10-02 10:38:57 +02:00 committed by Marge Bot
parent 5ba2d79076
commit 2df6327367
5 changed files with 124 additions and 119 deletions

View File

@ -544,7 +544,6 @@ update_hw_cursor (MetaCursorRendererNative *native,
GList *l; GList *l;
graphene_rect_t rect; graphene_rect_t rect;
gboolean painted = FALSE; gboolean painted = FALSE;
g_autoptr (MetaKmsFeedback) feedback = NULL;
if (cursor_sprite) if (cursor_sprite)
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
@ -589,23 +588,36 @@ update_hw_cursor (MetaCursorRendererNative *native,
painted = painted || data.out_painted; painted = painted || data.out_painted;
} }
feedback = meta_kms_post_pending_updates_sync (kms); for (l = meta_kms_get_devices (kms); l; l = l->next)
if (meta_kms_feedback_get_result (feedback) != META_KMS_FEEDBACK_PASSED)
{ {
for (l = meta_kms_feedback_get_failed_planes (feedback); l; l = l->next) MetaKmsDevice *kms_device = l->data;
MetaKmsUpdate *kms_update;
g_autoptr (MetaKmsFeedback) feedback = NULL;
kms_update = meta_kms_get_pending_update (kms, kms_device);
if (!kms_update)
continue;
feedback = meta_kms_post_pending_update_sync (kms, kms_device);
if (meta_kms_feedback_get_result (feedback) != META_KMS_FEEDBACK_PASSED)
{ {
MetaKmsPlaneFeedback *plane_feedback = l->data; GList *k;
if (!g_error_matches (plane_feedback->error, for (k = meta_kms_feedback_get_failed_planes (feedback); k; k = k->next)
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
{ {
disable_hw_cursor_for_crtc (plane_feedback->crtc, MetaKmsPlaneFeedback *plane_feedback = k->data;
plane_feedback->error);
}
}
priv->has_hw_cursor = FALSE; if (!g_error_matches (plane_feedback->error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
{
disable_hw_cursor_for_crtc (plane_feedback->crtc,
plane_feedback->error);
}
}
priv->has_hw_cursor = FALSE;
}
} }
priv->hw_state_invalidated = FALSE; priv->hw_state_invalidated = FALSE;

View File

@ -210,95 +210,65 @@ meta_kms_get_pending_update (MetaKms *kms,
return NULL; return NULL;
} }
static void static MetaKmsUpdate *
meta_kms_predict_states_in_impl (MetaKms *kms, meta_kms_take_pending_update (MetaKms *kms,
MetaKmsUpdate *update) MetaKmsDevice *device)
{ {
meta_assert_in_kms_impl (kms); GList *l;
g_list_foreach (kms->devices, for (l = kms->pending_updates; l; l = l->next)
(GFunc) meta_kms_device_predict_states_in_impl,
update);
}
static MetaKmsFeedback *
combine_feedbacks (MetaKmsFeedback *feedback,
MetaKmsFeedback *other_feedback)
{
GList *failed_planes;
MetaKmsFeedback *new_feedback;
const GError *error;
if (!feedback)
return other_feedback;
failed_planes =
g_list_concat (meta_kms_feedback_get_failed_planes (feedback),
meta_kms_feedback_get_failed_planes (other_feedback));
error = meta_kms_feedback_get_error (feedback);
if (!error)
error = meta_kms_feedback_get_error (other_feedback);
if (error)
{ {
new_feedback = meta_kms_feedback_new_failed (failed_planes, MetaKmsUpdate *update = l->data;
g_error_copy (error));
} if (meta_kms_update_get_device (update) == device)
else {
{ kms->pending_updates = g_list_delete_link (kms->pending_updates, l);
new_feedback = meta_kms_feedback_new_passed (); return update;
}
} }
meta_kms_feedback_free (feedback); return NULL;
meta_kms_feedback_free (other_feedback);
return new_feedback;
} }
static gpointer static gpointer
meta_kms_process_updates_in_impl (MetaKmsImpl *impl, meta_kms_process_update_in_impl (MetaKmsImpl *impl,
gpointer user_data, gpointer user_data,
GError **error) GError **error)
{ {
GList *updates = user_data; MetaKmsFeedback *feedback;
MetaKmsFeedback *feedback = NULL; MetaKmsUpdate *update = user_data;
GList *l;
for (l = updates; l; l = l->next) feedback = meta_kms_impl_process_update (impl, update);
{ meta_kms_device_predict_states_in_impl (meta_kms_update_get_device (update),
MetaKmsUpdate *update = l->data; update);
MetaKmsFeedback *device_feedback;
device_feedback = meta_kms_impl_process_update (impl, update);
feedback = combine_feedbacks (feedback, device_feedback);
meta_kms_predict_states_in_impl (meta_kms_impl_get_kms (impl), update);
}
g_list_free_full (updates, (GDestroyNotify) meta_kms_update_free);
return feedback; return feedback;
} }
static MetaKmsFeedback * MetaKmsFeedback *
meta_kms_post_updates_sync (MetaKms *kms, meta_kms_post_pending_update_sync (MetaKms *kms,
GList *updates) MetaKmsDevice *device)
{ {
g_list_foreach (updates, (GFunc) meta_kms_update_seal, NULL); MetaKmsUpdate *update;
MetaKmsFeedback *feedback;
COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync, COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync,
"KMS (post update)"); "KMS (post update)");
return meta_kms_run_impl_task_sync (kms, update = meta_kms_take_pending_update (kms, device);
meta_kms_process_updates_in_impl, if (!update)
updates, return NULL;
NULL);
}
MetaKmsFeedback * meta_kms_update_seal (update);
meta_kms_post_pending_updates_sync (MetaKms *kms)
{ feedback = meta_kms_run_impl_task_sync (kms,
return meta_kms_post_updates_sync (kms, meta_kms_process_update_in_impl,
g_steal_pointer (&kms->pending_updates)); update,
NULL);
meta_kms_update_free (update);
return feedback;
} }
static gpointer static gpointer
@ -584,6 +554,12 @@ meta_kms_get_backend (MetaKms *kms)
return kms->backend; return kms->backend;
} }
GList *
meta_kms_get_devices (MetaKms *kms)
{
return kms->devices;
}
MetaKmsDevice * MetaKmsDevice *
meta_kms_create_device (MetaKms *kms, meta_kms_create_device (MetaKms *kms,
const char *path, const char *path,

View File

@ -34,12 +34,15 @@ MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms,
MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms, MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms,
MetaKmsDevice *device); MetaKmsDevice *device);
MetaKmsFeedback * meta_kms_post_pending_updates_sync (MetaKms *kms); MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsDevice *device);
void meta_kms_discard_pending_page_flips (MetaKms *kms); void meta_kms_discard_pending_page_flips (MetaKms *kms);
MetaBackend * meta_kms_get_backend (MetaKms *kms); MetaBackend * meta_kms_get_backend (MetaKms *kms);
GList * meta_kms_get_devices (MetaKms *kms);
MetaKmsDevice * meta_kms_create_device (MetaKms *kms, MetaKmsDevice * meta_kms_create_device (MetaKms *kms,
const char *path, const char *path,
MetaKmsDeviceFlag flags, MetaKmsDeviceFlag flags,

View File

@ -122,7 +122,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
MetaKms *kms = meta_backend_native_get_kms (backend_native); MetaKms *kms = meta_backend_native_get_kms (backend_native);
uint64_t state; uint64_t state;
GList *l; GList *l;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
switch (mode) { switch (mode) {
case META_POWER_SAVE_ON: case META_POWER_SAVE_ON:
@ -146,16 +145,18 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
MetaGpuKms *gpu_kms = l->data; MetaGpuKms *gpu_kms = l->data;
MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms); MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
MetaKmsUpdate *kms_update; MetaKmsUpdate *kms_update;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
kms_update = meta_kms_ensure_pending_update (kms, kms_device); kms_update = meta_kms_ensure_pending_update (kms, kms_device);
meta_gpu_kms_set_power_save_mode (gpu_kms, state, kms_update); meta_gpu_kms_set_power_save_mode (gpu_kms, state, kms_update);
}
kms_feedback = meta_kms_post_pending_updates_sync (kms); kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device);
if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) if (meta_kms_feedback_get_result (kms_feedback) !=
{ META_KMS_FEEDBACK_PASSED)
g_warning ("Failed to set DPMS: %s", {
meta_kms_feedback_get_error (kms_feedback)->message); g_warning ("Failed to set DPMS: %s",
meta_kms_feedback_get_error (kms_feedback)->message);
}
} }
} }
@ -433,7 +434,7 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") gamma to %s", g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") gamma to %s",
meta_crtc_get_id (crtc), gamma_ramp_string); meta_crtc_get_id (crtc), gamma_ramp_string);
kms_feedback = meta_kms_post_pending_updates_sync (kms); kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device);
if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
{ {
g_warning ("Failed to set CRTC gamma: %s", g_warning ("Failed to set CRTC gamma: %s",

View File

@ -1867,24 +1867,24 @@ ensure_crtc_modes (CoglOnscreen *onscreen)
} }
} }
static gboolean static void
unset_disabled_crtcs (MetaBackend *backend, unset_disabled_crtcs (MetaBackend *backend,
MetaKms *kms) MetaKms *kms)
{ {
gboolean did_mode_set = FALSE;
GList *l; GList *l;
for (l = meta_backend_get_gpus (backend); l; l = l->next) for (l = meta_backend_get_gpus (backend); l; l = l->next)
{ {
MetaGpu *gpu = l->data; MetaGpu *gpu = l->data;
MetaKmsDevice *kms_device =
meta_gpu_kms_get_kms_device (META_GPU_KMS (gpu));
GList *k; GList *k;
gboolean did_mode_set = FALSE;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
for (k = meta_gpu_get_crtcs (gpu); k; k = k->next) for (k = meta_gpu_get_crtcs (gpu); k; k = k->next)
{ {
MetaCrtc *crtc = k->data; MetaCrtc *crtc = k->data;
MetaKmsCrtc *kms_crtc =
meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
MetaKmsUpdate *kms_update; MetaKmsUpdate *kms_update;
if (meta_crtc_get_config (crtc)) if (meta_crtc_get_config (crtc))
@ -1895,23 +1895,20 @@ unset_disabled_crtcs (MetaBackend *backend,
did_mode_set = TRUE; did_mode_set = TRUE;
} }
}
return did_mode_set; if (!did_mode_set)
} continue;
static void kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device);
post_pending_updates (MetaKms *kms) if (meta_kms_feedback_get_result (kms_feedback) !=
{ META_KMS_FEEDBACK_PASSED)
g_autoptr (MetaKmsFeedback) kms_feedback = NULL; {
const GError *error = meta_kms_feedback_get_error (kms_feedback);
kms_feedback = meta_kms_post_pending_updates_sync (kms); if (!g_error_matches (error, G_IO_ERROR,
if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) G_IO_ERROR_PERMISSION_DENIED))
{ g_warning ("Failed to post KMS update: %s", error->message);
const GError *error = meta_kms_feedback_get_error (kms_feedback); }
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
g_warning ("Failed to post KMS update: %s", error->message);
} }
} }
@ -1942,6 +1939,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
MetaPowerSave power_save_mode; MetaPowerSave power_save_mode;
g_autoptr (GError) error = NULL; g_autoptr (GError) error = NULL;
MetaDrmBufferGbm *buffer_gbm; MetaDrmBufferGbm *buffer_gbm;
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL; g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
@ -2008,7 +2007,22 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
COGL_TRACE_BEGIN (MetaRendererNativePostKmsUpdate, COGL_TRACE_BEGIN (MetaRendererNativePostKmsUpdate,
"Onscreen (post pending update)"); "Onscreen (post pending update)");
post_pending_updates (kms); kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
kms_device = meta_kms_crtc_get_device (kms_crtc);
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device);
if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
{
const GError *error = meta_kms_feedback_get_error (kms_feedback);
MetaGpuKms *gpu_kms =
META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc));
int64_t now_ns;
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
g_warning ("Failed to post KMS update: %s", error->message);
now_ns = meta_gpu_kms_get_current_time_ns (gpu_kms);
notify_view_crtc_presented (onscreen_native->view, kms_crtc, now_ns);
}
COGL_TRACE_END (MetaRendererNativePostKmsUpdate); COGL_TRACE_END (MetaRendererNativePostKmsUpdate);
} }
@ -2157,6 +2171,8 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
MetaMonitorManager *monitor_manager = MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend); meta_backend_get_monitor_manager (backend);
MetaPowerSave power_save_mode; MetaPowerSave power_save_mode;
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL; g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
@ -2179,7 +2195,9 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
meta_onscreen_native_flip_crtcs (onscreen, meta_onscreen_native_flip_crtcs (onscreen,
META_KMS_PAGE_FLIP_FLAG_NO_DISCARD_FEEDBACK); META_KMS_PAGE_FLIP_FLAG_NO_DISCARD_FEEDBACK);
kms_feedback = meta_kms_post_pending_updates_sync (kms); kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
kms_device = meta_kms_crtc_get_device (kms_crtc);
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device);
if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
{ {
const GError *feedback_error = meta_kms_feedback_get_error (kms_feedback); const GError *feedback_error = meta_kms_feedback_get_error (kms_feedback);
@ -3010,16 +3028,12 @@ meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
MetaBackend *backend = meta_renderer_get_backend (renderer); MetaBackend *backend = meta_renderer_get_backend (renderer);
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native); MetaKms *kms = meta_backend_native_get_kms (backend_native);
gboolean did_mode_set = FALSE;
if (renderer_native->pending_unset_disabled_crtcs) if (renderer_native->pending_unset_disabled_crtcs)
{ {
did_mode_set = unset_disabled_crtcs (backend, kms); unset_disabled_crtcs (backend, kms);
renderer_native->pending_unset_disabled_crtcs = FALSE; renderer_native->pending_unset_disabled_crtcs = FALSE;
} }
if (did_mode_set)
post_pending_updates (kms);
} }
static gboolean static gboolean
@ -3603,8 +3617,7 @@ meta_renderer_native_reset_modes (MetaRendererNative *renderer_native)
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native); MetaKms *kms = meta_backend_native_get_kms (backend_native);
if (unset_disabled_crtcs (backend, kms)) unset_disabled_crtcs (backend, kms);
post_pending_updates (kms);
} }
static MetaGpuKms * static MetaGpuKms *