kms: Have the device impl open device files themself

This changes the way the KMS backends load; if we're headless, we always
use the dummy one and fail otherwise; in other cases, we first try the
atomic backend, and if that fails, fall back on the simple one.

The aim for this is to have the impl device open and close the device
when needed, using the device pool directly.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1828>
This commit is contained in:
Jonas Ådahl 2021-04-06 12:14:24 +02:00
parent f3457b678c
commit e6421dc5da
6 changed files with 289 additions and 213 deletions

View File

@ -230,7 +230,6 @@ meta_kms_device_add_fake_plane_in_impl (MetaKmsDevice *device,
typedef struct _CreateImplDeviceData typedef struct _CreateImplDeviceData
{ {
MetaKmsDevice *device; MetaKmsDevice *device;
MetaDeviceFile *device_file;
const char *path; const char *path;
MetaKmsDeviceFlag flags; MetaKmsDeviceFlag flags;
@ -245,170 +244,70 @@ typedef struct _CreateImplDeviceData
char *out_path; char *out_path;
} CreateImplDeviceData; } CreateImplDeviceData;
static gboolean static const char *
is_atomic_allowed (const char *driver_name) impl_device_type_to_string (GType type)
{ {
const char *atomic_driver_deny_list[] = { if (type == META_TYPE_KMS_IMPL_DEVICE_ATOMIC)
"qxl", return "atomic modesetting";
"vmwgfx", else if (type == META_TYPE_KMS_IMPL_DEVICE_SIMPLE)
"vboxvideo", return "legacy modesetting";
"nvidia-drm", else if (type == META_TYPE_KMS_IMPL_DEVICE_DUMMY)
NULL, return "no modesetting";
}; g_assert_not_reached();
return !g_strv_contains (atomic_driver_deny_list, driver_name);
}
static gboolean
get_driver_info (int fd,
char **name,
char **description)
{
drmVersion *drm_version;
drm_version = drmGetVersion (fd);
if (!drm_version)
return FALSE;
*name = g_strndup (drm_version->name,
drm_version->name_len);
*description = g_strndup (drm_version->desc,
drm_version->desc_len);
drmFreeVersion (drm_version);
return TRUE;
} }
static MetaKmsImplDevice * static MetaKmsImplDevice *
meta_create_kms_impl_device (MetaKmsDevice *device, meta_create_kms_impl_device (MetaKmsDevice *device,
MetaKmsImpl *impl, MetaKmsImpl *impl,
MetaDeviceFile *device_file,
const char *path, const char *path,
MetaKmsDeviceFlag flags, MetaKmsDeviceFlag flags,
GError **error) 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 fd;
g_autoptr (MetaDeviceFile) impl_device_file = NULL;
MetaKmsImplDevice *impl_device;
meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl)); meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl));
fd = meta_device_file_get_fd (device_file);
if (!get_driver_info (fd, &driver_name, &driver_description))
{
driver_name = g_strdup ("unknown");
driver_description = g_strdup ("Unknown");
}
atomic_kms_enable_env = getenv ("MUTTER_DEBUG_ENABLE_ATOMIC_KMS");
if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING) if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING)
{ {
g_autofree char *render_node_path = NULL; return g_initable_new (META_TYPE_KMS_IMPL_DEVICE_DUMMY,
MetaDevicePool *device_pool; NULL, error,
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;
}
device_pool = meta_device_file_get_pool (device_file);
impl_device_file = meta_device_pool_open (device_pool, render_node_path,
META_DEVICE_FILE_FLAG_NONE,
error);
if (!impl_device_file)
return NULL;
g_message ("Adding device '%s' (from '%s', %s) using no mode setting.",
render_node_path, path, driver_name);
impl_device_type = META_TYPE_KMS_IMPL_DEVICE_DUMMY;
}
else if (atomic_kms_enable_env)
{
if (g_strcmp0 (atomic_kms_enable_env, "1") == 0)
{
impl_device_type = META_TYPE_KMS_IMPL_DEVICE_ATOMIC;
if (drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1) != 0)
{
g_error ("Failed to force atomic mode setting on '%s' (%s).",
path, driver_name);
}
}
else if (g_strcmp0 (atomic_kms_enable_env, "0") == 0)
{
impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE;
}
else
{
g_error ("Invalid value '%s' for MUTTER_DEBUG_ENABLE_ATOMIC_KMS, "
"bailing.",
atomic_kms_enable_env);
}
impl_device_file = meta_device_file_acquire (device_file);
g_message ("Mode setting implementation for '%s' (%s) forced (%s).",
path, driver_name,
impl_device_type == META_TYPE_KMS_IMPL_DEVICE_ATOMIC ?
"atomic" : "non-atomic");
}
else if (!is_atomic_allowed (driver_name))
{
g_message ("Adding device '%s' (%s) using non-atomic mode setting"
" (using atomic mode setting not allowed).",
path, driver_name);
impl_device_file = meta_device_file_acquire (device_file);
impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE;
}
else
{
int ret;
ret = drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1);
if (ret == 0)
supports_atomic_mode_setting = TRUE;
else
supports_atomic_mode_setting = FALSE;
if (supports_atomic_mode_setting)
{
g_message ("Adding device '%s' (%s) using atomic mode setting.",
path, driver_name);
impl_device_type = META_TYPE_KMS_IMPL_DEVICE_ATOMIC;
}
else
{
g_message ("Adding device '%s' (%s) using non-atomic mode setting.",
path, driver_name);
impl_device_type = META_TYPE_KMS_IMPL_DEVICE_SIMPLE;
}
impl_device_file = meta_device_file_acquire (device_file);
}
impl_device = g_initable_new (impl_device_type, NULL, error,
"device", device, "device", device,
"impl", impl, "impl", impl,
"device-file", impl_device_file, "path", path,
"flags", flags, "flags", flags,
"driver-name", driver_name,
"driver-description", driver_description,
NULL); NULL);
if (!impl_device) }
return NULL; else
{
GType impl_device_types[] = {
META_TYPE_KMS_IMPL_DEVICE_ATOMIC,
META_TYPE_KMS_IMPL_DEVICE_SIMPLE,
};
int i;
for (i = 0; i < G_N_ELEMENTS (impl_device_types); i++)
{
MetaKmsImplDevice *impl_device;
g_autoptr (GError) local_error = NULL;
impl_device = g_initable_new (impl_device_types[i],
NULL, &local_error,
"device", device,
"impl", impl,
"path", path,
"flags", flags,
NULL);
if (impl_device)
return impl_device; return impl_device;
if (local_error->domain != META_KMS_ERROR)
{
g_warning ("Failed to open %s backend: %s",
impl_device_type_to_string (impl_device_types[i]),
local_error->message);
}
}
return NULL;
}
} }
static gpointer static gpointer
@ -421,7 +320,6 @@ create_impl_device_in_impl (MetaKmsImpl *impl,
impl_device = meta_create_kms_impl_device (data->device, impl_device = meta_create_kms_impl_device (data->device,
impl, impl,
data->device_file,
data->path, data->path,
data->flags, data->flags,
error); error);
@ -452,29 +350,14 @@ meta_kms_device_new (MetaKms *kms,
MetaKmsDeviceFlag flags, MetaKmsDeviceFlag flags,
GError **error) GError **error)
{ {
MetaBackend *backend = meta_kms_get_backend (kms);
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaDevicePool *device_pool =
meta_backend_native_get_device_pool (backend_native);
MetaKmsDevice *device; MetaKmsDevice *device;
CreateImplDeviceData data; CreateImplDeviceData data;
g_autoptr (MetaDeviceFile) device_file = NULL;
MetaDeviceFileFlags device_file_flags;
device_file_flags = META_DEVICE_FILE_FLAG_NONE;
if (!(flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING))
device_file_flags |= META_DEVICE_FILE_FLAG_TAKE_CONTROL;
device_file = meta_device_pool_open (device_pool, path, flags, error);
if (!device_file)
return NULL;
device = g_object_new (META_TYPE_KMS_DEVICE, NULL); device = g_object_new (META_TYPE_KMS_DEVICE, NULL);
device->kms = kms; device->kms = kms;
data = (CreateImplDeviceData) { data = (CreateImplDeviceData) {
.device = device, .device = device,
.device_file = device_file,
.path = path, .path = path,
.flags = flags, .flags = flags,
}; };

View File

@ -21,6 +21,7 @@
#include "backends/native/meta-kms-impl-device-atomic.h" #include "backends/native/meta-kms-impl-device-atomic.h"
#include "backends/native/meta-backend-native-private.h"
#include "backends/native/meta-kms-connector-private.h" #include "backends/native/meta-kms-connector-private.h"
#include "backends/native/meta-kms-crtc-private.h" #include "backends/native/meta-kms-crtc-private.h"
#include "backends/native/meta-kms-device-private.h" #include "backends/native/meta-kms-device-private.h"
@ -44,6 +45,8 @@ struct _MetaKmsImplDeviceAtomic
GHashTable *page_flip_datas; GHashTable *page_flip_datas;
}; };
static GInitableIface *initable_parent_iface;
static void static void
initable_iface_init (GInitableIface *iface); initable_iface_init (GInitableIface *iface);
@ -1039,14 +1042,83 @@ meta_kms_impl_device_atomic_finalize (GObject *object)
G_OBJECT_CLASS (meta_kms_impl_device_atomic_parent_class)->finalize (object); G_OBJECT_CLASS (meta_kms_impl_device_atomic_parent_class)->finalize (object);
} }
static MetaDeviceFile *
meta_kms_impl_device_atomic_open_device_file (MetaKmsImplDevice *impl_device,
const char *path,
GError **error)
{
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
MetaKms *kms = meta_kms_device_get_kms (device);
MetaBackend *backend = meta_kms_get_backend (kms);
MetaDevicePool *device_pool =
meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend));
g_autoptr (MetaDeviceFile) device_file = NULL;
device_file = meta_device_pool_open (device_pool, path,
META_DEVICE_FILE_FLAG_TAKE_CONTROL,
error);
if (!device_file)
return NULL;
if (drmSetClientCap (meta_device_file_get_fd (device_file),
DRM_CLIENT_CAP_ATOMIC, 1) != 0)
{
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
"DRM_CLIENT_CAP_ATOMIC not supported");
return NULL;
}
return g_steal_pointer (&device_file);
}
static gboolean
is_atomic_allowed (const char *driver_name)
{
const char *atomic_driver_deny_list[] = {
"qxl",
"vmwgfx",
"vboxvideo",
"nvidia-drm",
NULL,
};
return !g_strv_contains (atomic_driver_deny_list, driver_name);
}
static gboolean static gboolean
meta_kms_impl_device_atomic_initable_init (GInitable *initable, meta_kms_impl_device_atomic_initable_init (GInitable *initable,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable); MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
const char *atomic_kms_enable_env;
return meta_kms_impl_device_init_mode_setting (impl_device, error); atomic_kms_enable_env = getenv ("MUTTER_DEBUG_ENABLE_ATOMIC_KMS");
if (atomic_kms_enable_env && g_strcmp0 (atomic_kms_enable_env, "1") != 0)
{
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_USER_INHIBITED,
"Atomic mode setting disable via env var");
return FALSE;
}
if (!initable_parent_iface->init (initable, cancellable, error))
return FALSE;
if (!is_atomic_allowed (meta_kms_impl_device_get_driver_name (impl_device)))
{
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_DENY_LISTED,
"Atomic mode setting disable via driver deny list");
return FALSE;
}
if (!meta_kms_impl_device_init_mode_setting (impl_device, error))
return FALSE;
g_message ("Added device '%s' (%s) using atomic mode setting.",
meta_kms_impl_device_get_path (impl_device),
meta_kms_impl_device_get_driver_name (impl_device));
return TRUE;
} }
static void static void
@ -1058,6 +1130,8 @@ meta_kms_impl_device_atomic_init (MetaKmsImplDeviceAtomic *impl_device_atomic)
static void static void
initable_iface_init (GInitableIface *iface) initable_iface_init (GInitableIface *iface)
{ {
initable_parent_iface = g_type_interface_peek_parent (iface);
iface->init = meta_kms_impl_device_atomic_initable_init; iface->init = meta_kms_impl_device_atomic_initable_init;
} }
@ -1070,6 +1144,8 @@ meta_kms_impl_device_atomic_class_init (MetaKmsImplDeviceAtomicClass *klass)
object_class->finalize = meta_kms_impl_device_atomic_finalize; object_class->finalize = meta_kms_impl_device_atomic_finalize;
impl_device_class->open_device_file =
meta_kms_impl_device_atomic_open_device_file;
impl_device_class->setup_drm_event_context = impl_device_class->setup_drm_event_context =
meta_kms_impl_device_atomic_setup_drm_event_context; meta_kms_impl_device_atomic_setup_drm_event_context;
impl_device_class->process_update = impl_device_class->process_update =

