mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 20:32:16 +00:00
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
This commit is contained in:
parent
2a990cc140
commit
104bdde746
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
meta_kms_impl_device_predict_states (impl_device, update);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user