monitor-manager-kms: Add all GPUs with connectors

First find the primary GPU and open it. Then go through all other
discovered GPUs with connectors and add those too. MetaRendererNative
still fails to initialize when multiple added GPUs and
MetaCursorRendererNative still always falls back on OpenGL based cursor
rendering when there are multiple GPUs.

https://bugzilla.gnome.org/show_bug.cgi?id=785381
This commit is contained in:
Jonas Ådahl 2017-07-24 17:07:09 +08:00
parent b0e42d3f6e
commit cbcf6a4f23

View File

@ -520,59 +520,16 @@ meta_monitor_manager_kms_get_primary_gpu (MetaMonitorManagerKms *manager_kms)
return manager_kms->primary_gpu; return manager_kms->primary_gpu;
} }
static guint typedef enum
count_devices_with_connectors (const char *seat_id,
GList *devices)
{ {
g_autoptr (GHashTable) cards = NULL; GPU_TYPE_PRIMARY,
GList *l; GPU_TYPE_SECONDARY
} GpuType;
cards = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); static GList *
for (l = devices; l != NULL; l = l->next) get_gpu_paths (MetaMonitorManagerKms *manager_kms,
{ GpuType gpu_type,
GUdevDevice *device = l->data; const char *filtered_gpu_path)
g_autoptr (GUdevDevice) parent_device = NULL;
const gchar *parent_device_type = NULL;
const gchar *parent_device_name = NULL;
const gchar *card_seat;
/* Filter out the real card devices, we only care about the connectors. */
if (g_udev_device_get_device_type (device) != G_UDEV_DEVICE_TYPE_NONE)
continue;
/* Only connectors have a modes attribute. */
if (!g_udev_device_has_sysfs_attr (device, "modes"))
continue;
parent_device = g_udev_device_get_parent (device);
if (g_udev_device_get_device_type (parent_device) ==
G_UDEV_DEVICE_TYPE_CHAR)
parent_device_type = g_udev_device_get_property (parent_device,
"DEVTYPE");
if (g_strcmp0 (parent_device_type, DRM_CARD_UDEV_DEVICE_TYPE) != 0)
continue;
card_seat = g_udev_device_get_property (parent_device, "ID_SEAT");
if (!card_seat)
card_seat = "seat0";
if (g_strcmp0 (seat_id, card_seat) != 0)
continue;
parent_device_name = g_udev_device_get_name (parent_device);
g_hash_table_insert (cards,
(gpointer) parent_device_name ,
g_steal_pointer (&parent_device));
}
return g_hash_table_size (cards);
}
static char *
get_primary_gpu_path (MetaMonitorManagerKms *manager_kms)
{ {
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
MetaBackend *backend = meta_monitor_manager_get_backend (manager); MetaBackend *backend = meta_monitor_manager_get_backend (manager);
@ -580,9 +537,9 @@ get_primary_gpu_path (MetaMonitorManagerKms *manager_kms)
MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native); MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native);
g_autoptr (GUdevEnumerator) enumerator = NULL; g_autoptr (GUdevEnumerator) enumerator = NULL;
const char *seat_id; const char *seat_id;
char *path = NULL;
GList *devices; GList *devices;
GList *l; GList *l;
GList *gpu_paths = NULL;
enumerator = g_udev_enumerator_new (manager_kms->udev); enumerator = g_udev_enumerator_new (manager_kms->udev);
@ -597,30 +554,16 @@ get_primary_gpu_path (MetaMonitorManagerKms *manager_kms)
devices = g_udev_enumerator_execute (enumerator); devices = g_udev_enumerator_execute (enumerator);
if (!devices) if (!devices)
goto out; return NULL;
seat_id = meta_launcher_get_seat_id (launcher); seat_id = meta_launcher_get_seat_id (launcher);
/*
* For now, fail on systems where some of the connectors are connected to
* secondary gpus.
*
* https://bugzilla.gnome.org/show_bug.cgi?id=771442
*/
if (g_getenv ("MUTTER_ALLOW_HYBRID_GPUS") == NULL)
{
unsigned int num_devices;
num_devices = count_devices_with_connectors (seat_id, devices);
if (num_devices != 1)
goto out;
}
for (l = devices; l; l = l->next) for (l = devices; l; l = l->next)
{ {
GUdevDevice *dev = l->data; GUdevDevice *dev = l->data;
g_autoptr (GUdevDevice) platform_device = NULL; g_autoptr (GUdevDevice) platform_device = NULL;
g_autoptr (GUdevDevice) pci_device = NULL; g_autoptr (GUdevDevice) pci_device = NULL;
const char *device_path;
const char *device_type; const char *device_type;
const char *device_seat; const char *device_seat;
@ -632,19 +575,24 @@ get_primary_gpu_path (MetaMonitorManagerKms *manager_kms)
if (g_strcmp0 (device_type, DRM_CARD_UDEV_DEVICE_TYPE) != 0) if (g_strcmp0 (device_type, DRM_CARD_UDEV_DEVICE_TYPE) != 0)
continue; continue;
device_path = g_udev_device_get_device_file (dev);
if (g_strcmp0 (device_path, filtered_gpu_path) == 0)
continue;
device_seat = g_udev_device_get_property (dev, "ID_SEAT"); device_seat = g_udev_device_get_property (dev, "ID_SEAT");
if (!device_seat) if (!device_seat)
{ {
/* When ID_SEAT is not set, it means seat0. */ /* When ID_SEAT is not set, it means seat0. */
device_seat = "seat0"; device_seat = "seat0";
} }
else if (g_strcmp0 (device_seat, "seat0") != 0) else if (g_strcmp0 (device_seat, "seat0") != 0 &&
gpu_type == GPU_TYPE_PRIMARY)
{ {
/* /*
* If the device has been explicitly assigned other seat * If the device has been explicitly assigned other seat
* than seat0, it is probably the right device to use. * than seat0, it is probably the right device to use.
*/ */
path = g_strdup (g_udev_device_get_device_file (dev)); gpu_paths = g_list_append (gpu_paths, g_strdup (device_path));
break; break;
} }
@ -655,14 +603,16 @@ get_primary_gpu_path (MetaMonitorManagerKms *manager_kms)
platform_device = g_udev_device_get_parent_with_subsystem (dev, platform_device = g_udev_device_get_parent_with_subsystem (dev,
"platform", "platform",
NULL); NULL);
if (platform_device != NULL) if (platform_device != NULL && gpu_type == GPU_TYPE_PRIMARY)
{ {
path = g_strdup (g_udev_device_get_device_file (dev)); gpu_paths = g_list_append (gpu_paths, g_strdup (device_path));
break; break;
} }
pci_device = g_udev_device_get_parent_with_subsystem (dev, "pci", NULL); pci_device = g_udev_device_get_parent_with_subsystem (dev, "pci", NULL);
if (pci_device != NULL) if (pci_device != NULL)
{
if (gpu_type == GPU_TYPE_PRIMARY)
{ {
int boot_vga; int boot_vga;
@ -670,16 +620,20 @@ get_primary_gpu_path (MetaMonitorManagerKms *manager_kms)
"boot_vga"); "boot_vga");
if (boot_vga == 1) if (boot_vga == 1)
{ {
path = g_strdup (g_udev_device_get_device_file (dev)); gpu_paths = g_list_append (gpu_paths, g_strdup (device_path));
break; break;
} }
} }
else
{
gpu_paths = g_list_append (gpu_paths, g_strdup (device_path));
}
}
} }
out:
g_list_free_full (devices, g_object_unref); g_list_free_full (devices, g_object_unref);
return path; return gpu_paths;
} }
static gboolean static gboolean
@ -689,21 +643,26 @@ meta_monitor_manager_kms_initable_init (GInitable *initable,
{ {
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (initable); MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (initable);
const char *subsystems[2] = { "drm", NULL }; const char *subsystems[2] = { "drm", NULL };
g_autofree char *primary_gpu_path; GList *gpu_paths;
g_autofree char *primary_gpu_path = NULL;
GList *l;
manager_kms->udev = g_udev_client_new (subsystems); manager_kms->udev = g_udev_client_new (subsystems);
primary_gpu_path = get_primary_gpu_path (manager_kms); gpu_paths = get_gpu_paths (manager_kms, GPU_TYPE_PRIMARY, NULL);
if (!primary_gpu_path) if (g_list_length (gpu_paths) != 1)
{ {
g_list_free_full (gpu_paths, g_free);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Could not find drm kms device"); "Could not find a primary drm kms device");
return FALSE; return FALSE;
} }
primary_gpu_path = g_strdup (gpu_paths->data);
manager_kms->primary_gpu = meta_gpu_kms_new (manager_kms, manager_kms->primary_gpu = meta_gpu_kms_new (manager_kms,
primary_gpu_path, primary_gpu_path,
error); error);
g_list_free_full (gpu_paths, g_free);
if (!manager_kms->primary_gpu) if (!manager_kms->primary_gpu)
return FALSE; return FALSE;
@ -712,6 +671,26 @@ meta_monitor_manager_kms_initable_init (GInitable *initable,
meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms), meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms),
META_GPU (manager_kms->primary_gpu)); META_GPU (manager_kms->primary_gpu));
gpu_paths = get_gpu_paths (manager_kms, GPU_TYPE_SECONDARY, primary_gpu_path);
for (l = gpu_paths; l; l = l->next)
{
GError *secondary_error = NULL;
char *gpu_path = l->data;
MetaGpuKms *gpu_kms;
gpu_kms = meta_gpu_kms_new (manager_kms, gpu_path, &secondary_error);
if (!gpu_kms)
{
g_warning ("Failed to open secondary gpu '%s': %s",
gpu_path, secondary_error->message);
g_error_free (secondary_error);
}
meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms),
META_GPU (gpu_kms));
}
g_list_free_full (gpu_paths, g_free);
return TRUE; return TRUE;
} }