[mutter] kms: Predict state changes when processing update
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] kms: Predict state changes when processing update
- Date: Mon, 7 Oct 2019 15:11:35 +0000 (UTC)
commit 104bdde746c9ceccd9e9ab09b22ef228b8f7026e
Author: Jonas Ådahl <jadahl gmail com>
Date: Fri Oct 4 11:54:29 2019 +0200
kms: Predict state changes when processing update
We can't just update the state of the connector and CRTC from KMS since
it might contain too new updates, e.g. from a from a future hot plug. In
order to not add ad-hoc hot plug detection everywhere, predict the state
changes by looking inside the MetaKmsUpdate object, and let the hot-plug
state changes happen after the actual hot-plug event.
This fixes issues where connectors were discovered as disconnected while
doing a mode-set, meaning assumptions about the connectedness of
monitors elsewhere were broken until the hot plug event was processed.
Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/782
https://gitlab.gnome.org/GNOME/mutter/merge_requests/826
src/backends/native/meta-kms-connector-private.h | 3 ++
src/backends/native/meta-kms-connector.c | 30 +++++++++++++
src/backends/native/meta-kms-crtc-private.h | 3 ++
src/backends/native/meta-kms-crtc.c | 57 ++++++++++++++++++++++++
src/backends/native/meta-kms-device-private.h | 6 ++-
src/backends/native/meta-kms-device.c | 32 +++++++------
src/backends/native/meta-kms-impl-device.c | 16 +++++--
src/backends/native/meta-kms-impl-device.h | 6 ++-
src/backends/native/meta-kms-types.h | 6 ---
src/backends/native/meta-kms.c | 49 +++++++++-----------
10 files changed, 153 insertions(+), 55 deletions(-)
---
diff --git a/src/backends/native/meta-kms-connector-private.h
b/src/backends/native/meta-kms-connector-private.h
index 427502a34..29901c487 100644
--- a/src/backends/native/meta-kms-connector-private.h
+++ b/src/backends/native/meta-kms-connector-private.h
@@ -25,6 +25,9 @@
void meta_kms_connector_update_state (MetaKmsConnector *connector,
drmModeRes *drm_resources);
+void meta_kms_connector_predict_state (MetaKmsConnector *connector,
+ MetaKmsUpdate *update);
+
MetaKmsConnector * meta_kms_connector_new (MetaKmsImplDevice *impl_device,
drmModeConnector *drm_connector,
drmModeRes *drm_resources);
diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c
index 1508d4fea..c018a5e62 100644
--- a/src/backends/native/meta-kms-connector.c
+++ b/src/backends/native/meta-kms-connector.c
@@ -24,6 +24,7 @@
#include <errno.h>
+#include "backends/native/meta-kms-crtc.h"
#include "backends/native/meta-kms-device-private.h"
#include "backends/native/meta-kms-impl-device.h"
#include "backends/native/meta-kms-update-private.h"
@@ -495,6 +496,35 @@ meta_kms_connector_update_state (MetaKmsConnector *connector,
drmModeFreeConnector (drm_connector);
}
+void
+meta_kms_connector_predict_state (MetaKmsConnector *connector,
+ MetaKmsUpdate *update)
+{
+ GList *mode_sets;
+ GList *l;
+
+ if (!connector->current_state)
+ return;
+
+ mode_sets = meta_kms_update_get_mode_sets (update);
+ for (l = mode_sets; l; l = l->next)
+ {
+ MetaKmsModeSet *mode_set = l->data;
+ MetaKmsCrtc *crtc;
+
+ if (!g_list_find (mode_set->connectors, connector))
+ continue;
+
+ crtc = mode_set->crtc;
+ if (crtc)
+ connector->current_state->current_crtc_id = meta_kms_crtc_get_id (crtc);
+ else
+ connector->current_state->current_crtc_id = 0;
+
+ break;
+ }
+}
+
static void
find_property_ids (MetaKmsConnector *connector,
MetaKmsImplDevice *impl_device,
diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h
index 41db399e6..f9a3a6e0a 100644
--- a/src/backends/native/meta-kms-crtc-private.h
+++ b/src/backends/native/meta-kms-crtc-private.h
@@ -30,4 +30,7 @@ MetaKmsCrtc * meta_kms_crtc_new (MetaKmsImplDevice *impl_device,
void meta_kms_crtc_update_state (MetaKmsCrtc *crtc);
+void meta_kms_crtc_predict_state (MetaKmsCrtc *crtc,
+ MetaKmsUpdate *update);
+
#endif /* META_KMS_CRTC_PRIVATE_H */
diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c
index 2b0f5385a..3610df903 100644
--- a/src/backends/native/meta-kms-crtc.c
+++ b/src/backends/native/meta-kms-crtc.c
@@ -143,6 +143,63 @@ meta_kms_crtc_update_state (MetaKmsCrtc *crtc)
drmModeFreeCrtc (drm_crtc);
}
+void
+meta_kms_crtc_predict_state (MetaKmsCrtc *crtc,
+ MetaKmsUpdate *update)
+{
+ GList *mode_sets;
+ GList *crtc_gammas;
+ GList *l;
+
+ mode_sets = meta_kms_update_get_mode_sets (update);
+ for (l = mode_sets; l; l = l->next)
+ {
+ MetaKmsModeSet *mode_set = l->data;
+
+ if (mode_set->crtc != crtc)
+ continue;
+
+ if (mode_set->drm_mode)
+ {
+ MetaKmsPlaneAssignment *plane_assignment;
+
+ plane_assignment =
+ meta_kms_update_get_primary_plane_assignment (update, crtc);
+
+ crtc->current_state.rect =
+ meta_fixed_16_rectangle_to_rectangle (plane_assignment->src_rect);
+ crtc->current_state.is_drm_mode_valid = TRUE;
+ crtc->current_state.drm_mode = *mode_set->drm_mode;
+ }
+ else
+ {
+ crtc->current_state.rect = (MetaRectangle) { 0 };
+ crtc->current_state.is_drm_mode_valid = FALSE;
+ crtc->current_state.drm_mode = (drmModeModeInfo) { 0 };
+ }
+
+ break;
+ }
+
+ crtc_gammas = meta_kms_update_get_crtc_gammas (update);
+ for (l = crtc_gammas; l; l = l->next)
+ {
+ MetaKmsCrtcGamma *gamma = l->data;
+
+ if (gamma->crtc != crtc)
+ continue;
+
+ crtc->current_state.gamma.size = gamma->size;
+ crtc->current_state.gamma.red =
+ g_memdup (gamma->red, gamma->size * sizeof (uint16_t));
+ crtc->current_state.gamma.green =
+ g_memdup (gamma->green, gamma->size * sizeof (uint16_t));
+ crtc->current_state.gamma.blue =
+ g_memdup (gamma->blue, gamma->size * sizeof (uint16_t));
+ break;
+ }
+}
+
MetaKmsCrtc *
meta_kms_crtc_new (MetaKmsImplDevice *impl_device,
drmModeCrtc *drm_crtc,
diff --git a/src/backends/native/meta-kms-device-private.h b/src/backends/native/meta-kms-device-private.h
index bcb3a6e74..876fb30fc 100644
--- a/src/backends/native/meta-kms-device-private.h
+++ b/src/backends/native/meta-kms-device-private.h
@@ -24,7 +24,9 @@
MetaKmsImplDevice * meta_kms_device_get_impl_device (MetaKmsDevice *device);
-void meta_kms_device_update_states_in_impl (MetaKmsDevice *device,
- MetaKmsUpdateStatesFlags flags);
+void meta_kms_device_update_states_in_impl (MetaKmsDevice *device);
+
+void meta_kms_device_predict_states_in_impl (MetaKmsDevice *device,
+ MetaKmsUpdate *update);
#endif /* META_KMS_DEVICE_PRIVATE_H */
diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c
index d137c63b9..8ed2de024 100644
--- a/src/backends/native/meta-kms-device.c
+++ b/src/backends/native/meta-kms-device.c
@@ -109,28 +109,34 @@ meta_kms_device_get_primary_plane_for (MetaKmsDevice *device,
}
void
-meta_kms_device_update_states_in_impl (MetaKmsDevice *device,
- MetaKmsUpdateStatesFlags flags)
+meta_kms_device_update_states_in_impl (MetaKmsDevice *device)
{
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
meta_assert_in_kms_impl (device->kms);
+ meta_assert_is_waiting_for_kms_impl_task (device->kms);
- meta_kms_impl_device_update_states (impl_device, flags);
+ meta_kms_impl_device_update_states (impl_device);
- if (flags & META_KMS_UPDATE_STATES_FLAG_HOTPLUG)
- {
- meta_assert_is_waiting_for_kms_impl_task (device->kms);
+ g_list_free (device->crtcs);
+ device->crtcs = meta_kms_impl_device_copy_crtcs (impl_device);
- g_list_free (device->crtcs);
- device->crtcs = meta_kms_impl_device_copy_crtcs (impl_device);
+ g_list_free (device->connectors);
+ device->connectors = meta_kms_impl_device_copy_connectors (impl_device);
- g_list_free (device->connectors);
- device->connectors = meta_kms_impl_device_copy_connectors (impl_device);
+ g_list_free (device->planes);
+ device->planes = meta_kms_impl_device_copy_planes (impl_device);
+}
- g_list_free (device->planes);
- device->planes = meta_kms_impl_device_copy_planes (impl_device);
- }
+void
+meta_kms_device_predict_states_in_impl (MetaKmsDevice *device,
+ MetaKmsUpdate *update)
+{
+ MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
+
+ meta_assert_in_kms_impl (device->kms);
+
+ meta_kms_impl_device_predict_states (impl_device, update);
}
static gboolean
diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c
index dde192b42..922aca103 100644
--- a/src/backends/native/meta-kms-impl-device.c
+++ b/src/backends/native/meta-kms-impl-device.c
@@ -319,8 +319,7 @@ init_planes (MetaKmsImplDevice *impl_device)
}
void
-meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device,
- MetaKmsUpdateStatesFlags flags)
+meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device)
{
drmModeRes *drm_resources;
@@ -328,8 +327,7 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device,
drm_resources = drmModeGetResources (impl_device->fd);
- if (flags & META_KMS_UPDATE_STATES_FLAG_HOTPLUG)
- update_connectors (impl_device, drm_resources);
+ update_connectors (impl_device, drm_resources);
g_list_foreach (impl_device->crtcs, (GFunc) meta_kms_crtc_update_state,
NULL);
@@ -338,6 +336,16 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device,
drmModeFreeResources (drm_resources);
}
+void
+meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device,
+ MetaKmsUpdate *update)
+{
+ g_list_foreach (impl_device->crtcs, (GFunc) meta_kms_crtc_predict_state,
+ update);
+ g_list_foreach (impl_device->connectors, (GFunc) meta_kms_connector_predict_state,
+ update);
+}
+
MetaKmsImplDevice *
meta_kms_impl_device_new (MetaKmsDevice *device,
MetaKmsImpl *impl,
diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h
index 1e971af8b..5bd0f5f98 100644
--- a/src/backends/native/meta-kms-impl-device.h
+++ b/src/backends/native/meta-kms-impl-device.h
@@ -53,8 +53,10 @@ int meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device);
int meta_kms_impl_device_leak_fd (MetaKmsImplDevice *impl_device);
-void meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device,
- MetaKmsUpdateStatesFlags flags);
+void meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device);
+
+void meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device,
+ MetaKmsUpdate *update);
int meta_kms_impl_device_close (MetaKmsImplDevice *impl_device);
diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h
index ed4a4cd9d..dd14a7be7 100644
--- a/src/backends/native/meta-kms-types.h
+++ b/src/backends/native/meta-kms-types.h
@@ -56,10 +56,4 @@ typedef enum _MetaKmsDeviceFlag
META_KMS_DEVICE_FLAG_PLATFORM_DEVICE = 1 << 1,
} MetaKmsDeviceFlag;
-typedef enum _MetaKmsUpdateStatesFlags
-{
- META_KMS_UPDATE_STATES_FLAG_NONE = 0,
- META_KMS_UPDATE_STATES_FLAG_HOTPLUG = 1 << 0,
-} MetaKmsUpdateStatesFlags;
-
#endif /* META_KMS_IMPL_TYPES_H */
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
index 39d1f3155..9485bb4e8 100644
--- a/src/backends/native/meta-kms.c
+++ b/src/backends/native/meta-kms.c
@@ -175,10 +175,6 @@ struct _MetaKms
G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT)
-static void
-meta_kms_update_states_in_impl (MetaKms *kms,
- MetaKmsUpdateStatesFlags flags);
-
MetaKmsUpdate *
meta_kms_ensure_pending_update (MetaKms *kms)
{
@@ -194,6 +190,17 @@ meta_kms_get_pending_update (MetaKms *kms)
return kms->pending_update;
}
+static void
+meta_kms_predict_states_in_impl (MetaKms *kms,
+ MetaKmsUpdate *update)
+{
+ meta_assert_in_kms_impl (kms);
+
+ g_list_foreach (kms->devices,
+ (GFunc) meta_kms_device_predict_states_in_impl,
+ update);
+}
+
static gboolean
meta_kms_update_process_in_impl (MetaKmsImpl *impl,
gpointer user_data,
@@ -205,8 +212,7 @@ meta_kms_update_process_in_impl (MetaKmsImpl *impl,
ret = meta_kms_impl_process_update (impl, update, error);
if (meta_kms_update_has_mode_set (update))
- meta_kms_update_states_in_impl (meta_kms_impl_get_kms (impl),
- META_KMS_UPDATE_STATES_FLAG_NONE);
+ meta_kms_predict_states_in_impl (meta_kms_impl_get_kms (impl), update);
return ret;
}
@@ -461,22 +467,16 @@ meta_kms_is_waiting_for_impl_task (MetaKms *kms)
}
static void
-meta_kms_update_states_in_impl (MetaKms *kms,
- MetaKmsUpdateStatesFlags flags)
+meta_kms_update_states_in_impl (MetaKms *kms)
{
- GList *l;
-
COGL_TRACE_BEGIN_SCOPED (MetaKmsUpdateStates,
"KMS (update states)");
meta_assert_in_kms_impl (kms);
- for (l = kms->devices; l; l = l->next)
- {
- MetaKmsDevice *device = l->data;
-
- meta_kms_device_update_states_in_impl (device, flags);
- }
+ g_list_foreach (kms->devices,
+ (GFunc) meta_kms_device_update_states_in_impl,
+ NULL);
}
static gboolean
@@ -485,22 +485,17 @@ update_states_in_impl (MetaKmsImpl *impl,
GError **error)
{
MetaKms *kms = meta_kms_impl_get_kms (impl);;
- MetaKmsUpdateStatesFlags flags = GPOINTER_TO_UINT (user_data);
- meta_kms_update_states_in_impl (kms, flags);
+ meta_kms_update_states_in_impl (kms);
return TRUE;
}
static gboolean
-meta_kms_update_states_sync (MetaKms *kms,
- MetaKmsUpdateStatesFlags flags,
- GError **error)
+meta_kms_update_states_sync (MetaKms *kms,
+ GError **error)
{
- return meta_kms_run_impl_task_sync (kms,
- update_states_in_impl,
- GUINT_TO_POINTER (flags),
- error);
+ return meta_kms_run_impl_task_sync (kms, update_states_in_impl, NULL, error);
}
static void
@@ -508,9 +503,7 @@ handle_hotplug_event (MetaKms *kms)
{
g_autoptr (GError) error = NULL;
- if (!meta_kms_update_states_sync (kms,
- META_KMS_UPDATE_STATES_FLAG_HOTPLUG,
- &error))
+ if (!meta_kms_update_states_sync (kms, &error))
g_warning ("Updating KMS state failed: %s", error->message);
g_signal_emit (kms, signals[RESOURCES_CHANGED], 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]