kms-device-impl: Implement leasing, revoking and listing leases
The lease_objects function takes connectors, CRTCs and planes which are turned into a drm lease. The resulting lease can be revoked with revoke_lease. With list_lessees the currently active leases can be queried. Co-authored-by: Sebastian Wick <sebastian.wick@redhat.com> Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3746>
This commit is contained in:
@ -423,6 +423,145 @@ meta_kms_device_handle_flush (MetaKmsDevice *device,
|
||||
return needs_flush;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaKmsDevice *device;
|
||||
GList *connectors;
|
||||
GList *crtcs;
|
||||
GList *planes;
|
||||
|
||||
int fd;
|
||||
uint32_t lessee_id;
|
||||
} LeaseRequestData;
|
||||
|
||||
static gpointer
|
||||
lease_objects_in_impl (MetaThreadImpl *thread_impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
LeaseRequestData *data = user_data;
|
||||
MetaKmsImplDevice *impl_device =
|
||||
meta_kms_device_get_impl_device (data->device);
|
||||
uint32_t lessee_id;
|
||||
int fd;
|
||||
|
||||
if (!meta_kms_impl_device_lease_objects (impl_device,
|
||||
data->connectors,
|
||||
data->crtcs,
|
||||
data->planes,
|
||||
&fd,
|
||||
&lessee_id,
|
||||
error))
|
||||
return GINT_TO_POINTER (FALSE);
|
||||
|
||||
data->fd = fd;
|
||||
data->lessee_id = lessee_id;
|
||||
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_device_lease_objects (MetaKmsDevice *device,
|
||||
GList *connectors,
|
||||
GList *crtcs,
|
||||
GList *planes,
|
||||
int *out_fd,
|
||||
uint32_t *out_lessee_id,
|
||||
GError **error)
|
||||
{
|
||||
LeaseRequestData data = {};
|
||||
|
||||
data.device = device;
|
||||
data.connectors = connectors;
|
||||
data.crtcs = crtcs;
|
||||
data.planes = planes;
|
||||
|
||||
if (!meta_kms_run_impl_task_sync (device->kms, lease_objects_in_impl, &data,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
*out_fd = data.fd;
|
||||
*out_lessee_id = data.lessee_id;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaKmsDevice *device;
|
||||
uint32_t lessee_id;
|
||||
} RevokeLeaseData;
|
||||
|
||||
static gpointer
|
||||
revoke_lease_in_impl (MetaThreadImpl *thread_impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
LeaseRequestData *data = user_data;
|
||||
MetaKmsImplDevice *impl_device =
|
||||
meta_kms_device_get_impl_device (data->device);
|
||||
|
||||
if (!meta_kms_impl_device_revoke_lease (impl_device, data->lessee_id, error))
|
||||
return GINT_TO_POINTER (FALSE);
|
||||
else
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_device_revoke_lease (MetaKmsDevice *device,
|
||||
uint32_t lessee_id,
|
||||
GError **error)
|
||||
{
|
||||
LeaseRequestData data = {};
|
||||
|
||||
data.device = device;
|
||||
data.lessee_id = lessee_id;
|
||||
|
||||
return !!meta_kms_run_impl_task_sync (device->kms, revoke_lease_in_impl, &data,
|
||||
error);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaKmsDevice *device;
|
||||
uint32_t **out_lessee_ids;
|
||||
int *out_num_lessee_ids;
|
||||
} ListLesseesData;
|
||||
|
||||
static gpointer
|
||||
list_lessees_in_impl (MetaThreadImpl *thread_impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
ListLesseesData *data = user_data;
|
||||
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (data->device);
|
||||
|
||||
if (!meta_kms_impl_device_list_lessees (impl_device,
|
||||
data->out_lessee_ids,
|
||||
data->out_num_lessee_ids,
|
||||
error))
|
||||
return GINT_TO_POINTER (FALSE);
|
||||
else
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_device_list_lessees (MetaKmsDevice *device,
|
||||
uint32_t **out_lessee_ids,
|
||||
int *out_num_lessee_ids,
|
||||
GError **error)
|
||||
{
|
||||
ListLesseesData data = {};
|
||||
|
||||
data.device = device;
|
||||
data.out_lessee_ids = out_lessee_ids;
|
||||
data.out_num_lessee_ids = out_num_lessee_ids;
|
||||
|
||||
return !!meta_kms_run_impl_task_sync (device->kms,
|
||||
list_lessees_in_impl,
|
||||
&data,
|
||||
error);
|
||||
}
|
||||
|
||||
typedef struct _CreateImplDeviceData
|
||||
{
|
||||
MetaKmsDevice *device;
|
||||
|
@ -86,6 +86,23 @@ gboolean meta_kms_device_handle_flush (MetaKmsDevice *device,
|
||||
META_EXPORT_TEST
|
||||
void meta_kms_device_disable (MetaKmsDevice *device);
|
||||
|
||||
gboolean meta_kms_device_lease_objects (MetaKmsDevice *device,
|
||||
GList *connectors,
|
||||
GList *crtcs,
|
||||
GList *planes,
|
||||
int *out_fd,
|
||||
uint32_t *out_lessee_id,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_kms_device_revoke_lease (MetaKmsDevice *device,
|
||||
uint32_t lessee_id,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_kms_device_list_lessees (MetaKmsDevice *device,
|
||||
uint32_t **out_lessee_ids,
|
||||
int *out_num_lessee_ids,
|
||||
GError **error);
|
||||
|
||||
MetaKmsDevice * meta_kms_device_new (MetaKms *kms,
|
||||
const char *path,
|
||||
MetaKmsDeviceFlag flags,
|
||||
|
@ -264,6 +264,188 @@ meta_kms_impl_device_get_path (MetaKmsImplDevice *impl_device)
|
||||
return priv->path;
|
||||
}
|
||||
|
||||
static MetaDeviceFile *
|
||||
meta_kms_impl_device_open_device_file (MetaKmsImplDevice *impl_device,
|
||||
const char *path,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
|
||||
|
||||
return klass->open_device_file (impl_device, priv->path, error);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
kms_event_dispatch_in_impl (MetaThreadImpl *impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevice *impl_device = user_data;
|
||||
gboolean ret;
|
||||
|
||||
ret = meta_kms_impl_device_dispatch (impl_device, error);
|
||||
return GINT_TO_POINTER (ret);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_device_file (MetaKmsImplDevice *impl_device,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaDeviceFile *device_file;
|
||||
|
||||
if (priv->device_file)
|
||||
return TRUE;
|
||||
|
||||
device_file = meta_kms_impl_device_open_device_file (impl_device,
|
||||
priv->path,
|
||||
error);
|
||||
if (!device_file)
|
||||
return FALSE;
|
||||
|
||||
priv->device_file = device_file;
|
||||
|
||||
if (!(priv->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING))
|
||||
{
|
||||
priv->fd_source =
|
||||
meta_thread_impl_register_fd (META_THREAD_IMPL (priv->impl),
|
||||
meta_device_file_get_fd (device_file),
|
||||
kms_event_dispatch_in_impl,
|
||||
impl_device);
|
||||
g_source_set_priority (priv->fd_source, G_PRIORITY_HIGH);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_impl_device_lease_objects (MetaKmsImplDevice *impl_device,
|
||||
GList *connectors,
|
||||
GList *crtcs,
|
||||
GList *planes,
|
||||
int *out_fd,
|
||||
uint32_t *out_lessee_id,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
uint32_t *object_ids;
|
||||
int n_object_ids;
|
||||
GList *l;
|
||||
int retval;
|
||||
uint32_t lessee_id;
|
||||
int i = 0;
|
||||
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
|
||||
|
||||
if (!ensure_device_file (impl_device, error))
|
||||
return FALSE;
|
||||
|
||||
meta_kms_impl_device_hold_fd (impl_device);
|
||||
|
||||
n_object_ids = (g_list_length (connectors) +
|
||||
g_list_length (crtcs) +
|
||||
g_list_length (planes));
|
||||
object_ids = g_alloca (sizeof (uint32_t) * n_object_ids);
|
||||
|
||||
for (l = connectors; l; l = l->next)
|
||||
{
|
||||
MetaKmsConnector *connector = l->data;
|
||||
|
||||
object_ids[i++] = meta_kms_connector_get_id (connector);
|
||||
}
|
||||
|
||||
for (l = crtcs; l; l = l->next)
|
||||
{
|
||||
MetaKmsCrtc *crtc = l->data;
|
||||
|
||||
object_ids[i++] = meta_kms_crtc_get_id (crtc);
|
||||
}
|
||||
|
||||
for (l = planes; l; l = l->next)
|
||||
{
|
||||
MetaKmsPlane *plane = l->data;
|
||||
|
||||
object_ids[i++] = meta_kms_plane_get_id (plane);
|
||||
}
|
||||
|
||||
retval = drmModeCreateLease (meta_kms_impl_device_get_fd (impl_device),
|
||||
object_ids, n_object_ids, 0,
|
||||
&lessee_id);
|
||||
|
||||
if (retval < 0)
|
||||
{
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-retval),
|
||||
"Failed to create lease: %s", g_strerror (-retval));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*out_fd = retval;
|
||||
*out_lessee_id = lessee_id;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_impl_device_revoke_lease (MetaKmsImplDevice *impl_device,
|
||||
uint32_t lessee_id,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
int retval;
|
||||
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
|
||||
|
||||
retval = drmModeRevokeLease (meta_kms_impl_device_get_fd (impl_device),
|
||||
lessee_id);
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
|
||||
if (retval != 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-retval),
|
||||
"Failed to revoke lease: %s", g_strerror (-retval));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_impl_device_list_lessees (MetaKmsImplDevice *impl_device,
|
||||
uint32_t **out_lessee_ids,
|
||||
int *out_num_lessee_ids,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
drmModeLesseeListRes *list;
|
||||
int i;
|
||||
uint32_t *lessee_ids;
|
||||
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
|
||||
|
||||
list = drmModeListLessees (meta_kms_impl_device_get_fd (impl_device));
|
||||
|
||||
if (!list)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to list lessees");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lessee_ids = g_new0 (uint32_t, list->count);
|
||||
for (i = 0; i < list->count; i++)
|
||||
lessee_ids[i] = list->lessees[i];
|
||||
|
||||
*out_lessee_ids = lessee_ids;
|
||||
*out_num_lessee_ids = list->count;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device,
|
||||
GError **error)
|
||||
@ -314,18 +496,6 @@ meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
kms_event_dispatch_in_impl (MetaThreadImpl *impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevice *impl_device = user_data;
|
||||
gboolean ret;
|
||||
|
||||
ret = meta_kms_impl_device_dispatch (impl_device, error);
|
||||
return GINT_TO_POINTER (ret);
|
||||
}
|
||||
|
||||
drmModePropertyPtr
|
||||
meta_kms_impl_device_find_property (MetaKmsImplDevice *impl_device,
|
||||
drmModeObjectProperties *props,
|
||||
@ -890,50 +1060,6 @@ init_fallback_modes (MetaKmsImplDevice *impl_device)
|
||||
priv->fallback_modes = g_list_reverse (modes);
|
||||
}
|
||||
|
||||
static MetaDeviceFile *
|
||||
meta_kms_impl_device_open_device_file (MetaKmsImplDevice *impl_device,
|
||||
const char *path,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
|
||||
|
||||
return klass->open_device_file (impl_device, priv->path, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_device_file (MetaKmsImplDevice *impl_device,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaDeviceFile *device_file;
|
||||
|
||||
if (priv->device_file)
|
||||
return TRUE;
|
||||
|
||||
device_file = meta_kms_impl_device_open_device_file (impl_device,
|
||||
priv->path,
|
||||
error);
|
||||
if (!device_file)
|
||||
return FALSE;
|
||||
|
||||
priv->device_file = device_file;
|
||||
|
||||
if (!(priv->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING))
|
||||
{
|
||||
priv->fd_source =
|
||||
meta_thread_impl_register_fd (META_THREAD_IMPL (priv->impl),
|
||||
meta_device_file_get_fd (device_file),
|
||||
kms_event_dispatch_in_impl,
|
||||
impl_device);
|
||||
g_source_set_priority (priv->fd_source, G_PRIORITY_HIGH);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_latched_fd_hold (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
|
@ -132,6 +132,23 @@ const char * meta_kms_impl_device_get_driver_description (MetaKmsImplDevice *imp
|
||||
|
||||
const char * meta_kms_impl_device_get_path (MetaKmsImplDevice *impl_device);
|
||||
|
||||
gboolean meta_kms_impl_device_lease_objects (MetaKmsImplDevice *impl_device,
|
||||
GList *connectors,
|
||||
GList *crtcs,
|
||||
GList *planes,
|
||||
int *out_fd,
|
||||
uint32_t *out_lessee_id,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_kms_impl_device_revoke_lease (MetaKmsImplDevice *impl_device,
|
||||
uint32_t lessee_id,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_kms_impl_device_list_lessees (MetaKmsImplDevice *impl_device,
|
||||
uint32_t **out_lessee_ids,
|
||||
int *out_num_lessee_ids,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device,
|
||||
GError **error);
|
||||
|
||||
|
Reference in New Issue
Block a user