backends/native: Re-order primary GPU choosing logic

This is a step towards moving the primary GPU logic into the native
renderer exclusively. In the future the renderer will have one more
criterion on choosing the primary GPU than MetaMonitorManagerKms should
know about: does a GPU offer hardware rendering.

The choosing of primary GPU is separated from the discovery of GPUs.
When GPUs are discovered and added to the list, the MetaGpuKmsFlag is
now populated correctly and used in choosing.

Choosing the primary GPU is done after all GPUs have been found and is
slightly different from before:

- Skipping devices that do not belong to our seat now works instead of
becoming the primary GPU.

- Fall back to any non-platform, non-boot_vga device if neither kind is
found.

The old preference of platform over boot_vga device is kept.

The hotplug path will continue creating a gpu_kms without flags, because
at that point the primary GPU has already been chosen and the flags are
irrelevant.

Co-authored by: Pekka Paalanen <pekka.paalanen@collabora.com>

https://gitlab.gnome.org/GNOME/mutter/merge_requests/271
This commit is contained in:
Emilio Pozuelo Monfort 2018-09-21 14:37:03 +02:00 committed by Jonas Ådahl
parent ddb0ef1e8d
commit 1def099047

View File

@ -586,16 +586,9 @@ meta_monitor_manager_kms_get_primary_gpu (MetaMonitorManagerKms *manager_kms)
return manager_kms->primary_gpu;
}
typedef enum
{
GPU_TYPE_PRIMARY,
GPU_TYPE_SECONDARY
} GpuType;
static GList *
get_gpu_paths (MetaMonitorManagerKms *manager_kms,
GpuType gpu_type,
const char *filtered_gpu_path)
static gboolean
init_gpus (MetaMonitorManagerKms *manager_kms,
GError **error)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
@ -605,7 +598,7 @@ get_gpu_paths (MetaMonitorManagerKms *manager_kms,
const char *seat_id;
GList *devices;
GList *l;
GList *gpu_paths = NULL;
MetaGpuKmsFlag flags = META_GPU_KMS_FLAG_NONE;
enumerator = g_udev_enumerator_new (manager_kms->udev);
@ -620,18 +613,24 @@ get_gpu_paths (MetaMonitorManagerKms *manager_kms,
devices = g_udev_enumerator_execute (enumerator);
if (!devices)
return NULL;
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"No GPUs found with udev");
return FALSE;
}
seat_id = meta_launcher_get_seat_id (launcher);
for (l = devices; l; l = l->next)
{
GUdevDevice *dev = l->data;
MetaGpuKms *gpu_kms;
g_autoptr (GUdevDevice) platform_device = NULL;
g_autoptr (GUdevDevice) pci_device = NULL;
const char *device_path;
const char *device_type;
const char *device_seat;
GError *local_error = NULL;
/* Filter out devices that are not character device, like card0-VGA-1. */
if (g_udev_device_get_device_type (dev) != G_UDEV_DEVICE_TYPE_CHAR)
@ -642,8 +641,6 @@ get_gpu_paths (MetaMonitorManagerKms *manager_kms,
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");
if (!device_seat)
@ -651,16 +648,6 @@ get_gpu_paths (MetaMonitorManagerKms *manager_kms,
/* When ID_SEAT is not set, it means seat0. */
device_seat = "seat0";
}
else if (g_strcmp0 (device_seat, "seat0") != 0 &&
gpu_type == GPU_TYPE_PRIMARY)
{
/*
* If the device has been explicitly assigned other seat
* than seat0, it is probably the right device to use.
*/
gpu_paths = g_list_append (gpu_paths, g_strdup (device_path));
break;
}
/* Skip devices that do not belong to our seat. */
if (g_strcmp0 (seat_id, device_seat))
@ -669,38 +656,71 @@ get_gpu_paths (MetaMonitorManagerKms *manager_kms,
platform_device = g_udev_device_get_parent_with_subsystem (dev,
"platform",
NULL);
if (platform_device != NULL && gpu_type == GPU_TYPE_PRIMARY)
{
gpu_paths = g_list_append (gpu_paths, g_strdup (device_path));
break;
}
if (platform_device != NULL)
flags |= META_GPU_KMS_FLAG_PLATFORM_DEVICE;
pci_device = g_udev_device_get_parent_with_subsystem (dev, "pci", NULL);
if (pci_device != NULL)
{
if (gpu_type == GPU_TYPE_PRIMARY)
{
int boot_vga;
boot_vga = g_udev_device_get_sysfs_attr_as_int (pci_device,
"boot_vga");
if (boot_vga == 1)
{
gpu_paths = g_list_append (gpu_paths, g_strdup (device_path));
break;
}
}
if (g_udev_device_get_sysfs_attr_as_int (pci_device,
"boot_vga") == 1)
flags |= META_GPU_KMS_FLAG_BOOT_VGA;
}
if (gpu_type == GPU_TYPE_SECONDARY)
gpu_kms = meta_gpu_kms_new (manager_kms, device_path, flags,
&local_error);
if (!gpu_kms)
{
gpu_paths = g_list_append (gpu_paths, g_strdup (device_path));
g_warning ("Failed to open gpu '%s': %s",
device_path, local_error->message);
g_clear_error (&local_error);
continue;
}
meta_monitor_manager_add_gpu (manager, META_GPU (gpu_kms));
}
g_list_free_full (devices, g_object_unref);
return gpu_paths;
if (!meta_monitor_manager_get_gpus (manager))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"No GPUs found");
return FALSE;
}
return TRUE;
}
static MetaGpuKms *
choose_primary_gpu (MetaMonitorManagerKms *manager_kms)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
GList *gpus = meta_monitor_manager_get_gpus (manager);
GList *l;
g_return_val_if_fail (gpus, NULL);
/* Prefer a platform device */
for (l = gpus; l; l = l->next)
{
MetaGpuKms *gpu_kms = META_GPU_KMS (l->data);
if (meta_gpu_kms_is_platform_device (gpu_kms))
return gpu_kms;
}
/* Otherwise a device we booted with */
for (l = gpus; l; l = l->next)
{
MetaGpuKms *gpu_kms = META_GPU_KMS (l->data);
if (meta_gpu_kms_is_boot_vga (gpu_kms))
return gpu_kms;
}
/* Lastly, just pick the first device */
return META_GPU_KMS (gpus->data);
}
static gboolean
@ -711,57 +731,19 @@ meta_monitor_manager_kms_initable_init (GInitable *initable,
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (initable);
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
const char *subsystems[2] = { "drm", NULL };
GList *gpu_paths;
g_autofree char *primary_gpu_path = NULL;
GList *l;
gboolean can_have_outputs;
manager_kms->udev = g_udev_client_new (subsystems);
gpu_paths = get_gpu_paths (manager_kms, GPU_TYPE_PRIMARY, NULL);
if (g_list_length (gpu_paths) != 1)
meta_monitor_manager_kms_connect_uevent_handler (manager_kms);
if (!init_gpus (manager_kms, error))
{
g_list_free_full (gpu_paths, g_free);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Could not find a primary drm kms device");
return FALSE;
}
primary_gpu_path = g_strdup (gpu_paths->data);
manager_kms->primary_gpu = meta_gpu_kms_new (manager_kms,
primary_gpu_path,
META_GPU_KMS_FLAG_NONE,
error);
g_list_free_full (gpu_paths, g_free);
if (!manager_kms->primary_gpu)
return FALSE;
meta_monitor_manager_kms_connect_uevent_handler (manager_kms);
meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms),
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)
{
g_autoptr (GError) secondary_error = NULL;
char *gpu_path = l->data;
MetaGpuKms *gpu_kms;
gpu_kms = meta_gpu_kms_new (manager_kms, gpu_path,
META_GPU_KMS_FLAG_NONE,
&secondary_error);
if (!gpu_kms)
{
g_warning ("Failed to open secondary gpu '%s': %s",
gpu_path, secondary_error->message);
continue;
}
meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms),
META_GPU (gpu_kms));
}
g_list_free_full (gpu_paths, g_free);
manager_kms->primary_gpu = choose_primary_gpu (manager_kms);
can_have_outputs = FALSE;
for (l = meta_monitor_manager_get_gpus (manager); l; l = l->next)