native: Consolidate DRM buffer management to MetaDrmBuffer types
This commit consolidates DRM buffer management to the MetaDrmBuffer types, where the base type handles the common functionality (such as managing the framebuffer id using drmModeAdd*/RMFb()), and the sub types their corresponding type specific behavior. This means that drmModeAdd*/RmFB() handling is moved from meta-gpu-kms.c to meta-drm-buffer.c; dumb buffer allocation/management from meta-renderer-native.c. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Intel Corporation.
|
||||
* Copyright (C) 2016 Red Hat
|
||||
* Copyright (C) 2016-2020 Red Hat
|
||||
* Copyright (C) 2018 DisplayLink (UK) Ltd.
|
||||
* Copyright (C) 2018 Canonical Ltd.
|
||||
*
|
||||
@ -24,14 +24,298 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "backends/native/meta-drm-buffer.h"
|
||||
#include "backends/native/meta-drm-buffer-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaDrmBuffer, meta_drm_buffer, G_TYPE_OBJECT)
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#include "backends/native/meta-kms-device-private.h"
|
||||
#include "backends/native/meta-kms-impl-device.h"
|
||||
#include "backends/native/meta-kms-utils.h"
|
||||
#include "backends/native/meta-kms-private.h"
|
||||
|
||||
#define INVALID_FB_ID 0U
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_DEVICE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[N_PROPS];
|
||||
|
||||
typedef struct _MetaDrmBufferPrivate
|
||||
{
|
||||
MetaKmsDevice *device;
|
||||
uint32_t fb_id;
|
||||
} MetaDrmBufferPrivate;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaDrmBuffer, meta_drm_buffer,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
MetaKmsDevice *
|
||||
meta_drm_buffer_get_device (MetaDrmBuffer *buffer)
|
||||
{
|
||||
MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
|
||||
|
||||
return priv->device;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_drm_buffer_ensure_fb_in_impl (MetaDrmBuffer *buffer,
|
||||
gboolean use_modifiers,
|
||||
const MetaDrmFbArgs *fb_args,
|
||||
GError **error)
|
||||
{
|
||||
MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
|
||||
MetaKmsDevice *device = priv->device;
|
||||
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
||||
int fd;
|
||||
MetaDrmFormatBuf tmp;
|
||||
uint32_t fb_id;
|
||||
|
||||
fd = meta_kms_impl_device_get_fd (impl_device);
|
||||
|
||||
if (use_modifiers && fb_args->modifiers[0] != DRM_FORMAT_MOD_INVALID)
|
||||
{
|
||||
if (drmModeAddFB2WithModifiers (fd,
|
||||
fb_args->width,
|
||||
fb_args->height,
|
||||
fb_args->format,
|
||||
fb_args->handles,
|
||||
fb_args->strides,
|
||||
fb_args->offsets,
|
||||
fb_args->modifiers,
|
||||
&fb_id,
|
||||
DRM_MODE_FB_MODIFIERS))
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_errno (errno),
|
||||
"drmModeAddFB2WithModifiers failed: %s",
|
||||
g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (drmModeAddFB2 (fd,
|
||||
fb_args->width,
|
||||
fb_args->height,
|
||||
fb_args->format,
|
||||
fb_args->handles,
|
||||
fb_args->strides,
|
||||
fb_args->offsets,
|
||||
&fb_id,
|
||||
0))
|
||||
{
|
||||
if (fb_args->format != DRM_FORMAT_XRGB8888)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"drmModeAddFB does not support format '%s' (0x%x)",
|
||||
meta_drm_format_to_string (&tmp, fb_args->format),
|
||||
fb_args->format);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (drmModeAddFB (fd,
|
||||
fb_args->width,
|
||||
fb_args->height,
|
||||
24,
|
||||
32,
|
||||
fb_args->strides[0],
|
||||
fb_args->handles[0],
|
||||
&fb_id))
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_errno (errno),
|
||||
"drmModeAddFB failed: %s",
|
||||
g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
priv->fb_id = fb_id;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaDrmBuffer *buffer;
|
||||
gboolean use_modifiers;
|
||||
MetaDrmFbArgs fb_args;
|
||||
} AddFbData;
|
||||
|
||||
static gpointer
|
||||
add_fb_in_impl (MetaKmsImpl *impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
AddFbData *data = user_data;
|
||||
|
||||
if (meta_drm_buffer_ensure_fb_in_impl (data->buffer,
|
||||
data->use_modifiers,
|
||||
&data->fb_args,
|
||||
error))
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
else
|
||||
return GINT_TO_POINTER (FALSE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_drm_buffer_ensure_fb_id (MetaDrmBuffer *buffer,
|
||||
gboolean use_modifiers,
|
||||
const MetaDrmFbArgs *fb_args,
|
||||
GError **error)
|
||||
{
|
||||
MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
|
||||
AddFbData data;
|
||||
|
||||
data = (AddFbData) {
|
||||
.buffer = buffer,
|
||||
.use_modifiers = use_modifiers,
|
||||
.fb_args = *fb_args,
|
||||
};
|
||||
|
||||
if (!meta_kms_run_impl_task_sync (meta_kms_device_get_kms (priv->device),
|
||||
add_fb_in_impl,
|
||||
&data,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaKmsDevice *device;
|
||||
uint32_t fb_id;
|
||||
} RmFbData;
|
||||
|
||||
static gpointer
|
||||
rm_fb_in_impl (MetaKmsImpl *impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
RmFbData *data = user_data;
|
||||
MetaKmsDevice *device = data->device;
|
||||
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
||||
uint32_t fb_id = data->fb_id;
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
fd = meta_kms_impl_device_get_fd (impl_device);
|
||||
ret = drmModeRmFB (fd, fb_id);
|
||||
if (ret != 0)
|
||||
g_warning ("drmModeRmFB: %s", g_strerror (-ret));
|
||||
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_drm_buffer_release_fb_id (MetaDrmBuffer *buffer)
|
||||
{
|
||||
MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
|
||||
RmFbData data;
|
||||
|
||||
data = (RmFbData) {
|
||||
.device = priv->device,
|
||||
.fb_id = priv->fb_id,
|
||||
};
|
||||
|
||||
meta_kms_run_impl_task_sync (meta_kms_device_get_kms (priv->device),
|
||||
rm_fb_in_impl,
|
||||
&data,
|
||||
NULL);
|
||||
priv->fb_id = 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
meta_drm_buffer_get_fb_id (MetaDrmBuffer *buffer)
|
||||
{
|
||||
return META_DRM_BUFFER_GET_CLASS (buffer)->get_fb_id (buffer);
|
||||
MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
|
||||
|
||||
return priv->fb_id;
|
||||
}
|
||||
|
||||
int
|
||||
meta_drm_buffer_get_width (MetaDrmBuffer *buffer)
|
||||
{
|
||||
return META_DRM_BUFFER_GET_CLASS (buffer)->get_width (buffer);
|
||||
}
|
||||
|
||||
int
|
||||
meta_drm_buffer_get_height (MetaDrmBuffer *buffer)
|
||||
{
|
||||
return META_DRM_BUFFER_GET_CLASS (buffer)->get_height (buffer);
|
||||
}
|
||||
|
||||
int
|
||||
meta_drm_buffer_get_stride (MetaDrmBuffer *buffer)
|
||||
{
|
||||
return META_DRM_BUFFER_GET_CLASS (buffer)->get_stride (buffer);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
meta_drm_buffer_get_format (MetaDrmBuffer *buffer)
|
||||
{
|
||||
return META_DRM_BUFFER_GET_CLASS (buffer)->get_format (buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_drm_buffer_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDrmBuffer *buffer = META_DRM_BUFFER (object);
|
||||
MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DEVICE:
|
||||
g_value_set_object (value, priv->device);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_drm_buffer_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDrmBuffer *buffer = META_DRM_BUFFER (object);
|
||||
MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DEVICE:
|
||||
priv->device = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_drm_buffer_finalize (GObject *object)
|
||||
{
|
||||
MetaDrmBuffer *buffer = META_DRM_BUFFER (object);
|
||||
MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer);
|
||||
|
||||
if (priv->fb_id != INVALID_FB_ID)
|
||||
meta_drm_buffer_release_fb_id (buffer);
|
||||
|
||||
G_OBJECT_CLASS (meta_drm_buffer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -42,4 +326,19 @@ meta_drm_buffer_init (MetaDrmBuffer *buffer)
|
||||
static void
|
||||
meta_drm_buffer_class_init (MetaDrmBufferClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = meta_drm_buffer_get_property;
|
||||
object_class->set_property = meta_drm_buffer_set_property;
|
||||
object_class->finalize = meta_drm_buffer_finalize;
|
||||
|
||||
obj_props[PROP_DEVICE] =
|
||||
g_param_spec_object ("device",
|
||||
"device",
|
||||
"MetaKmsDevice",
|
||||
META_TYPE_KMS_DEVICE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
||||
}
|
||||
|
Reference in New Issue
Block a user