kms: Add way to run without mode setting

Currently our only entry point for DRM devices is MetaKms*, but in order
to run without being DRM master, we cannot use /dev/dri/card*, nor can
we be either of the existing MetaKmsImplDevice implementation (legacy
KMS, and atomic KMS), as they both depend on being DRM master.

Thus to handle running without being DRM master (i.e. headless), add a
"dummy" MetaKmsImplDevice implementation, that doesn't do any mode
setting at all, and that switches to operate on the render node, instead
of the card node itself.

This means we still use the same GBM code paths as the regular native
backend paths, except we never make use of any CRTC backed onscreen
framebuffers.

Eventually, this "dummy" MetaKmsImplDevice will be replaced separating
"KMS" device objects from "render" device objects, but that will require
more significant changes. It will, however, be necessary for e.g. going
from being headless, only having access to a render node, to turning
into a real session, with a seat, being DRM master, and having access to
a card node.

This is currently not hooked up, but will be in a later commit.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1698>
This commit is contained in:
Jonas Ådahl
2021-01-19 14:54:45 +01:00
committed by Marge Bot
parent 739283d396
commit ee4e78b100
9 changed files with 248 additions and 26 deletions

View File

@ -23,10 +23,14 @@
#include "backends/native/meta-kms-device-private.h"
#include "backends/native/meta-kms-device.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <xf86drm.h>
#include "backends/native/meta-backend-native.h"
#include "backends/native/meta-kms-impl-device-atomic.h"
#include "backends/native/meta-kms-impl-device-dummy.h"
#include "backends/native/meta-kms-impl-device-simple.h"
#include "backends/native/meta-kms-impl-device.h"
#include "backends/native/meta-kms-impl.h"
@ -227,6 +231,7 @@ typedef struct _CreateImplDeviceData
MetaKmsDevice *device;
int fd;
const char *path;
MetaKmsDeviceFlag flags;
MetaKmsImplDevice *out_impl_device;
GList *out_crtcs;
@ -236,6 +241,7 @@ typedef struct _CreateImplDeviceData
GList *out_fallback_modes;
char *out_driver_name;
char *out_driver_description;
char *out_path;
} CreateImplDeviceData;
static gboolean
@ -273,17 +279,21 @@ get_driver_info (int fd,
}
static MetaKmsImplDevice *
meta_create_kms_impl_device (MetaKmsDevice *device,
MetaKmsImpl *impl,
int fd,
const char *path,
GError **error)
meta_create_kms_impl_device (MetaKmsDevice *device,
MetaKmsImpl *impl,
int fd,
const char *path,
MetaKmsDeviceFlag flags,
GError **error)
{
GType impl_device_type;
gboolean supports_atomic_mode_setting;
g_autofree char *driver_name = NULL;
g_autofree char *driver_description = NULL;
const char *atomic_kms_enable_env;
int impl_fd;
g_autofree char *impl_path = NULL;
MetaKmsImplDevice *impl_device;
meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl));
@ -294,7 +304,36 @@ meta_create_kms_impl_device (MetaKmsDevice *device,
}
atomic_kms_enable_env = getenv ("MUTTER_DEBUG_ENABLE_ATOMIC_KMS");
if (atomic_kms_enable_env)
if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING)
{
g_autofree char *render_node_path = NULL;
render_node_path = drmGetRenderDeviceNameFromFd (fd);
if (!render_node_path)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Couldn't find render node device for '%s' (%s)",
path, driver_name);
return NULL;
}
impl_fd = open (render_node_path, O_RDWR | O_CLOEXEC, 0);
if (impl_fd == -1)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"Failed to open render node '%s': %s",
render_node_path, g_strerror (errno));
return NULL;
}
g_message ("Adding device '%s' (from '%s', %s) using no mode setting.",
render_node_path, path, driver_name);
impl_path = g_steal_pointer (&render_node_path);
impl_device_type = META_TYPE_KMS_IMPL_DEVICE_DUMMY;
}
else if (atomic_kms_enable_env)
{
if (g_strcmp0 (atomic_kms_enable_env, "1") == 0)
{
@ -316,6 +355,9 @@ meta_create_kms_impl_device (MetaKmsDevice *device,
atomic_kms_enable_env);
}
impl_fd = dup (fd);
impl_path = g_strdup (path);
g_message ("Mode setting implementation for '%s' (%s) forced (%s).",
path, driver_name,
impl_device_type == META_TYPE_KMS_IMPL_DEVICE_ATOMIC ?
@ -326,6 +368,8 @@ meta_create_kms_impl_device (MetaKmsDevice *device,
g_message ("Adding device '%s' (%s) using non-atomic mode setting"
" (using atomic mode setting not allowed).",
path, driver_name);
impl_fd = dup (fd);
impl_path = g_strdup (path);
impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE;
}
else
@ -350,16 +394,29 @@ meta_create_kms_impl_device (MetaKmsDevice *device,
path, driver_name);
impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE;
}
impl_fd = dup (fd);
impl_path = g_strdup (path);
}
return g_initable_new (impl_device_type, NULL, error,
"device", device,
"impl", impl,
"fd", fd,
"path", path,
"driver-name", driver_name,
"driver-description", driver_description,
NULL);
impl_device = g_initable_new (impl_device_type, NULL, error,
"device", device,
"impl", impl,
"fd", impl_fd,
"path", impl_path,
"flags", flags,
"driver-name", driver_name,
"driver-description", driver_description,
NULL);
if (!impl_device)
{
close (impl_fd);
return NULL;
}
close (fd);
return impl_device;
}
static gpointer
@ -374,6 +431,7 @@ create_impl_device_in_impl (MetaKmsImpl *impl,
impl,
data->fd,
data->path,
data->flags,
error);
if (!impl_device)
return FALSE;
@ -391,6 +449,7 @@ create_impl_device_in_impl (MetaKmsImpl *impl,
g_strdup (meta_kms_impl_device_get_driver_name (impl_device));
data->out_driver_description =
g_strdup (meta_kms_impl_device_get_driver_description (impl_device));
data->out_path = g_strdup (meta_kms_impl_device_get_path (impl_device));
return GINT_TO_POINTER (TRUE);
}
@ -408,9 +467,22 @@ meta_kms_device_new (MetaKms *kms,
CreateImplDeviceData data;
int fd;
fd = meta_launcher_open_restricted (launcher, path, error);
if (fd == -1)
return NULL;
if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING)
{
fd = open (path, O_RDWR | O_CLOEXEC, 0);
if (fd == -1)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"Failed to open DRM device: %s", g_strerror (errno));
return NULL;
}
}
else
{
fd = meta_launcher_open_restricted (launcher, path, error);
if (fd == -1)
return NULL;
}
device = g_object_new (META_TYPE_KMS_DEVICE, NULL);
device->kms = kms;
@ -419,11 +491,15 @@ meta_kms_device_new (MetaKms *kms,
.device = device,
.fd = fd,
.path = path,
.flags = flags,
};
if (!meta_kms_run_impl_task_sync (kms, create_impl_device_in_impl, &data,
error))
{
meta_launcher_close_restricted (launcher, fd);
if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING)
close (fd);
else
meta_launcher_close_restricted (launcher, fd);
g_object_unref (device);
return NULL;
}
@ -438,6 +514,8 @@ meta_kms_device_new (MetaKms *kms,
device->fallback_modes = data.out_fallback_modes;
device->driver_name = data.out_driver_name;
device->driver_description = data.out_driver_description;
free (device->path);
device->path = data.out_path;
return device;
}
@ -495,7 +573,10 @@ meta_kms_device_finalize (GObject *object)
}
else
{
meta_launcher_close_restricted (launcher, data.out_fd);
if (device->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING)
close (data.out_fd);
else
meta_launcher_close_restricted (launcher, data.out_fd);
}
}
G_OBJECT_CLASS (meta_kms_device_parent_class)->finalize (object);