View File

@ -21,15 +21,21 @@
#include "backends/native/meta-kms-impl-device-dummy.h" #include "backends/native/meta-kms-impl-device-dummy.h"
#include "backends/native/meta-backend-native-private.h"
#include "backends/native/meta-kms.h"
struct _MetaKmsImplDeviceDummy struct _MetaKmsImplDeviceDummy
{ {
MetaKmsImplDevice parent; MetaKmsImplDevice parent;
}; };
static GInitableIface *initable_parent_iface;
static void static void
initable_iface_init (GInitableIface *iface); initable_iface_init (GInitableIface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceDummy, meta_kms_impl_device_dummy, G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceDummy,
meta_kms_impl_device_dummy,
META_TYPE_KMS_IMPL_DEVICE, META_TYPE_KMS_IMPL_DEVICE,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init)) initable_iface_init))
@ -39,9 +45,43 @@ meta_kms_impl_device_dummy_discard_pending_page_flips (MetaKmsImplDevice *impl_d
{ {
} }
static void static MetaDeviceFile *
meta_kms_impl_device_dummy_init (MetaKmsImplDeviceDummy *impl_device_dummy) meta_kms_impl_device_dummy_open_device_file (MetaKmsImplDevice *impl_device,
const char *path,
GError **error)
{ {
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
MetaKms *kms = meta_kms_device_get_kms (device);
MetaBackend *backend = meta_kms_get_backend (kms);
MetaDevicePool *device_pool =
meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend));
g_autoptr (MetaDeviceFile) device_file = NULL;
int fd;
g_autofree char *render_node_path = NULL;
device_file = meta_device_pool_open (device_pool, path,
META_DEVICE_FILE_FLAG_NONE,
error);
if (!device_file)
return NULL;
fd = meta_device_file_get_fd (device_file);
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)",
meta_kms_impl_device_get_path (impl_device),
meta_kms_impl_device_get_driver_name (impl_device));
return NULL;
}
meta_topic (META_DEBUG_KMS, "Found render node '%s' from '%s'",
render_node_path, path);
return meta_device_pool_open (device_pool, render_node_path,
META_DEVICE_FILE_FLAG_NONE,
error);
} }
static gboolean static gboolean
@ -49,21 +89,39 @@ meta_kms_impl_device_dummy_initable_init (GInitable *initable,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
if (!initable_parent_iface->init (initable, cancellable, error))
return FALSE;
g_message ("Added device '%s' (%s) using no mode setting.",
meta_kms_impl_device_get_path (impl_device),
meta_kms_impl_device_get_driver_name (impl_device));
return TRUE; return TRUE;
} }
static void static void
initable_iface_init (GInitableIface *iface) initable_iface_init (GInitableIface *iface)
{ {
initable_parent_iface = g_type_interface_peek_parent (iface);
iface->init = meta_kms_impl_device_dummy_initable_init; iface->init = meta_kms_impl_device_dummy_initable_init;
} }
static void
meta_kms_impl_device_dummy_init (MetaKmsImplDeviceDummy *impl_device_dummy)
{
}
static void static void
meta_kms_impl_device_dummy_class_init (MetaKmsImplDeviceDummyClass *klass) meta_kms_impl_device_dummy_class_init (MetaKmsImplDeviceDummyClass *klass)
{ {
MetaKmsImplDeviceClass *impl_device_class = MetaKmsImplDeviceClass *impl_device_class =
META_KMS_IMPL_DEVICE_CLASS (klass); META_KMS_IMPL_DEVICE_CLASS (klass);
impl_device_class->open_device_file =
meta_kms_impl_device_dummy_open_device_file;
impl_device_class->discard_pending_page_flips = impl_device_class->discard_pending_page_flips =
meta_kms_impl_device_dummy_discard_pending_page_flips; meta_kms_impl_device_dummy_discard_pending_page_flips;
} }

