From a0eac7b417aaaf14170afce3c0b66269608a070e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 8 Mar 2019 16:23:15 +0100 Subject: [PATCH] kms: Add connector representation Represents drmModeConnector; both connected and disconnected. Currently only provides non-changing meta data. MetaOutputKms is changed to use MetaKmsConnector to get basic metadata, but variable metadata, those changing depending on what is connected (e.g. physical dimension, EDID, etc), are still manually retrieved by MetaOutputKms. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525 --- src/backends/native/meta-gpu-kms.c | 49 ++++--- .../native/meta-kms-connector-private.h | 29 ++++ src/backends/native/meta-kms-connector.c | 136 ++++++++++++++++++ src/backends/native/meta-kms-connector.h | 42 ++++++ src/backends/native/meta-kms-device.c | 11 ++ src/backends/native/meta-kms-device.h | 2 + src/backends/native/meta-kms-impl-device.c | 34 +++++ src/backends/native/meta-kms-impl-device.h | 2 + src/backends/native/meta-kms-types.h | 1 + src/backends/native/meta-output-kms.c | 54 ++----- src/backends/native/meta-output-kms.h | 2 + src/meson.build | 3 + 12 files changed, 304 insertions(+), 61 deletions(-) create mode 100644 src/backends/native/meta-kms-connector-private.h create mode 100644 src/backends/native/meta-kms-connector.c create mode 100644 src/backends/native/meta-kms-connector.h diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c index 36b090379..7b186de80 100644 --- a/src/backends/native/meta-gpu-kms.c +++ b/src/backends/native/meta-gpu-kms.c @@ -37,6 +37,7 @@ #include "backends/meta-output.h" #include "backends/native/meta-backend-native.h" #include "backends/native/meta-crtc-kms.h" +#include "backends/native/meta-kms-connector.h" #include "backends/native/meta-kms-device.h" #include "backends/native/meta-kms.h" #include "backends/native/meta-launcher.h" @@ -750,37 +751,43 @@ init_outputs (MetaGpuKms *gpu_kms, GList *old_outputs; GList *outputs; unsigned int i; + GList *l; old_outputs = meta_gpu_get_outputs (gpu); outputs = NULL; - for (i = 0; i < gpu_kms->n_connectors; i++) + i = 0; + for (l = meta_kms_device_get_connectors (gpu_kms->kms_device); l; l = l->next) { + MetaKmsConnector *kms_connector = l->data; + MetaOutput *output; + MetaOutput *old_output; + GError *error = NULL; drmModeConnector *connector; - connector = gpu_kms->connectors[i]; + connector = gpu_kms->connectors[i++]; - if (connector && connector->connection == DRM_MODE_CONNECTED) + if (!connector || connector->connection != DRM_MODE_CONNECTED) + continue; + + old_output = + find_output_by_connector_id (old_outputs, + meta_kms_connector_get_id (kms_connector)); + output = meta_create_kms_output (gpu_kms, + kms_connector, + connector, + resources, + old_output, + &error); + if (!output) { - MetaOutput *output; - MetaOutput *old_output; - GError *error = NULL; - - old_output = find_output_by_connector_id (old_outputs, - connector->connector_id); - output = meta_create_kms_output (gpu_kms, connector, resources, - old_output, - &error); - if (!output) - { - g_warning ("Failed to create KMS output: %s", error->message); - g_error_free (error); - } - else - { - outputs = g_list_prepend (outputs, output); - } + g_warning ("Failed to create KMS output: %s", error->message); + g_error_free (error); + } + else + { + outputs = g_list_prepend (outputs, output); } } diff --git a/src/backends/native/meta-kms-connector-private.h b/src/backends/native/meta-kms-connector-private.h new file mode 100644 index 000000000..a9bca85ba --- /dev/null +++ b/src/backends/native/meta-kms-connector-private.h @@ -0,0 +1,29 @@ +/* + * 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_CONNECTOR_PRIVATE_H +#define META_KMS_CONNECTOR_PRIVATE_H + +#include "backends/native/meta-kms-types.h" + +MetaKmsConnector * meta_kms_connector_new (MetaKmsImplDevice *impl_device, + drmModeConnector *drm_connector, + drmModeRes *drm_resources); + +#endif /* META_KMS_CONNECTOR_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c new file mode 100644 index 000000000..98b9a2f1b --- /dev/null +++ b/src/backends/native/meta-kms-connector.c @@ -0,0 +1,136 @@ +/* + * 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. + */ + +#include "config.h" + +#include "backends/native/meta-kms-connector.h" +#include "backends/native/meta-kms-connector-private.h" + +#include + +#include "backends/native/meta-kms-impl-device.h" + +struct _MetaKmsConnector +{ + GObject parent; + + MetaKmsDevice *device; + + uint32_t id; + MetaConnectorType type; + char *name; +}; + +G_DEFINE_TYPE (MetaKmsConnector, meta_kms_connector, G_TYPE_OBJECT) + +MetaKmsDevice * +meta_kms_connector_get_device (MetaKmsConnector *connector) +{ + return connector->device; +} + +MetaConnectorType +meta_kms_connector_get_connector_type (MetaKmsConnector *connector) +{ + return connector->type; +} + +uint32_t +meta_kms_connector_get_id (MetaKmsConnector *connector) +{ + return connector->id; +} + +const char * +meta_kms_connector_get_name (MetaKmsConnector *connector) +{ + return connector->name; +} + +static char * +make_connector_name (drmModeConnector *drm_connector) +{ + static const char * const connector_type_names[] = { + "None", + "VGA", + "DVI-I", + "DVI-D", + "DVI-A", + "Composite", + "SVIDEO", + "LVDS", + "Component", + "DIN", + "DP", + "HDMI", + "HDMI-B", + "TV", + "eDP", + "Virtual", + "DSI", + }; + + if (drm_connector->connector_type < G_N_ELEMENTS (connector_type_names)) + return g_strdup_printf ("%s-%d", + connector_type_names[drm_connector->connector_type], + drm_connector->connector_type_id); + else + return g_strdup_printf ("Unknown%d-%d", + drm_connector->connector_type, + drm_connector->connector_type_id); +} + +MetaKmsConnector * +meta_kms_connector_new (MetaKmsImplDevice *impl_device, + drmModeConnector *drm_connector, + drmModeRes *drm_resources) +{ + MetaKmsConnector *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; + connector->type = (MetaConnectorType) drm_connector->connector_type; + connector->name = make_connector_name (drm_connector); + + return connector; +} + +static void +meta_kms_connector_finalize (GObject *object) +{ + MetaKmsConnector *connector = META_KMS_CONNECTOR (object); + + g_free (connector->name); + + G_OBJECT_CLASS (meta_kms_connector_parent_class)->finalize (object); +} + +static void +meta_kms_connector_init (MetaKmsConnector *connector) +{ +} + +static void +meta_kms_connector_class_init (MetaKmsConnectorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_kms_connector_finalize; +} diff --git a/src/backends/native/meta-kms-connector.h b/src/backends/native/meta-kms-connector.h new file mode 100644 index 000000000..d49b31fe3 --- /dev/null +++ b/src/backends/native/meta-kms-connector.h @@ -0,0 +1,42 @@ +/* + * 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_CONNECTOR_H +#define META_KMS_CONNECTOR_H + +#include +#include +#include + +#include "backends/native/meta-kms-types.h" +#include "backends/meta-output.h" + +#define META_TYPE_KMS_CONNECTOR (meta_kms_connector_get_type ()) +G_DECLARE_FINAL_TYPE (MetaKmsConnector, meta_kms_connector, + META, KMS_CONNECTOR, GObject) + +MetaKmsDevice * meta_kms_connector_get_device (MetaKmsConnector *connector); + +MetaConnectorType meta_kms_connector_get_connector_type (MetaKmsConnector *connector); + +uint32_t meta_kms_connector_get_id (MetaKmsConnector *connector); + +const char * meta_kms_connector_get_name (MetaKmsConnector *connector); + +#endif /* META_KMS_CONNECTOR_H */ diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c index e3fc396fd..c168bad80 100644 --- a/src/backends/native/meta-kms-device.c +++ b/src/backends/native/meta-kms-device.c @@ -38,6 +38,7 @@ struct _MetaKmsDevice char *path; GList *crtcs; + GList *connectors; GList *planes; }; @@ -61,6 +62,12 @@ meta_kms_device_get_flags (MetaKmsDevice *device) return device->flags; } +GList * +meta_kms_device_get_connectors (MetaKmsDevice *device) +{ + return device->connectors; +} + GList * meta_kms_device_get_crtcs (MetaKmsDevice *device) { @@ -74,6 +81,7 @@ typedef struct _CreateImplDeviceData MetaKmsImplDevice *out_impl_device; GList *out_crtcs; + GList *out_connectors; GList *out_planes; } CreateImplDeviceData; @@ -89,6 +97,7 @@ create_impl_device_in_impl (MetaKmsImpl *impl, data->out_impl_device = impl_device; data->out_crtcs = meta_kms_impl_device_copy_crtcs (impl_device); + data->out_connectors = meta_kms_impl_device_copy_connectors (impl_device); data->out_planes = meta_kms_impl_device_copy_planes (impl_device); return TRUE; @@ -130,6 +139,7 @@ meta_kms_device_new (MetaKms *kms, device->flags = flags; device->path = g_strdup (path); device->crtcs = data.out_crtcs; + device->connectors = data.out_connectors; device->planes = data.out_planes; return device; @@ -170,6 +180,7 @@ meta_kms_device_finalize (GObject *object) GError *error = NULL; g_list_free (device->crtcs); + g_list_free (device->connectors); g_list_free (device->planes); data = (FreeImplDeviceData) { diff --git a/src/backends/native/meta-kms-device.h b/src/backends/native/meta-kms-device.h index 480f8aa1d..77037f237 100644 --- a/src/backends/native/meta-kms-device.h +++ b/src/backends/native/meta-kms-device.h @@ -35,6 +35,8 @@ const char * meta_kms_device_get_path (MetaKmsDevice *device); MetaKmsDeviceFlag meta_kms_device_get_flags (MetaKmsDevice *device); +GList * meta_kms_device_get_connectors (MetaKmsDevice *device); + GList * meta_kms_device_get_crtcs (MetaKmsDevice *device); MetaKmsDevice * meta_kms_device_new (MetaKms *kms, diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index 91c6b7119..d35f2300b 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -23,6 +23,8 @@ #include +#include "backends/native/meta-kms-connector-private.h" +#include "backends/native/meta-kms-connector.h" #include "backends/native/meta-kms-crtc-private.h" #include "backends/native/meta-kms-crtc.h" #include "backends/native/meta-kms-impl.h" @@ -39,6 +41,7 @@ struct _MetaKmsImplDevice int fd; GList *crtcs; + GList *connectors; GList *planes; }; @@ -50,6 +53,12 @@ meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device) return impl_device->device; } +GList * +meta_kms_impl_device_copy_connectors (MetaKmsImplDevice *impl_device) +{ + return g_list_copy (impl_device->connectors); +} + GList * meta_kms_impl_device_copy_crtcs (MetaKmsImplDevice *impl_device) { @@ -112,6 +121,29 @@ init_crtcs (MetaKmsImplDevice *impl_device, impl_device->crtcs = g_list_reverse (impl_device->crtcs); } +static void +init_connectors (MetaKmsImplDevice *impl_device, + drmModeRes *drm_resources) +{ + unsigned int i; + + for (i = 0; i < drm_resources->count_connectors; i++) + { + drmModeConnector *drm_connector; + MetaKmsConnector *connector; + + drm_connector = drmModeGetConnector (impl_device->fd, + drm_resources->connectors[i]); + connector = meta_kms_connector_new (impl_device, drm_connector, + drm_resources); + drmModeFreeConnector (drm_connector); + + impl_device->connectors = g_list_prepend (impl_device->connectors, + connector); + } + impl_device->connectors = g_list_reverse (impl_device->connectors); +} + static MetaKmsPlaneType get_plane_type (MetaKmsImplDevice *impl_device, drmModeObjectProperties *props) @@ -204,6 +236,7 @@ meta_kms_impl_device_new (MetaKmsDevice *device, drm_resources = drmModeGetResources (fd); init_crtcs (impl_device, drm_resources); + init_connectors (impl_device, drm_resources); init_planes (impl_device); drmModeFreeResources (drm_resources); @@ -245,6 +278,7 @@ meta_kms_impl_device_finalize (GObject *object) g_list_free_full (impl_device->planes, g_object_unref); g_list_free_full (impl_device->crtcs, g_object_unref); + g_list_free_full (impl_device->connectors, g_object_unref); G_OBJECT_CLASS (meta_kms_impl_device_parent_class)->finalize (object); } diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h index 6ad45a887..26d946760 100644 --- a/src/backends/native/meta-kms-impl-device.h +++ b/src/backends/native/meta-kms-impl-device.h @@ -34,6 +34,8 @@ G_DECLARE_FINAL_TYPE (MetaKmsImplDevice, meta_kms_impl_device, MetaKmsDevice * meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device); +GList * meta_kms_impl_device_copy_connectors (MetaKmsImplDevice *impl_device); + GList * meta_kms_impl_device_copy_crtcs (MetaKmsImplDevice *impl_device); GList * meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device); diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h index 47e3b56e1..d8d099626 100644 --- a/src/backends/native/meta-kms-types.h +++ b/src/backends/native/meta-kms-types.h @@ -24,6 +24,7 @@ typedef struct _MetaKms MetaKms; typedef struct _MetaKmsDevice MetaKmsDevice; typedef struct _MetaKmsCrtc MetaKmsCrtc; +typedef struct _MetaKmsConnector MetaKmsConnector; typedef struct _MetaKmsImpl MetaKmsImpl; typedef struct _MetaKmsImplDevice MetaKmsImplDevice; diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c index 50b58b76f..9444d5b62 100644 --- a/src/backends/native/meta-output-kms.c +++ b/src/backends/native/meta-output-kms.c @@ -29,6 +29,7 @@ #include #include "backends/meta-crtc.h" +#include "backends/native/meta-kms-connector.h" #include "backends/native/meta-crtc-kms.h" #include "meta-default-modes.h" @@ -39,6 +40,8 @@ typedef struct _MetaOutputKms { MetaOutput parent; + MetaKmsConnector *kms_connector; + drmModeConnector *connector; /* @@ -122,7 +125,7 @@ meta_output_kms_get_connector_id (MetaOutput *output) { MetaOutputKms *output_kms = output->driver_private; - return output_kms->connector->connector_id; + return meta_kms_connector_get_id (output_kms->kms_connector); } void @@ -368,39 +371,6 @@ find_connector_properties (MetaGpuKms *gpu_kms, } } -static char * -make_output_name (drmModeConnector *connector) -{ - static const char * const connector_type_names[] = { - "None", - "VGA", - "DVI-I", - "DVI-D", - "DVI-A", - "Composite", - "SVIDEO", - "LVDS", - "Component", - "DIN", - "DP", - "HDMI", - "HDMI-B", - "TV", - "eDP", - "Virtual", - "DSI", - }; - - if (connector->connector_type < G_N_ELEMENTS (connector_type_names)) - return g_strdup_printf ("%s-%d", - connector_type_names[connector->connector_type], - connector->connector_type_id); - else - return g_strdup_printf ("Unknown%d-%d", - connector->connector_type, - connector->connector_type_id); -} - static void meta_output_destroy_notify (MetaOutput *output) { @@ -544,6 +514,7 @@ init_output_modes (MetaOutput *output, MetaOutput * meta_create_kms_output (MetaGpuKms *gpu_kms, + MetaKmsConnector *kms_connector, drmModeConnector *connector, MetaKmsResources *resources, MetaOutput *old_output, @@ -552,13 +523,14 @@ meta_create_kms_output (MetaGpuKms *gpu_kms, MetaGpu *gpu = META_GPU (gpu_kms); MetaOutput *output; MetaOutputKms *output_kms; + uint32_t connector_id; GArray *crtcs; GBytes *edid; GList *l; unsigned int i; unsigned int crtc_mask; int fd; - uint32_t id; + uint32_t gpu_id; unsigned int n_encoders; drmModeEncoderPtr *encoders; drmModeEncoderPtr current_encoder = NULL; @@ -570,10 +542,11 @@ meta_create_kms_output (MetaGpuKms *gpu_kms, output->driver_notify = (GDestroyNotify) meta_output_destroy_notify; output->gpu = gpu; - output->name = make_output_name (connector); + output->name = g_strdup (meta_kms_connector_get_name (kms_connector)); - id = meta_gpu_kms_get_id (gpu_kms); - output->winsys_id = ((uint64_t) id << 32) | connector->connector_id; + gpu_id = meta_gpu_kms_get_id (gpu_kms); + connector_id = meta_kms_connector_get_id (kms_connector); + output->winsys_id = ((uint64_t) gpu_id << 32) | connector_id; switch (connector->subpixel) { @@ -598,6 +571,8 @@ meta_create_kms_output (MetaGpuKms *gpu_kms, break; } + output_kms->kms_connector = kms_connector; + output_kms->connector = connector; find_connector_properties (gpu_kms, output); @@ -710,8 +685,7 @@ meta_create_kms_output (MetaGpuKms *gpu_kms, meta_output_parse_edid (output, edid); g_bytes_unref (edid); - /* MetaConnectorType matches DRM's connector types */ - output->connector_type = (MetaConnectorType) connector->connector_type; + output->connector_type = meta_kms_connector_get_connector_type (kms_connector); output_get_tile_info (gpu_kms, output); diff --git a/src/backends/native/meta-output-kms.h b/src/backends/native/meta-output-kms.h index 58385de0a..2c0bf8f95 100644 --- a/src/backends/native/meta-output-kms.h +++ b/src/backends/native/meta-output-kms.h @@ -25,6 +25,7 @@ #include "backends/meta-output.h" #include "backends/native/meta-gpu-kms.h" +#include "backends/native/meta-kms-types.h" void meta_output_kms_set_underscan (MetaOutput *output); @@ -39,6 +40,7 @@ uint32_t meta_output_kms_get_connector_id (MetaOutput *output); GBytes * meta_output_kms_read_edid (MetaOutput *output); MetaOutput * meta_create_kms_output (MetaGpuKms *gpu_kms, + MetaKmsConnector *kms_connector, drmModeConnector *connector, MetaKmsResources *resources, MetaOutput *old_output, diff --git a/src/meson.build b/src/meson.build index 37b372030..33288335d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -594,6 +594,9 @@ if have_native_backend 'backends/native/meta-output-kms.c', 'backends/native/meta-output-kms.h', 'backends/native/meta-renderer-native.c', + 'backends/native/meta-kms-connector-private.h', + 'backends/native/meta-kms-connector.c', + 'backends/native/meta-kms-connector.h', 'backends/native/meta-kms-crtc-private.h', 'backends/native/meta-kms-crtc.c', 'backends/native/meta-kms-crtc.h',