diff --git a/src/backends/meta-output.c b/src/backends/meta-output.c index 432697d6d..36d8cc227 100644 --- a/src/backends/meta-output.c +++ b/src/backends/meta-output.c @@ -463,3 +463,37 @@ meta_output_class_init (MetaOutputClass *klass) G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, obj_props); } + +gboolean +meta_tile_info_equal (MetaTileInfo *a, + MetaTileInfo *b) +{ + if (a == b) + return TRUE; + + if (a->group_id != b->group_id) + return FALSE; + + if (a->flags != b->flags) + return FALSE; + + if (a->max_h_tiles != b->max_h_tiles) + return FALSE; + + if (a->max_v_tiles != b->max_v_tiles) + return FALSE; + + if (a->loc_h_tile != b->loc_h_tile) + return FALSE; + + if (a->loc_v_tile != b->loc_v_tile) + return FALSE; + + if (a->tile_w != b->tile_w) + return FALSE; + + if (a->tile_h != b->tile_h) + return FALSE; + + return TRUE; +} diff --git a/src/backends/meta-output.h b/src/backends/meta-output.h index b96c118d8..cc055881c 100644 --- a/src/backends/meta-output.h +++ b/src/backends/meta-output.h @@ -106,6 +106,10 @@ typedef struct _MetaOutputInfo MetaTileInfo tile_info; } MetaOutputInfo; +gboolean +meta_tile_info_equal (MetaTileInfo *a, + MetaTileInfo *b); + #define META_TYPE_OUTPUT_INFO (meta_output_info_get_type ()) META_EXPORT_TEST GType meta_output_info_get_type (void); diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h index 06f6e100a..e6f8b3e87 100644 --- a/src/backends/native/meta-gpu-kms.h +++ b/src/backends/native/meta-gpu-kms.h @@ -62,9 +62,6 @@ void meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms, MetaCrtcMode * meta_gpu_kms_get_mode_from_kms_mode (MetaGpuKms *gpu_kms, MetaKmsMode *kms_mode); -gboolean meta_drm_mode_equal (const drmModeModeInfo *one, - const drmModeModeInfo *two); - MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms, MetaCrtc *crtc, GClosure *flip_closure); diff --git a/src/backends/native/meta-kms-connector-private.h b/src/backends/native/meta-kms-connector-private.h index 9accf8ccd..77f9e476a 100644 --- a/src/backends/native/meta-kms-connector-private.h +++ b/src/backends/native/meta-kms-connector-private.h @@ -38,8 +38,8 @@ uint32_t meta_kms_connector_get_prop_id (MetaKmsConnector *connector, const char * meta_kms_connector_get_prop_name (MetaKmsConnector *connector, MetaKmsConnectorProp prop); -void meta_kms_connector_update_state (MetaKmsConnector *connector, - drmModeRes *drm_resources); +MetaKmsUpdateChanges meta_kms_connector_update_state (MetaKmsConnector *connector, + drmModeRes *drm_resources); void meta_kms_connector_predict_state (MetaKmsConnector *connector, MetaKmsUpdate *update); diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c index a666bb45c..01b572019 100644 --- a/src/backends/native/meta-kms-connector.c +++ b/src/backends/native/meta-kms-connector.c @@ -46,6 +46,7 @@ struct _MetaKmsConnector uint32_t type_id; char *name; + drmModeConnection connection; MetaKmsConnectorState *current_state; MetaKmsConnectorPropTable prop_table; @@ -467,18 +468,116 @@ meta_kms_connector_state_free (MetaKmsConnectorState *state) g_free (state); } -static void +G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsConnectorState, + meta_kms_connector_state_free); + +static gboolean +kms_modes_equal (GList *modes, + GList *other_modes) +{ + GList *l; + + if (g_list_length (modes) != g_list_length (other_modes)) + return FALSE; + + for (l = modes; l; l = l->next) + { + GList *k; + MetaKmsMode *mode = l->data; + + for (k = other_modes; k; k = k->next) + { + MetaKmsMode *other_mode = k->data; + + if (!meta_kms_mode_equal (mode, other_mode)) + return FALSE; + } + } + + return TRUE; +} + +static MetaKmsUpdateChanges +meta_kms_connector_state_changes (MetaKmsConnectorState *state, + MetaKmsConnectorState *new_state) +{ + if (state->current_crtc_id != new_state->current_crtc_id) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->common_possible_crtcs != new_state->common_possible_crtcs) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->common_possible_clones != new_state->common_possible_clones) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->encoder_device_idxs != new_state->encoder_device_idxs) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->width_mm != new_state->width_mm) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->height_mm != new_state->height_mm) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->has_scaling != new_state->has_scaling) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->non_desktop != new_state->non_desktop) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->subpixel_order != new_state->subpixel_order) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->suggested_x != new_state->suggested_x) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->suggested_y != new_state->suggested_y) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->hotplug_mode_update != new_state->hotplug_mode_update) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->panel_orientation_transform != + new_state->panel_orientation_transform) + return META_KMS_UPDATE_CHANGE_FULL; + + if (!meta_tile_info_equal (&state->tile_info, &new_state->tile_info)) + return META_KMS_UPDATE_CHANGE_FULL; + + if ((state->edid_data && !new_state->edid_data) || !state->edid_data || + !g_bytes_equal (state->edid_data, new_state->edid_data)) + return META_KMS_UPDATE_CHANGE_FULL; + + if (!kms_modes_equal (state->modes, new_state->modes)) + return META_KMS_UPDATE_CHANGE_FULL; + + return META_KMS_UPDATE_CHANGE_NONE; +} + +static MetaKmsUpdateChanges meta_kms_connector_read_state (MetaKmsConnector *connector, MetaKmsImplDevice *impl_device, drmModeConnector *drm_connector, drmModeRes *drm_resources) { - MetaKmsConnectorState *state; + g_autoptr (MetaKmsConnectorState) state = NULL; + g_autoptr (MetaKmsConnectorState) current_state = NULL; + MetaKmsUpdateChanges connector_changes; + MetaKmsUpdateChanges changes; - g_clear_pointer (&connector->current_state, meta_kms_connector_state_free); + current_state = g_steal_pointer (&connector->current_state); + changes = META_KMS_UPDATE_CHANGE_NONE; - if (!drm_connector || drm_connector->connection != DRM_MODE_CONNECTED) - return; + if (drm_connector->connection != DRM_MODE_CONNECTED) + { + if (drm_connector->connection != connector->connection) + { + connector->connection = drm_connector->connection; + changes |= META_KMS_UPDATE_CHANGE_FULL; + } + + return changes; + } state = meta_kms_connector_state_new (); @@ -495,26 +594,54 @@ meta_kms_connector_read_state (MetaKmsConnector *connector, state_set_crtc_state (state, drm_connector, impl_device, drm_resources); - connector->current_state = state; + if (drm_connector->connection != connector->connection) + { + connector->connection = drm_connector->connection; + changes |= META_KMS_UPDATE_CHANGE_FULL; + } - sync_fd_held (connector, impl_device); + if (!current_state) + connector_changes = META_KMS_UPDATE_CHANGE_FULL; + else + connector_changes = meta_kms_connector_state_changes (current_state, state); + + if (connector_changes == META_KMS_UPDATE_CHANGE_NONE) + { + connector->current_state = g_steal_pointer (¤t_state); + } + else + { + connector->current_state = g_steal_pointer (&state); + changes |= connector_changes; + } + + if (changes != META_KMS_UPDATE_CHANGE_NONE) + sync_fd_held (connector, impl_device); + + return changes; } -void +MetaKmsUpdateChanges meta_kms_connector_update_state (MetaKmsConnector *connector, drmModeRes *drm_resources) { MetaKmsImplDevice *impl_device; drmModeConnector *drm_connector; + MetaKmsUpdateChanges changes; impl_device = meta_kms_device_get_impl_device (connector->device); drm_connector = drmModeGetConnector (meta_kms_impl_device_get_fd (impl_device), connector->id); - meta_kms_connector_read_state (connector, impl_device, - drm_connector, - drm_resources); - if (drm_connector) - drmModeFreeConnector (drm_connector); + + if (!drm_connector) + return META_KMS_UPDATE_CHANGE_FULL; + + changes = meta_kms_connector_read_state (connector, impl_device, + drm_connector, + drm_resources); + drmModeFreeConnector (drm_connector); + + return changes; } void @@ -651,6 +778,7 @@ meta_kms_connector_new (MetaKmsImplDevice *impl_device, { MetaKmsConnector *connector; + g_assert (drm_connector); connector = g_object_new (META_TYPE_KMS_CONNECTOR, NULL); connector->device = meta_kms_impl_device_get_device (impl_device); connector->id = drm_connector->connector_id; diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h index 60c5fd309..f91731a00 100644 --- a/src/backends/native/meta-kms-crtc-private.h +++ b/src/backends/native/meta-kms-crtc-private.h @@ -23,6 +23,7 @@ #include #include "backends/native/meta-kms-crtc.h" +#include "backends/native/meta-kms-update-private.h" typedef enum _MetaKmsCrtcProp { @@ -37,7 +38,7 @@ MetaKmsCrtc * meta_kms_crtc_new (MetaKmsImplDevice *impl_device, int idx, GError **error); -void meta_kms_crtc_update_state (MetaKmsCrtc *crtc); +MetaKmsUpdateChanges meta_kms_crtc_update_state (MetaKmsCrtc *crtc); void meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, MetaKmsUpdate *update); diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c index 51d040b44..3e0506026 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -94,32 +94,62 @@ meta_kms_crtc_is_active (MetaKmsCrtc *crtc) static void read_gamma_state (MetaKmsCrtc *crtc, + MetaKmsCrtcState *crtc_state, MetaKmsImplDevice *impl_device, drmModeCrtc *drm_crtc) { - MetaKmsCrtcState *current_state = &crtc->current_state; - - if (current_state->gamma.size != drm_crtc->gamma_size) + if (crtc_state->gamma.size != drm_crtc->gamma_size) { - current_state->gamma.size = drm_crtc->gamma_size; + crtc_state->gamma.size = drm_crtc->gamma_size; - current_state->gamma.red = g_realloc_n (current_state->gamma.red, - drm_crtc->gamma_size, - sizeof (uint16_t)); - current_state->gamma.green = g_realloc_n (current_state->gamma.green, - drm_crtc->gamma_size, - sizeof (uint16_t)); - current_state->gamma.blue = g_realloc_n (current_state->gamma.blue, - drm_crtc->gamma_size, - sizeof (uint16_t)); + crtc_state->gamma.red = g_realloc_n (crtc_state->gamma.red, + drm_crtc->gamma_size, + sizeof (uint16_t)); + crtc_state->gamma.green = g_realloc_n (crtc_state->gamma.green, + drm_crtc->gamma_size, + sizeof (uint16_t)); + crtc_state->gamma.blue = g_realloc_n (crtc_state->gamma.blue, + drm_crtc->gamma_size, + sizeof (uint16_t)); } drmModeCrtcGetGamma (meta_kms_impl_device_get_fd (impl_device), crtc->id, - current_state->gamma.size, - current_state->gamma.red, - current_state->gamma.green, - current_state->gamma.blue); + crtc_state->gamma.size, + crtc_state->gamma.red, + crtc_state->gamma.green, + crtc_state->gamma.blue); +} + +static MetaKmsUpdateChanges +meta_kms_crtc_state_changes (MetaKmsCrtcState *state, + MetaKmsCrtcState *other_state) +{ + if (!meta_rectangle_equal (&state->rect, &other_state->rect)) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->is_drm_mode_valid != other_state->is_drm_mode_valid) + return META_KMS_UPDATE_CHANGE_FULL; + + if (!meta_drm_mode_equal (&state->drm_mode, &other_state->drm_mode)) + return META_KMS_UPDATE_CHANGE_FULL; + + if (state->gamma.size != other_state->gamma.size) + return META_KMS_UPDATE_CHANGE_GAMMA; + + if (memcmp (state->gamma.blue, other_state->gamma.blue, + state->gamma.size * sizeof (uint16_t)) != 0) + return META_KMS_UPDATE_CHANGE_GAMMA; + + if (memcmp (state->gamma.green, other_state->gamma.green, + state->gamma.size * sizeof (uint16_t)) != 0) + return META_KMS_UPDATE_CHANGE_GAMMA; + + if (memcmp (state->gamma.red, other_state->gamma.red, + state->gamma.size * sizeof (uint16_t)) != 0) + return META_KMS_UPDATE_CHANGE_GAMMA; + + return META_KMS_UPDATE_CHANGE_NONE; } static int @@ -141,23 +171,35 @@ find_prop_idx (MetaKmsProp *prop, } static void +clear_gamma_state (MetaKmsCrtcState *crtc_state) +{ + crtc_state->gamma.size = 0; + g_clear_pointer (&crtc_state->gamma.red, g_free); + g_clear_pointer (&crtc_state->gamma.green, g_free); + g_clear_pointer (&crtc_state->gamma.blue, g_free); +} + +static MetaKmsUpdateChanges meta_kms_crtc_read_state (MetaKmsCrtc *crtc, MetaKmsImplDevice *impl_device, drmModeCrtc *drm_crtc, drmModeObjectProperties *drm_props) { + MetaKmsCrtcState crtc_state = {0}; + MetaKmsUpdateChanges changes = META_KMS_UPDATE_CHANGE_NONE; MetaKmsProp *active_prop; int active_idx; - crtc->current_state.rect = (MetaRectangle) { + crtc_state.rect = (MetaRectangle) { .x = drm_crtc->x, .y = drm_crtc->y, .width = drm_crtc->width, .height = drm_crtc->height, }; - crtc->current_state.is_drm_mode_valid = drm_crtc->mode_valid; - crtc->current_state.drm_mode = drm_crtc->mode; + crtc_state.is_drm_mode_valid = drm_crtc->mode_valid; + crtc_state.drm_mode = drm_crtc->mode; + crtc_state.gamma.size = 0; active_prop = &crtc->prop_table.props[META_KMS_CRTC_PROP_ACTIVE]; if (active_prop->prop_id) @@ -165,13 +207,36 @@ meta_kms_crtc_read_state (MetaKmsCrtc *crtc, active_idx = find_prop_idx (active_prop, drm_props->props, drm_props->count_props); - crtc->current_state.is_active = !!drm_props->prop_values[active_idx]; + crtc_state.is_active = !!drm_props->prop_values[active_idx]; } else { - crtc->current_state.is_active = drm_crtc->mode_valid; + crtc_state.is_active = drm_crtc->mode_valid; } + if (crtc_state.is_active != crtc->current_state.is_active) + { + changes |= META_KMS_UPDATE_CHANGE_FULL; + } + else if (!crtc_state.is_active) + { + clear_gamma_state (&crtc_state); + return changes; + } + + read_gamma_state (crtc, &crtc_state, impl_device, drm_crtc); + + changes |= meta_kms_crtc_state_changes (&crtc->current_state, &crtc_state); + + if (changes == META_KMS_UPDATE_CHANGE_NONE) + { + clear_gamma_state (&crtc_state); + return changes; + } + + clear_gamma_state (&crtc->current_state); + crtc->current_state = crtc_state; + meta_topic (META_DEBUG_KMS, "Read CRTC %u state: active: %d, mode: %s", crtc->id, crtc->current_state.is_active, @@ -179,13 +244,14 @@ meta_kms_crtc_read_state (MetaKmsCrtc *crtc, ? crtc->current_state.drm_mode.name : "(nil)"); - read_gamma_state (crtc, impl_device, drm_crtc); + return changes; } -void +MetaKmsUpdateChanges meta_kms_crtc_update_state (MetaKmsCrtc *crtc) { MetaKmsImplDevice *impl_device; + MetaKmsUpdateChanges changes; int fd; drmModeCrtc *drm_crtc; drmModeObjectProperties *drm_props; @@ -201,23 +267,17 @@ meta_kms_crtc_update_state (MetaKmsCrtc *crtc) crtc->current_state.is_active = FALSE; crtc->current_state.rect = (MetaRectangle) { }; crtc->current_state.is_drm_mode_valid = FALSE; + changes = META_KMS_UPDATE_CHANGE_FULL; goto out; } - meta_kms_crtc_read_state (crtc, impl_device, drm_crtc, drm_props); + changes = meta_kms_crtc_read_state (crtc, impl_device, drm_crtc, drm_props); out: g_clear_pointer (&drm_props, drmModeFreeObjectProperties); g_clear_pointer (&drm_crtc, drmModeFreeCrtc); -} -static void -clear_gamma_state (MetaKmsCrtc *crtc) -{ - crtc->current_state.gamma.size = 0; - g_clear_pointer (&crtc->current_state.gamma.red, g_free); - g_clear_pointer (&crtc->current_state.gamma.green, g_free); - g_clear_pointer (&crtc->current_state.gamma.blue, g_free); + return changes; } void @@ -270,7 +330,7 @@ meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, if (gamma->crtc != crtc) continue; - clear_gamma_state (crtc); + clear_gamma_state (&crtc->current_state); crtc->current_state.gamma.size = gamma->size; crtc->current_state.gamma.red = g_memdup2 (gamma->red, gamma->size * sizeof (uint16_t)); @@ -380,7 +440,7 @@ meta_kms_crtc_finalize (GObject *object) { MetaKmsCrtc *crtc = META_KMS_CRTC (object); - clear_gamma_state (crtc); + clear_gamma_state (&crtc->current_state); G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object); } @@ -388,6 +448,7 @@ meta_kms_crtc_finalize (GObject *object) static void meta_kms_crtc_init (MetaKmsCrtc *crtc) { + crtc->current_state.gamma.size = 0; } static void diff --git a/src/backends/native/meta-kms-device-private.h b/src/backends/native/meta-kms-device-private.h index 41e05a2f7..831f7820a 100644 --- a/src/backends/native/meta-kms-device-private.h +++ b/src/backends/native/meta-kms-device-private.h @@ -21,10 +21,11 @@ #define META_KMS_DEVICE_PRIVATE_H #include "backends/native/meta-kms-types.h" +#include "backends/native/meta-kms-update-private.h" MetaKmsImplDevice * meta_kms_device_get_impl_device (MetaKmsDevice *device); -void meta_kms_device_update_states_in_impl (MetaKmsDevice *device); +MetaKmsUpdateChanges meta_kms_device_update_states_in_impl (MetaKmsDevice *device); void meta_kms_device_predict_states_in_impl (MetaKmsDevice *device, MetaKmsUpdate *update); diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c index b4d3e5802..beb2360e6 100644 --- a/src/backends/native/meta-kms-device.c +++ b/src/backends/native/meta-kms-device.c @@ -186,15 +186,19 @@ meta_kms_device_get_fallback_modes (MetaKmsDevice *device) return device->fallback_modes; } -void +MetaKmsUpdateChanges meta_kms_device_update_states_in_impl (MetaKmsDevice *device) { MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); + MetaKmsUpdateChanges changes; 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); + changes = meta_kms_impl_device_update_states (impl_device); + + if (changes == META_KMS_UPDATE_CHANGE_NONE) + return changes; g_list_free (device->crtcs); device->crtcs = meta_kms_impl_device_copy_crtcs (impl_device); @@ -204,6 +208,8 @@ meta_kms_device_update_states_in_impl (MetaKmsDevice *device) g_list_free (device->planes); device->planes = meta_kms_impl_device_copy_planes (impl_device); + + return changes; } void diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index e08e672e5..e616ffd2a 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -36,7 +36,6 @@ #include "backends/native/meta-kms-plane-private.h" #include "backends/native/meta-kms-plane.h" #include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update-private.h" #include "meta-default-modes.h" #include "meta-private-enum-types.h" @@ -390,13 +389,14 @@ find_existing_connector (MetaKmsImplDevice *impl_device, return NULL; } -static void +static MetaKmsUpdateChanges update_connectors (MetaKmsImplDevice *impl_device, drmModeRes *drm_resources) { MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); - GList *connectors = NULL; + g_autolist (MetaKmsConnector) connectors = NULL; + gboolean needs_full_change = FALSE; unsigned int i; int fd; @@ -413,17 +413,28 @@ update_connectors (MetaKmsImplDevice *impl_device, connector = find_existing_connector (impl_device, drm_connector); if (connector) - connector = g_object_ref (connector); + { + connector = g_object_ref (connector); + } else - connector = meta_kms_connector_new (impl_device, drm_connector, - drm_resources); + { + connector = meta_kms_connector_new (impl_device, drm_connector, + drm_resources); + needs_full_change = TRUE; + } + drmModeFreeConnector (drm_connector); connectors = g_list_prepend (connectors, connector); } + if (!needs_full_change) + return META_KMS_UPDATE_CHANGE_NONE; + g_list_free_full (priv->connectors, g_object_unref); - priv->connectors = g_list_reverse (connectors); + priv->connectors = g_list_reverse (g_steal_pointer (&connectors)); + + return META_KMS_UPDATE_CHANGE_FULL; } static MetaKmsPlaneType @@ -690,7 +701,7 @@ clear_latched_fd_hold (MetaKmsImplDevice *impl_device) } } -void +MetaKmsUpdateChanges meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device) { MetaKmsImplDevicePrivate *priv = @@ -698,6 +709,8 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device) g_autoptr (GError) error = NULL; int fd; drmModeRes *drm_resources; + MetaKmsUpdateChanges changes; + GList *l; meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); @@ -720,20 +733,25 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device) goto err; } - update_connectors (impl_device, drm_resources); + changes = update_connectors (impl_device, drm_resources); + + for (l = priv->crtcs; l; l = l->next) + changes |= meta_kms_crtc_update_state (META_KMS_CRTC (l->data)); + + for (l = priv->connectors; l; l = l->next) + changes |= meta_kms_connector_update_state (META_KMS_CONNECTOR (l->data), + drm_resources); - g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_update_state, - NULL); - g_list_foreach (priv->connectors, (GFunc) meta_kms_connector_update_state, - drm_resources); drmModeFreeResources (drm_resources); - return; + return changes; err: g_clear_list (&priv->planes, g_object_unref); g_clear_list (&priv->crtcs, g_object_unref); g_clear_list (&priv->connectors, g_object_unref); + + return META_KMS_UPDATE_CHANGE_FULL; } void diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h index e77024ecd..caddae3c1 100644 --- a/src/backends/native/meta-kms-impl-device.h +++ b/src/backends/native/meta-kms-impl-device.h @@ -135,7 +135,7 @@ void meta_kms_impl_device_hold_fd (MetaKmsImplDevice *impl_device); void meta_kms_impl_device_unhold_fd (MetaKmsImplDevice *impl_device); -void meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device); +MetaKmsUpdateChanges meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device); void meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update); diff --git a/src/backends/native/meta-kms-mode.c b/src/backends/native/meta-kms-mode.c index 7094cd0da..a52451620 100644 --- a/src/backends/native/meta-kms-mode.c +++ b/src/backends/native/meta-kms-mode.c @@ -73,7 +73,7 @@ meta_kms_mode_get_drm_mode (MetaKmsMode *mode) return &mode->drm_mode; } -static gboolean +gboolean meta_drm_mode_equal (const drmModeModeInfo *one, const drmModeModeInfo *two) { diff --git a/src/backends/native/meta-kms-mode.h b/src/backends/native/meta-kms-mode.h index 40e844796..f9a4477a4 100644 --- a/src/backends/native/meta-kms-mode.h +++ b/src/backends/native/meta-kms-mode.h @@ -42,6 +42,9 @@ const drmModeModeInfo * meta_kms_mode_get_drm_mode (MetaKmsMode *mode); gboolean meta_kms_mode_equal (MetaKmsMode *mode, MetaKmsMode *other_mode); +gboolean meta_drm_mode_equal (const drmModeModeInfo *one, + const drmModeModeInfo *two); + unsigned int meta_kms_mode_hash (MetaKmsMode *mode); #endif /* META_KMS_MODE_H */ diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h index 5786ff51f..64045ef45 100644 --- a/src/backends/native/meta-kms-types.h +++ b/src/backends/native/meta-kms-types.h @@ -64,6 +64,13 @@ typedef enum _MetaKmsDeviceFlag META_KMS_DEVICE_FLAG_NO_MODE_SETTING = 1 << 4, } MetaKmsDeviceFlag; +typedef enum _MetaKmsUpdateChanges +{ + META_KMS_UPDATE_CHANGE_NONE = 0, + META_KMS_UPDATE_CHANGE_GAMMA = 1 << 0, + META_KMS_UPDATE_CHANGE_FULL = -1, +} MetaKmsUpdateChanges; + typedef enum _MetaKmsPlaneType MetaKmsPlaneType; typedef enum _MetaKmsPropType diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 70feccc22..6676db3e7 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -29,6 +29,8 @@ #include "backends/native/meta-udev.h" #include "cogl/cogl.h" +#include "meta-private-enum-types.h" + /** * SECTION:kms * @short description: KMS abstraction @@ -563,17 +565,25 @@ 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) +static MetaKmsUpdateChanges +meta_kms_update_states_in_impl (MetaKms *kms) { + MetaKmsUpdateChanges changes = META_KMS_UPDATE_CHANGE_NONE; + GList *l; + COGL_TRACE_BEGIN_SCOPED (MetaKmsUpdateStates, "KMS (update states)"); meta_assert_in_kms_impl (kms); - g_list_foreach (kms->devices, - (GFunc) meta_kms_device_update_states_in_impl, - NULL); + for (l = kms->devices; l; l = l->next) + { + MetaKmsDevice *kms_device = META_KMS_DEVICE (l->data); + + changes |= meta_kms_device_update_states_in_impl (kms_device); + } + + return changes; } static gpointer @@ -583,30 +593,27 @@ update_states_in_impl (MetaKmsImpl *impl, { MetaKms *kms = meta_kms_impl_get_kms (impl); - meta_kms_update_states_in_impl (kms); - - return GINT_TO_POINTER (TRUE); + return GUINT_TO_POINTER (meta_kms_update_states_in_impl (kms)); } -static gboolean -meta_kms_update_states_sync (MetaKms *kms, - GError **error) +static MetaKmsUpdateChanges +meta_kms_update_states_sync (MetaKms *kms) { gpointer ret; - ret = meta_kms_run_impl_task_sync (kms, update_states_in_impl, NULL, error); - return GPOINTER_TO_INT (ret); + ret = meta_kms_run_impl_task_sync (kms, update_states_in_impl, NULL, NULL); + return GPOINTER_TO_UINT (ret); } static void handle_hotplug_event (MetaKms *kms) { - g_autoptr (GError) error = NULL; + MetaKmsUpdateChanges changes; - if (!meta_kms_update_states_sync (kms, &error)) - g_warning ("Updating KMS state failed: %s", error->message); + changes = meta_kms_update_states_sync (kms); - g_signal_emit (kms, signals[RESOURCES_CHANGED], 0); + if (changes != META_KMS_UPDATE_CHANGE_NONE) + g_signal_emit (kms, signals[RESOURCES_CHANGED], 0, changes); } void @@ -750,5 +757,6 @@ meta_kms_class_init (MetaKmsClass *klass) G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); + G_TYPE_NONE, 1, + META_TYPE_KMS_UPDATE_CHANGES); } diff --git a/src/backends/native/meta-monitor-manager-native.c b/src/backends/native/meta-monitor-manager-native.c index 2d598af12..d76972df8 100644 --- a/src/backends/native/meta-monitor-manager-native.c +++ b/src/backends/native/meta-monitor-manager-native.c @@ -508,9 +508,12 @@ handle_hotplug_event (MetaMonitorManager *manager) } static void -on_kms_resources_changed (MetaKms *kms, - MetaMonitorManager *manager) +on_kms_resources_changed (MetaKms *kms, + MetaKmsUpdateChanges changes, + MetaMonitorManager *manager) { + g_assert (changes != META_KMS_UPDATE_CHANGE_NONE); + handle_hotplug_event (manager); }