View File

@ -21,6 +21,7 @@
#include "backends/native/meta-kms-impl-device-simple.h" #include "backends/native/meta-kms-impl-device-simple.h"
#include "backends/native/meta-backend-native-private.h"
#include "backends/native/meta-drm-buffer-gbm.h" #include "backends/native/meta-drm-buffer-gbm.h"
#include "backends/native/meta-kms-connector-private.h" #include "backends/native/meta-kms-connector-private.h"
#include "backends/native/meta-kms-crtc-private.h" #include "backends/native/meta-kms-crtc-private.h"
@ -60,6 +61,8 @@ struct _MetaKmsImplDeviceSimple
GHashTable *cached_mode_sets; GHashTable *cached_mode_sets;
}; };
static GInitableIface *initable_parent_iface;
static void static void
initable_iface_init (GInitableIface *iface); initable_iface_init (GInitableIface *iface);
@ -1534,6 +1537,22 @@ meta_kms_impl_device_simple_finalize (GObject *object)
G_OBJECT_CLASS (meta_kms_impl_device_simple_parent_class)->finalize (object); G_OBJECT_CLASS (meta_kms_impl_device_simple_parent_class)->finalize (object);
} }
static MetaDeviceFile *
meta_kms_impl_device_simple_open_device_file (MetaKmsImplDevice *impl_device,
const char *path,
GError **error)
{
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
MetaKms *kms = meta_kms_device_get_kms (device);
MetaBackend *backend = meta_kms_get_backend (kms);
MetaDevicePool *device_pool =
meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend));
return meta_device_pool_open (device_pool, path,
META_DEVICE_FILE_FLAG_TAKE_CONTROL,
error);
}
static gboolean static gboolean
meta_kms_impl_device_simple_initable_init (GInitable *initable, meta_kms_impl_device_simple_initable_init (GInitable *initable,
GCancellable *cancellable, GCancellable *cancellable,
@ -1545,6 +1564,9 @@ meta_kms_impl_device_simple_initable_init (GInitable *initable,
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
GList *l; GList *l;
if (!initable_parent_iface->init (initable, cancellable, error))
return FALSE;
if (!meta_kms_impl_device_init_mode_setting (impl_device, error)) if (!meta_kms_impl_device_init_mode_setting (impl_device, error))
return FALSE; return FALSE;
@ -1573,6 +1595,10 @@ meta_kms_impl_device_simple_initable_init (GInitable *initable,
crtc); crtc);
} }
g_message ("Added device '%s' (%s) using non-atomic mode setting.",
meta_kms_impl_device_get_path (impl_device),
meta_kms_impl_device_get_driver_name (impl_device));
return TRUE; return TRUE;
} }
@ -1584,6 +1610,8 @@ meta_kms_impl_device_simple_init (MetaKmsImplDeviceSimple *impl_device_simple)
static void static void
initable_iface_init (GInitableIface *iface) initable_iface_init (GInitableIface *iface)
{ {
initable_parent_iface = g_type_interface_peek_parent (iface);
iface->init = meta_kms_impl_device_simple_initable_init; iface->init = meta_kms_impl_device_simple_initable_init;
} }
@ -1596,6 +1624,8 @@ meta_kms_impl_device_simple_class_init (MetaKmsImplDeviceSimpleClass *klass)
object_class->finalize = meta_kms_impl_device_simple_finalize; object_class->finalize = meta_kms_impl_device_simple_finalize;
impl_device_class->open_device_file =
meta_kms_impl_device_simple_open_device_file;
impl_device_class->setup_drm_event_context = impl_device_class->setup_drm_event_context =
meta_kms_impl_device_simple_setup_drm_event_context; meta_kms_impl_device_simple_setup_drm_event_context;
impl_device_class->process_update = impl_device_class->process_update =

