kms/impl-device: Add and remove connectors on hot plug
Connectors may disappear and appear on hot plugs, e.g. when a docking station is connected, so when processing a hot plug event, make sure we remove connectors that are now gone, and add new ones that have appeared since last time. Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/728 https://gitlab.gnome.org/GNOME/mutter/merge_requests/743
This commit is contained in:
parent
35776c5d29
commit
4cf828323d
@ -29,4 +29,7 @@ MetaKmsConnector * meta_kms_connector_new (MetaKmsImplDevice *impl_device,
|
||||
drmModeConnector *drm_connector,
|
||||
drmModeRes *drm_resources);
|
||||
|
||||
gboolean meta_kms_connector_is_same_as (MetaKmsConnector *connector,
|
||||
drmModeConnector *drm_connector);
|
||||
|
||||
#endif /* META_KMS_CONNECTOR_PRIVATE_H */
|
||||
|
@ -36,6 +36,7 @@ struct _MetaKmsConnector
|
||||
|
||||
uint32_t id;
|
||||
MetaConnectorType type;
|
||||
uint32_t type_id;
|
||||
char *name;
|
||||
|
||||
MetaKmsConnectorState *current_state;
|
||||
@ -562,6 +563,15 @@ make_connector_name (drmModeConnector *drm_connector)
|
||||
drm_connector->connector_type_id);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_connector_is_same_as (MetaKmsConnector *connector,
|
||||
drmModeConnector *drm_connector)
|
||||
{
|
||||
return (connector->id == drm_connector->connector_id &&
|
||||
connector->type == drm_connector->connector_type &&
|
||||
connector->type_id == drm_connector->connector_type_id);
|
||||
}
|
||||
|
||||
MetaKmsConnector *
|
||||
meta_kms_connector_new (MetaKmsImplDevice *impl_device,
|
||||
drmModeConnector *drm_connector,
|
||||
@ -573,6 +583,7 @@ meta_kms_connector_new (MetaKmsImplDevice *impl_device,
|
||||
connector->device = meta_kms_impl_device_get_device (impl_device);
|
||||
connector->id = drm_connector->connector_id;
|
||||
connector->type = (MetaConnectorType) drm_connector->connector_type;
|
||||
connector->type_id = drm_connector->connector_type_id;
|
||||
connector->name = make_connector_name (drm_connector);
|
||||
|
||||
find_property_ids (connector, impl_device, drm_connector);
|
||||
|
@ -24,4 +24,7 @@
|
||||
|
||||
MetaKmsImplDevice * meta_kms_device_get_impl_device (MetaKmsDevice *device);
|
||||
|
||||
void meta_kms_device_update_states_in_impl (MetaKmsDevice *device,
|
||||
MetaKmsUpdateStatesFlags flags);
|
||||
|
||||
#endif /* META_KMS_DEVICE_PRIVATE_H */
|
||||
|
@ -108,6 +108,31 @@ meta_kms_device_get_primary_plane_for (MetaKmsDevice *device,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_device_update_states_in_impl (MetaKmsDevice *device,
|
||||
MetaKmsUpdateStatesFlags flags)
|
||||
{
|
||||
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
||||
|
||||
meta_assert_in_kms_impl (device->kms);
|
||||
|
||||
meta_kms_impl_device_update_states (impl_device, flags);
|
||||
|
||||
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->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);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dispatch_in_impl (MetaKmsImpl *impl,
|
||||
gpointer user_data,
|
||||
|
@ -196,10 +196,28 @@ init_crtcs (MetaKmsImplDevice *impl_device,
|
||||
impl_device->crtcs = g_list_reverse (impl_device->crtcs);
|
||||
}
|
||||
|
||||
static void
|
||||
init_connectors (MetaKmsImplDevice *impl_device,
|
||||
drmModeRes *drm_resources)
|
||||
static MetaKmsConnector *
|
||||
find_existing_connector (MetaKmsImplDevice *impl_device,
|
||||
drmModeConnector *drm_connector)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = impl_device->connectors; l; l = l->next)
|
||||
{
|
||||
MetaKmsConnector *connector = l->data;
|
||||
|
||||
if (meta_kms_connector_is_same_as (connector, drm_connector))
|
||||
return connector;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
update_connectors (MetaKmsImplDevice *impl_device,
|
||||
drmModeRes *drm_resources)
|
||||
{
|
||||
GList *connectors = NULL;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < drm_resources->count_connectors; i++)
|
||||
@ -212,14 +230,19 @@ init_connectors (MetaKmsImplDevice *impl_device,
|
||||
if (!drm_connector)
|
||||
continue;
|
||||
|
||||
connector = meta_kms_connector_new (impl_device, drm_connector,
|
||||
drm_resources);
|
||||
connector = find_existing_connector (impl_device, drm_connector);
|
||||
if (connector)
|
||||
connector = g_object_ref (connector);
|
||||
else
|
||||
connector = meta_kms_connector_new (impl_device, drm_connector,
|
||||
drm_resources);
|
||||
drmModeFreeConnector (drm_connector);
|
||||
|
||||
impl_device->connectors = g_list_prepend (impl_device->connectors,
|
||||
connector);
|
||||
connectors = g_list_prepend (connectors, connector);
|
||||
}
|
||||
impl_device->connectors = g_list_reverse (impl_device->connectors);
|
||||
|
||||
g_list_free_full (impl_device->connectors, g_object_unref);
|
||||
impl_device->connectors = g_list_reverse (connectors);
|
||||
}
|
||||
|
||||
static MetaKmsPlaneType
|
||||
@ -295,13 +318,18 @@ init_planes (MetaKmsImplDevice *impl_device)
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device)
|
||||
meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsUpdateStatesFlags flags)
|
||||
{
|
||||
drmModeRes *drm_resources;
|
||||
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl_device->impl));
|
||||
|
||||
drm_resources = drmModeGetResources (impl_device->fd);
|
||||
|
||||
if (flags & META_KMS_UPDATE_STATES_FLAG_HOTPLUG)
|
||||
update_connectors (impl_device, drm_resources);
|
||||
|
||||
g_list_foreach (impl_device->crtcs, (GFunc) meta_kms_crtc_update_state,
|
||||
NULL);
|
||||
g_list_foreach (impl_device->connectors, (GFunc) meta_kms_connector_update_state,
|
||||
@ -346,9 +374,10 @@ meta_kms_impl_device_new (MetaKmsDevice *device,
|
||||
impl_device->fd = fd;
|
||||
|
||||
init_crtcs (impl_device, drm_resources);
|
||||
init_connectors (impl_device, drm_resources);
|
||||
init_planes (impl_device);
|
||||
|
||||
update_connectors (impl_device, drm_resources);
|
||||
|
||||
drmModeFreeResources (drm_resources);
|
||||
|
||||
impl_device->fd_source =
|
||||
|
@ -53,7 +53,8 @@ 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);
|
||||
void meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsUpdateStatesFlags flags);
|
||||
|
||||
int meta_kms_impl_device_close (MetaKmsImplDevice *impl_device);
|
||||
|
||||
|
@ -56,4 +56,10 @@ 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 */
|
||||
|
@ -167,7 +167,8 @@ struct _MetaKms
|
||||
G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
meta_kms_update_states_in_impl (MetaKms *kms);
|
||||
meta_kms_update_states_in_impl (MetaKms *kms,
|
||||
MetaKmsUpdateStatesFlags flags);
|
||||
|
||||
MetaKmsUpdate *
|
||||
meta_kms_ensure_pending_update (MetaKms *kms)
|
||||
@ -195,7 +196,8 @@ 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_in_impl (meta_kms_impl_get_kms (impl),
|
||||
META_KMS_UPDATE_STATES_FLAG_NONE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -450,7 +452,8 @@ meta_kms_is_waiting_for_impl_task (MetaKms *kms)
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_update_states_in_impl (MetaKms *kms)
|
||||
meta_kms_update_states_in_impl (MetaKms *kms,
|
||||
MetaKmsUpdateStatesFlags flags)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
@ -462,9 +465,8 @@ meta_kms_update_states_in_impl (MetaKms *kms)
|
||||
for (l = kms->devices; l; l = l->next)
|
||||
{
|
||||
MetaKmsDevice *device = l->data;
|
||||
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
||||
|
||||
meta_kms_impl_device_update_states (impl_device);
|
||||
meta_kms_device_update_states_in_impl (device, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,20 +475,22 @@ update_states_in_impl (MetaKmsImpl *impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
MetaKms *kms = user_data;
|
||||
MetaKms *kms = meta_kms_impl_get_kms (impl);;
|
||||
MetaKmsUpdateStatesFlags flags = GPOINTER_TO_UINT (user_data);
|
||||
|
||||
meta_kms_update_states_in_impl (kms);
|
||||
meta_kms_update_states_in_impl (kms, flags);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_kms_update_states_sync (MetaKms *kms,
|
||||
GError **error)
|
||||
meta_kms_update_states_sync (MetaKms *kms,
|
||||
MetaKmsUpdateStatesFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
return meta_kms_run_impl_task_sync (kms,
|
||||
update_states_in_impl,
|
||||
kms,
|
||||
GUINT_TO_POINTER (flags),
|
||||
error);
|
||||
}
|
||||
|
||||
@ -495,7 +499,9 @@ handle_hotplug_event (MetaKms *kms)
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
if (!meta_kms_update_states_sync (kms, &error))
|
||||
if (!meta_kms_update_states_sync (kms,
|
||||
META_KMS_UPDATE_STATES_FLAG_HOTPLUG,
|
||||
&error))
|
||||
g_warning ("Updating KMS state failed: %s", error->message);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user