Compare commits

...

3 Commits

Author SHA1 Message Date
9582f7b207 monitor-manager/kms: Get hotplug events from MetaKms
This makes it clearer that MetaMonitorManagerKms keeps updated as
MetaKms updates its state.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/743
2019-09-03 19:14:47 +02:00
5fa38f4cd5 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 has appeared
since last time.

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

https://gitlab.gnome.org/GNOME/mutter/merge_requests/743
2019-09-03 19:14:47 +02:00
0ae31a45ab kms: Add assert to check that the main thread is blocked on impl task
This is so that we can have code in impl tasks that pokes at the main
context objects.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/743
2019-09-03 19:14:45 +02:00
10 changed files with 149 additions and 46 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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,

View File

@ -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 =

View File

@ -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);

View File

@ -55,9 +55,13 @@ GSource * meta_kms_register_fd_in_impl (MetaKms *kms,
gboolean meta_kms_in_impl_task (MetaKms *kms);
gboolean meta_kms_is_waiting_for_impl_task (MetaKms *kms);
#define meta_assert_in_kms_impl(kms) \
g_assert (meta_kms_in_impl_task (kms))
#define meta_assert_not_in_kms_impl(kms) \
g_assert (!meta_kms_in_impl_task (kms))
#define meta_assert_is_waiting_for_kms_impl_task(kms) \
g_assert (meta_kms_is_waiting_for_impl_task (kms))
#endif /* META_KMS_PRIVATE_H */

View File

@ -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 */

View File

@ -119,6 +119,15 @@
*
*/
enum
{
RESOURCES_CHANGED,
N_SIGNALS
};
static int signals[N_SIGNALS];
typedef struct _MetaKmsCallbackData
{
MetaKmsCallback callback;
@ -154,6 +163,7 @@ struct _MetaKms
MetaKmsImpl *impl;
gboolean in_impl_task;
gboolean waiting_for_impl_task;
GList *devices;
@ -166,7 +176,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)
@ -194,7 +205,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;
}
@ -322,7 +334,9 @@ meta_kms_run_impl_task_sync (MetaKms *kms,
gboolean ret;
kms->in_impl_task = TRUE;
kms->waiting_for_impl_task = TRUE;
ret = func (kms->impl, user_data, error);
kms->waiting_for_impl_task = FALSE;
kms->in_impl_task = FALSE;
return ret;
@ -440,8 +454,15 @@ meta_kms_in_impl_task (MetaKms *kms)
return kms->in_impl_task;
}
gboolean
meta_kms_is_waiting_for_impl_task (MetaKms *kms)
{
return kms->waiting_for_impl_task;
}
static void
meta_kms_update_states_in_impl (MetaKms *kms)
meta_kms_update_states_in_impl (MetaKms *kms,
MetaKmsUpdateStatesFlags flags)
{
GList *l;
@ -453,9 +474,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);
}
}
@ -464,20 +484,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);
}
@ -486,8 +508,12 @@ 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);
g_signal_emit (kms, signals[RESOURCES_CHANGED], 0);
}
static void
@ -590,4 +616,12 @@ meta_kms_class_init (MetaKmsClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_kms_finalize;
signals[RESOURCES_CHANGED] =
g_signal_new ("resources-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}

View File

@ -75,8 +75,7 @@ struct _MetaMonitorManagerKms
{
MetaMonitorManager parent_instance;
guint hotplug_handler_id;
guint removed_handler_id;
gulong kms_resources_changed_handler_id;
};
struct _MetaMonitorManagerKmsClass
@ -479,16 +478,8 @@ handle_hotplug_event (MetaMonitorManager *manager)
}
static void
on_udev_hotplug (MetaUdev *udev,
MetaMonitorManager *manager)
{
handle_hotplug_event (manager);
}
static void
on_udev_device_removed (MetaUdev *udev,
GUdevDevice *device,
MetaMonitorManager *manager)
on_kms_resources_changed (MetaKms *kms,
MetaMonitorManager *manager)
{
handle_hotplug_event (manager);
}
@ -498,14 +489,12 @@ meta_monitor_manager_kms_connect_hotplug_handler (MetaMonitorManagerKms *manager
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
MetaUdev *udev = meta_backend_native_get_udev (META_BACKEND_NATIVE (backend));
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
manager_kms->hotplug_handler_id =
g_signal_connect_after (udev, "hotplug",
G_CALLBACK (on_udev_hotplug), manager);
manager_kms->removed_handler_id =
g_signal_connect_after (udev, "device-removed",
G_CALLBACK (on_udev_device_removed), manager);
manager_kms->kms_resources_changed_handler_id =
g_signal_connect (kms, "resources-changed",
G_CALLBACK (on_kms_resources_changed), manager);
}
static void
@ -513,12 +502,10 @@ meta_monitor_manager_kms_disconnect_hotplug_handler (MetaMonitorManagerKms *mana
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
MetaUdev *udev = meta_backend_native_get_udev (META_BACKEND_NATIVE (backend));
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
g_signal_handler_disconnect (udev, manager_kms->hotplug_handler_id);
manager_kms->hotplug_handler_id = 0;
g_signal_handler_disconnect (udev, manager_kms->removed_handler_id);
manager_kms->removed_handler_id = 0;
g_clear_signal_handler (&manager_kms->kms_resources_changed_handler_id, kms);
}
void