View File

@ -47,10 +47,8 @@ enum
PROP_DEVICE, PROP_DEVICE,
PROP_IMPL, PROP_IMPL,
PROP_DEVICE_FILE, PROP_PATH,
PROP_FLAGS, PROP_FLAGS,
PROP_DRIVER_NAME,
PROP_DRIVER_DESCRIPTION,
N_PROPS N_PROPS
}; };
@ -79,9 +77,16 @@ typedef struct _MetaKmsImplDevicePrivate
GList *fallback_modes; GList *fallback_modes;
} MetaKmsImplDevicePrivate; } MetaKmsImplDevicePrivate;
static void
initable_iface_init (GInitableIface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDevice, meta_kms_impl_device, G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDevice, meta_kms_impl_device,
G_TYPE_OBJECT, G_TYPE_OBJECT,
G_ADD_PRIVATE (MetaKmsImplDevice)) G_ADD_PRIVATE (MetaKmsImplDevice)
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init))
G_DEFINE_QUARK (-meta-kms-error-quark, meta_kms_error)
MetaKmsDevice * MetaKmsDevice *
meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device) meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device)
@ -711,18 +716,9 @@ meta_kms_impl_device_get_property (GObject *object,
case PROP_IMPL: case PROP_IMPL:
g_value_set_object (value, priv->impl); g_value_set_object (value, priv->impl);
break; break;
case PROP_DEVICE_FILE:
g_value_set_pointer (value, priv->device_file);
break;
case PROP_FLAGS: case PROP_FLAGS:
g_value_set_flags (value, priv->flags); g_value_set_flags (value, priv->flags);
break; break;
case PROP_DRIVER_NAME:
g_value_set_string (value, priv->driver_name);
break;
case PROP_DRIVER_DESCRIPTION:
g_value_set_string (value, priv->driver_name);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -747,19 +743,12 @@ meta_kms_impl_device_set_property (GObject *object,
case PROP_IMPL: case PROP_IMPL:
priv->impl = g_value_get_object (value); priv->impl = g_value_get_object (value);
break; break;
case PROP_DEVICE_FILE: case PROP_PATH:
priv->device_file = priv->path = g_value_dup_string (value);
meta_device_file_acquire (g_value_get_pointer (value));
break; break;
case PROP_FLAGS: case PROP_FLAGS:
priv->flags = g_value_get_flags (value); priv->flags = g_value_get_flags (value);
break; break;
case PROP_DRIVER_NAME:
priv->driver_name = g_value_dup_string (value);
break;
case PROP_DRIVER_DESCRIPTION:
priv->driver_description = g_value_dup_string (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -849,16 +838,52 @@ meta_kms_impl_device_prepare_shutdown (MetaKmsImplDevice *impl_device)
klass->prepare_shutdown (impl_device); klass->prepare_shutdown (impl_device);
} }
static void static gboolean
meta_kms_impl_device_constructed (GObject *object) get_driver_info (int fd,
char **name,
char **description)
{ {
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (object); drmVersion *drm_version;
drm_version = drmGetVersion (fd);
if (!drm_version)
return FALSE;
*name = g_strndup (drm_version->name,
drm_version->name_len);
*description = g_strndup (drm_version->desc,
drm_version->desc_len);
drmFreeVersion (drm_version);
return TRUE;
}
static gboolean
meta_kms_impl_device_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
MetaKmsImplDevicePrivate *priv = MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device); meta_kms_impl_device_get_instance_private (impl_device);
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
int fd;
priv->device_file = klass->open_device_file (impl_device, priv->path, error);
if (!priv->device_file)
return FALSE;
g_clear_pointer (&priv->path, g_free);
priv->path = g_strdup (meta_device_file_get_path (priv->device_file)); priv->path = g_strdup (meta_device_file_get_path (priv->device_file));
G_OBJECT_CLASS (meta_kms_impl_device_parent_class)->constructed (object); fd = meta_device_file_get_fd (priv->device_file);
if (!get_driver_info (fd, &priv->driver_name, &priv->driver_description))
{
priv->driver_name = g_strdup ("unknown");
priv->driver_description = g_strdup ("Unknown");
}
return TRUE;
} }
static void static void
@ -866,6 +891,12 @@ meta_kms_impl_device_init (MetaKmsImplDevice *impl_device)
{ {
} }
static void
initable_iface_init (GInitableIface *iface)
{
iface->init = meta_kms_impl_device_initable_init;
}
static void static void
meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass) meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass)
{ {
@ -873,7 +904,6 @@ meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass)
object_class->get_property = meta_kms_impl_device_get_property; object_class->get_property = meta_kms_impl_device_get_property;
object_class->set_property = meta_kms_impl_device_set_property; object_class->set_property = meta_kms_impl_device_set_property;
object_class->constructed = meta_kms_impl_device_constructed;
object_class->finalize = meta_kms_impl_device_finalize; object_class->finalize = meta_kms_impl_device_finalize;
obj_props[PROP_DEVICE] = obj_props[PROP_DEVICE] =
@ -892,11 +922,12 @@ meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass)
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS); G_PARAM_STATIC_STRINGS);
obj_props[PROP_DEVICE_FILE] = obj_props[PROP_PATH] =
g_param_spec_pointer ("device-file", g_param_spec_string ("path",
"device-file", "path",
"Device file", "Device path",
G_PARAM_READWRITE | NULL,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS); G_PARAM_STATIC_STRINGS);
obj_props[PROP_FLAGS] = obj_props[PROP_FLAGS] =
@ -908,21 +939,5 @@ meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass)
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS); G_PARAM_STATIC_STRINGS);
obj_props[PROP_DRIVER_NAME] =
g_param_spec_string ("driver-name",
"driver-name",
"DRM device driver name",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_DRIVER_DESCRIPTION] =
g_param_spec_string ("driver-description",
"driver-description",
"DRM device driver description",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, obj_props); g_object_class_install_properties (object_class, N_PROPS, obj_props);
} }

