diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c index 1877903c4..8ac7fb969 100644 --- a/src/backends/native/meta-crtc-kms.c +++ b/src/backends/native/meta-crtc-kms.c @@ -494,27 +494,25 @@ meta_crtc_destroy_notify (MetaCrtc *crtc) } MetaCrtc * -meta_create_kms_crtc (MetaGpuKms *gpu_kms, - MetaKmsCrtc *kms_crtc, - drmModeCrtc *drm_crtc) +meta_create_kms_crtc (MetaGpuKms *gpu_kms, + MetaKmsCrtc *kms_crtc) { MetaGpu *gpu = META_GPU (gpu_kms); MetaCrtc *crtc; MetaCrtcKms *crtc_kms; + const MetaKmsCrtcState *crtc_state; + + crtc_state = meta_kms_crtc_get_current_state (kms_crtc); crtc = g_object_new (META_TYPE_CRTC, NULL); - crtc->gpu = gpu; crtc->crtc_id = meta_kms_crtc_get_id (kms_crtc); - crtc->rect.x = drm_crtc->x; - crtc->rect.y = drm_crtc->y; - crtc->rect.width = drm_crtc->width; - crtc->rect.height = drm_crtc->height; + crtc->rect = crtc_state->rect; crtc->is_dirty = FALSE; crtc->transform = META_MONITOR_TRANSFORM_NORMAL; crtc->all_transforms = ALL_TRANSFORMS_MASK; - if (drm_crtc->mode_valid) + if (crtc_state->is_drm_mode_valid) { GList *l; @@ -522,7 +520,7 @@ meta_create_kms_crtc (MetaGpuKms *gpu_kms, { MetaCrtcMode *mode = l->data; - if (meta_drm_mode_equal (&drm_crtc->mode, mode->driver_private)) + if (meta_drm_mode_equal (&crtc_state->drm_mode, mode->driver_private)) { crtc->current_mode = mode; break; diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h index 8e09614c9..3be1d5db8 100644 --- a/src/backends/native/meta-crtc-kms.h +++ b/src/backends/native/meta-crtc-kms.h @@ -55,8 +55,7 @@ gboolean meta_crtc_kms_supports_format (MetaCrtc *crtc, uint32_t drm_format); -MetaCrtc * meta_create_kms_crtc (MetaGpuKms *gpu_kms, - MetaKmsCrtc *kms_crtc, - drmModeCrtc *drm_crtc); +MetaCrtc * meta_create_kms_crtc (MetaGpuKms *gpu_kms, + MetaKmsCrtc *kms_crtc); #endif /* META_CRTC_KMS_H */ diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c index 7b186de80..09b1c87d7 100644 --- a/src/backends/native/meta-gpu-kms.c +++ b/src/backends/native/meta-gpu-kms.c @@ -703,8 +703,7 @@ init_modes (MetaGpuKms *gpu_kms, } static void -init_crtcs (MetaGpuKms *gpu_kms, - MetaKmsResources *resources) +init_crtcs (MetaGpuKms *gpu_kms) { MetaGpu *gpu = META_GPU (gpu_kms); MetaKmsDevice *kms_device = gpu_kms->kms_device; @@ -716,15 +715,9 @@ init_crtcs (MetaGpuKms *gpu_kms, for (l = meta_kms_device_get_crtcs (kms_device); l; l = l->next) { MetaKmsCrtc *kms_crtc = l->data; - int crtc_idx; - drmModeCrtc *drm_crtc; MetaCrtc *crtc; - crtc_idx = meta_kms_crtc_get_idx (kms_crtc); - drm_crtc = drmModeGetCrtc (gpu_kms->fd, - resources->resources->crtcs[crtc_idx]); - crtc = meta_create_kms_crtc (gpu_kms, kms_crtc, drm_crtc); - drmModeFreeCrtc (drm_crtc); + crtc = meta_create_kms_crtc (gpu_kms, kms_crtc); crtcs = g_list_append (crtcs, crtc); } @@ -868,7 +861,7 @@ meta_gpu_kms_read_current (MetaGpu *gpu, init_connectors (gpu_kms, resources.resources); init_modes (gpu_kms, resources.resources); - init_crtcs (gpu_kms, &resources); + init_crtcs (gpu_kms); init_outputs (gpu_kms, &resources); init_frame_clock (gpu_kms); diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h index ad4492bf1..41db399e6 100644 --- a/src/backends/native/meta-kms-crtc-private.h +++ b/src/backends/native/meta-kms-crtc-private.h @@ -28,4 +28,6 @@ MetaKmsCrtc * meta_kms_crtc_new (MetaKmsImplDevice *impl_device, drmModeCrtc *drm_crtc, int idx); +void meta_kms_crtc_update_state (MetaKmsCrtc *crtc); + #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 73ae8ab9c..910a5a84a 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -22,6 +22,7 @@ #include "backends/native/meta-kms-crtc.h" #include "backends/native/meta-kms-crtc-private.h" +#include "backends/native/meta-kms-device-private.h" #include "backends/native/meta-kms-impl-device.h" struct _MetaKmsCrtc @@ -32,6 +33,8 @@ struct _MetaKmsCrtc uint32_t id; int idx; + + MetaKmsCrtcState current_state; }; G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT) @@ -42,6 +45,12 @@ meta_kms_crtc_get_device (MetaKmsCrtc *crtc) return crtc->device; } +const MetaKmsCrtcState * +meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc) +{ + return &crtc->current_state; +} + uint32_t meta_kms_crtc_get_id (MetaKmsCrtc *crtc) { @@ -54,6 +63,36 @@ meta_kms_crtc_get_idx (MetaKmsCrtc *crtc) return crtc->idx; } +static void +meta_kms_crtc_read_state (MetaKmsCrtc *crtc, + MetaKmsImplDevice *impl_device, + drmModeCrtc *drm_crtc) +{ + crtc->current_state = (MetaKmsCrtcState) { + .rect = { + .x = drm_crtc->x, + .y = drm_crtc->y, + .width = drm_crtc->width, + .height = drm_crtc->height, + }, + .is_drm_mode_valid = drm_crtc->mode_valid, + .drm_mode = drm_crtc->mode, + }; +} + +void +meta_kms_crtc_update_state (MetaKmsCrtc *crtc) +{ + MetaKmsImplDevice *impl_device; + drmModeCrtc *drm_crtc; + + impl_device = meta_kms_device_get_impl_device (crtc->device); + drm_crtc = drmModeGetCrtc (meta_kms_impl_device_get_fd (impl_device), + crtc->id); + meta_kms_crtc_read_state (crtc, impl_device, drm_crtc); + drmModeFreeCrtc (drm_crtc); +} + MetaKmsCrtc * meta_kms_crtc_new (MetaKmsImplDevice *impl_device, drmModeCrtc *drm_crtc, diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h index 12eda39f2..9d0ceadd9 100644 --- a/src/backends/native/meta-kms-crtc.h +++ b/src/backends/native/meta-kms-crtc.h @@ -25,6 +25,18 @@ #include #include "backends/native/meta-kms-types.h" +#include "meta/boxes.h" + +typedef struct _MetaKmsCrtcState +{ + MetaRectangle rect; + gboolean is_drm_mode_valid; + drmModeModeInfo drm_mode; + + uint32_t common_possible_crtcs; + uint32_t common_possible_clones; + uint32_t encoder_device_idxs; +} MetaKmsCrtcState; #define META_TYPE_KMS_CRTC (meta_kms_crtc_get_type ()) G_DECLARE_FINAL_TYPE (MetaKmsCrtc, meta_kms_crtc, @@ -33,6 +45,8 @@ G_DECLARE_FINAL_TYPE (MetaKmsCrtc, meta_kms_crtc, MetaKmsDevice * meta_kms_crtc_get_device (MetaKmsCrtc *crtc); +const MetaKmsCrtcState * meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc); + uint32_t meta_kms_crtc_get_id (MetaKmsCrtc *crtc); int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc); diff --git a/src/backends/native/meta-kms-device-private.h b/src/backends/native/meta-kms-device-private.h new file mode 100644 index 000000000..0d4f4e341 --- /dev/null +++ b/src/backends/native/meta-kms-device-private.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2019 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef META_KMS_DEVICE_PRIVATE_H +#define META_KMS_DEVICE_PRIVATE_H + +#include "backends/native/meta-kms-types.h" + +MetaKmsImplDevice * meta_kms_device_get_impl_device (MetaKmsDevice *device); + +#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 c168bad80..6f5caf02d 100644 --- a/src/backends/native/meta-kms-device.c +++ b/src/backends/native/meta-kms-device.c @@ -19,6 +19,7 @@ #include "config.h" +#include "backends/native/meta-kms-device-private.h" #include "backends/native/meta-kms-device.h" #include "backends/native/meta-backend-native.h" @@ -44,6 +45,12 @@ struct _MetaKmsDevice G_DEFINE_TYPE (MetaKmsDevice, meta_kms_device, G_TYPE_OBJECT); +MetaKmsImplDevice * +meta_kms_device_get_impl_device (MetaKmsDevice *device) +{ + return device->impl_device; +} + int meta_kms_device_leak_fd (MetaKmsDevice *device) { diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index d35f2300b..b849a138d 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -216,6 +216,15 @@ init_planes (MetaKmsImplDevice *impl_device) impl_device->planes = g_list_reverse (impl_device->planes); } +void +meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device) +{ + meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl_device->impl)); + + g_list_foreach (impl_device->crtcs, (GFunc) meta_kms_crtc_update_state, + NULL); +} + 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 26d946760..974915c3d 100644 --- a/src/backends/native/meta-kms-impl-device.h +++ b/src/backends/native/meta-kms-impl-device.h @@ -49,6 +49,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); + int meta_kms_impl_device_close (MetaKmsImplDevice *impl_device); MetaKmsImplDevice * meta_kms_impl_device_new (MetaKmsDevice *device, diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 40ce2e8ea..4fd9c5ee4 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -21,8 +21,11 @@ #include "backends/native/meta-kms-private.h" +#include "backends/native/meta-backend-native.h" +#include "backends/native/meta-kms-device-private.h" #include "backends/native/meta-kms-impl.h" #include "backends/native/meta-kms-impl-simple.h" +#include "backends/native/meta-udev.h" struct _MetaKms { @@ -30,6 +33,8 @@ struct _MetaKms MetaBackend *backend; + guint hotplug_handler_id; + MetaKmsImpl *impl; gboolean in_impl_task; @@ -59,6 +64,45 @@ meta_kms_in_impl_task (MetaKms *kms) return kms->in_impl_task; } +static gboolean +update_states_in_impl (MetaKmsImpl *impl, + gpointer user_data, + GError **error) +{ + MetaKms *kms = user_data; + GList *l; + + 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); + } + + return TRUE; +} + +static gboolean +meta_kms_update_states_sync (MetaKms *kms, + GError **error) +{ + return meta_kms_run_impl_task_sync (kms, + update_states_in_impl, + kms, + error); +} + +static void +on_udev_hotplug (MetaUdev *udev, + MetaKms *kms) +{ + g_autoptr (GError) error = NULL; + + if (!meta_kms_update_states_sync (kms, &error)) + g_warning ("Updating KMS state failed: %s", error->message); +} + MetaBackend * meta_kms_get_backend (MetaKms *kms) { @@ -86,6 +130,8 @@ MetaKms * meta_kms_new (MetaBackend *backend, GError **error) { + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + MetaUdev *udev = meta_backend_native_get_udev (backend_native); MetaKms *kms; kms = g_object_new (META_TYPE_KMS, NULL); @@ -97,6 +143,9 @@ meta_kms_new (MetaBackend *backend, return NULL; } + kms->hotplug_handler_id = + g_signal_connect (udev, "hotplug", G_CALLBACK (on_udev_hotplug), kms); + return kms; } @@ -104,9 +153,14 @@ static void meta_kms_finalize (GObject *object) { MetaKms *kms = META_KMS (object); + MetaBackendNative *backend_native = META_BACKEND_NATIVE (kms->backend); + MetaUdev *udev = meta_backend_native_get_udev (backend_native); g_list_free_full (kms->devices, g_object_unref); + if (kms->hotplug_handler_id) + g_signal_handler_disconnect (udev, kms->hotplug_handler_id); + G_OBJECT_CLASS (meta_kms_parent_class)->finalize (object); } diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c index 3c118e736..6fa230020 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c @@ -412,7 +412,8 @@ meta_monitor_manager_kms_connect_hotplug_handler (MetaMonitorManagerKms *manager MetaUdev *udev = meta_backend_native_get_udev (META_BACKEND_NATIVE (backend)); manager_kms->hotplug_handler_id = - g_signal_connect (udev, "hotplug", G_CALLBACK (on_udev_hotplug), manager); + g_signal_connect_after (udev, "hotplug", + G_CALLBACK (on_udev_hotplug), manager); } static void diff --git a/src/meson.build b/src/meson.build index 0bdd4583e..6e13c7c2f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -601,6 +601,7 @@ if have_native_backend 'backends/native/meta-kms-crtc-private.h', 'backends/native/meta-kms-crtc.c', 'backends/native/meta-kms-crtc.h', + 'backends/native/meta-kms-device-private.h', 'backends/native/meta-kms-device.c', 'backends/native/meta-kms-device.h', 'backends/native/meta-kms-impl-device.c',