View File

@ -25,6 +25,7 @@
#include <xf86drm.h> #include <xf86drm.h>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include "backends/native/meta-device-pool.h"
#include "backends/native/meta-kms-device.h" #include "backends/native/meta-kms-device.h"
#include "backends/native/meta-kms-page-flip-private.h" #include "backends/native/meta-kms-page-flip-private.h"
#include "backends/native/meta-kms-types.h" #include "backends/native/meta-kms-types.h"
@ -62,6 +63,9 @@ struct _MetaKmsImplDeviceClass
{ {
GObjectClass parent_class; GObjectClass parent_class;
MetaDeviceFile * (* open_device_file) (MetaKmsImplDevice *impl_device,
const char *path,
GError **error);
void (* setup_drm_event_context) (MetaKmsImplDevice *impl_device, void (* setup_drm_event_context) (MetaKmsImplDevice *impl_device,
drmEventContext *drm_event_context); drmEventContext *drm_event_context);
MetaKmsFeedback * (* process_update) (MetaKmsImplDevice *impl_device, MetaKmsFeedback * (* process_update) (MetaKmsImplDevice *impl_device,
@ -73,6 +77,16 @@ struct _MetaKmsImplDeviceClass
void (* prepare_shutdown) (MetaKmsImplDevice *impl_device); void (* prepare_shutdown) (MetaKmsImplDevice *impl_device);
}; };
enum
{
META_KMS_ERROR_USER_INHIBITED,
META_KMS_ERROR_DENY_LISTED,
META_KMS_ERROR_NOT_SUPPORTED,
};
#define META_KMS_ERROR meta_kms_error_quark ()
GQuark meta_kms_error_quark (void);
MetaKmsDevice * meta_kms_impl_device_get_device (MetaKmsImplDevice *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_connectors (MetaKmsImplDevice *impl_device);