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:
Jonas Ådahl 2020-09-29 09:40:53 +02:00 committed by Marge Bot
parent 40e5633fab
commit 84bde805fe
15 changed files with 880 additions and 435 deletions

View File

@ -25,41 +25,322 @@
#include "backends/native/meta-drm-buffer-dumb.h"
#include <xf86drm.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "backends/native/meta-kms-device-private.h"
#include "backends/native/meta-kms-impl-device.h"
#include "backends/native/meta-kms-private.h"
struct _MetaDrmBufferDumb
{
MetaDrmBuffer parent;
uint32_t fb_id;
uint32_t handle;
void *map;
uint64_t map_size;
int width;
int height;
int stride_bytes;
uint32_t drm_format;
int dmabuf_fd;
};
G_DEFINE_TYPE (MetaDrmBufferDumb, meta_drm_buffer_dumb, META_TYPE_DRM_BUFFER)
MetaDrmBufferDumb *
meta_drm_buffer_dumb_new (uint32_t dumb_fb_id)
static int
meta_drm_buffer_dumb_get_width (MetaDrmBuffer *buffer)
{
MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer);
return buffer_dumb->width;
}
static int
meta_drm_buffer_dumb_get_height (MetaDrmBuffer *buffer)
{
MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer);
return buffer_dumb->height;
}
static int
meta_drm_buffer_dumb_get_stride (MetaDrmBuffer *buffer)
{
MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer);
return buffer_dumb->stride_bytes;
}
static uint32_t
meta_drm_buffer_dumb_get_format (MetaDrmBuffer *buffer)
{
MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer);
return buffer_dumb->drm_format;
}
typedef struct
{
MetaDrmBufferDumb *buffer_dumb;
buffer_dumb = g_object_new (META_TYPE_DRM_BUFFER_DUMB, NULL);
buffer_dumb->fb_id = dumb_fb_id;
int out_dmabuf_fd;
} HandleToFdData;
static gpointer
handle_to_fd_in_impl (MetaKmsImpl *impl,
gpointer user_data,
GError **error)
{
HandleToFdData *data = user_data;
MetaDrmBufferDumb *buffer_dumb = data->buffer_dumb;
MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
int fd;
int ret;
int dmabuf_fd;
fd = meta_kms_impl_device_get_fd (impl_device);
ret = drmPrimeHandleToFD (fd, buffer_dumb->handle, DRM_CLOEXEC,
&dmabuf_fd);
if (ret)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
"drmPrimeHandleToFd: %s", g_strerror (-ret));
return GINT_TO_POINTER (FALSE);
}
data->out_dmabuf_fd = dmabuf_fd;
return GINT_TO_POINTER (TRUE);
}
int
meta_drm_buffer_dumb_ensure_dmabuf_fd (MetaDrmBufferDumb *buffer_dumb,
GError **error)
{
MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
HandleToFdData data;
if (buffer_dumb->dmabuf_fd != -1)
return buffer_dumb->dmabuf_fd;
data = (HandleToFdData) {
.buffer_dumb = buffer_dumb,
};
if (!meta_kms_run_impl_task_sync (meta_kms_device_get_kms (device),
handle_to_fd_in_impl,
&data,
error))
return -1;
buffer_dumb->dmabuf_fd = data.out_dmabuf_fd;
return buffer_dumb->dmabuf_fd;
}
void *
meta_drm_buffer_dumb_get_data (MetaDrmBufferDumb *buffer_dumb)
{
return buffer_dumb->map;
}
typedef struct
{
MetaDrmBufferDumb *buffer_dumb;
int width;
int height;
uint32_t format;
} InitDumbData;
static gpointer
init_dumb_buffer_in_impl (MetaKmsImpl *impl,
gpointer user_data,
GError **error)
{
InitDumbData *data = user_data;
MetaDrmBufferDumb *buffer_dumb = data->buffer_dumb;
MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
int fd;
struct drm_mode_create_dumb create_arg;
struct drm_mode_destroy_dumb destroy_arg;
struct drm_mode_map_dumb map_arg;
void *map;
MetaDrmFbArgs fb_args;
fd = meta_kms_impl_device_get_fd (impl_device);
create_arg = (struct drm_mode_create_dumb) {
.bpp = 32, /* RGBX8888 */
.width = data->width,
.height = data->height
};
if (drmIoctl (fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg) != 0)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Failed to create dumb drm buffer: %s",
g_strerror (errno));
goto err_ioctl;
}
fb_args = (MetaDrmFbArgs) {
.width = data->width,
.height = data->height,
.format = data->format,
.handles = { create_arg.handle },
.strides = { create_arg.pitch },
};
if (!meta_drm_buffer_ensure_fb_id (buffer, FALSE, &fb_args, error))
goto err_add_fb;
map_arg = (struct drm_mode_map_dumb) {
.handle = create_arg.handle
};
if (drmIoctl (fd, DRM_IOCTL_MODE_MAP_DUMB,
&map_arg) != 0)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Failed to map dumb drm buffer: %s",
g_strerror (errno));
goto err_map_dumb;
}
map = mmap (NULL, create_arg.size, PROT_WRITE, MAP_SHARED,
fd, map_arg.offset);
if (map == MAP_FAILED)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Failed to mmap dumb drm buffer memory: %s",
g_strerror (errno));
goto err_mmap;
}
buffer_dumb->handle = create_arg.handle;
buffer_dumb->map = map;
buffer_dumb->map_size = create_arg.size;
buffer_dumb->width = data->width;
buffer_dumb->height = data->height;
buffer_dumb->stride_bytes = create_arg.pitch;
buffer_dumb->drm_format = data->format;
return FALSE;
err_mmap:
err_map_dumb:
err_add_fb:
destroy_arg = (struct drm_mode_destroy_dumb) {
.handle = create_arg.handle
};
drmIoctl (fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
err_ioctl:
return FALSE;
}
MetaDrmBufferDumb *
meta_drm_buffer_dumb_new (MetaKmsDevice *device,
int width,
int height,
uint32_t format,
GError **error)
{
MetaDrmBufferDumb *buffer_dumb;
InitDumbData data;
buffer_dumb = g_object_new (META_TYPE_DRM_BUFFER_DUMB,
"device", device,
NULL);
data = (InitDumbData) {
.buffer_dumb = buffer_dumb,
.width = width,
.height = height,
.format = format,
};
if (meta_kms_run_impl_task_sync (meta_kms_device_get_kms (device),
init_dumb_buffer_in_impl,
&data,
error))
{
g_object_unref (buffer_dumb);
return NULL;
}
return buffer_dumb;
}
static uint32_t
meta_drm_buffer_dumb_get_fb_id (MetaDrmBuffer *buffer)
static gpointer
destroy_dumb_in_impl (MetaKmsImpl *impl,
gpointer user_data,
GError **error)
{
return META_DRM_BUFFER_DUMB (buffer)->fb_id;
MetaDrmBufferDumb *buffer_dumb = user_data;
MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
int fd;
struct drm_mode_destroy_dumb destroy_arg;
fd = meta_kms_impl_device_get_fd (impl_device);
munmap (buffer_dumb->map, buffer_dumb->map_size);
destroy_arg = (struct drm_mode_destroy_dumb) {
.handle = buffer_dumb->handle
};
drmIoctl (fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
if (buffer_dumb->dmabuf_fd != -1)
close (buffer_dumb->dmabuf_fd);
return GINT_TO_POINTER (TRUE);
}
static void
meta_drm_buffer_dumb_finalize (GObject *object)
{
MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (object);
if (buffer_dumb->handle)
{
MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb);
MetaKmsDevice *device = meta_drm_buffer_get_device (buffer);
meta_kms_run_impl_task_sync (meta_kms_device_get_kms (device),
destroy_dumb_in_impl,
buffer_dumb,
NULL);
}
G_OBJECT_CLASS (meta_drm_buffer_dumb_parent_class)->finalize (object);
}
static void
meta_drm_buffer_dumb_init (MetaDrmBufferDumb *buffer_dumb)
{
buffer_dumb->dmabuf_fd = -1;
}
static void
meta_drm_buffer_dumb_class_init (MetaDrmBufferDumbClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaDrmBufferClass *buffer_class = META_DRM_BUFFER_CLASS (klass);
buffer_class->get_fb_id = meta_drm_buffer_dumb_get_fb_id;
object_class->finalize = meta_drm_buffer_dumb_finalize;
buffer_class->get_width = meta_drm_buffer_dumb_get_width;
buffer_class->get_height = meta_drm_buffer_dumb_get_height;
buffer_class->get_stride = meta_drm_buffer_dumb_get_stride;
buffer_class->get_format = meta_drm_buffer_dumb_get_format;
}

View File

@ -22,7 +22,8 @@
#ifndef META_DRM_BUFFER_DUMB_H
#define META_DRM_BUFFER_DUMB_H
#include "backends/native/meta-drm-buffer.h"
#include "backends/native/meta-drm-buffer-private.h"
#include "backends/native/meta-kms-device.h"
#define META_TYPE_DRM_BUFFER_DUMB (meta_drm_buffer_dumb_get_type ())
G_DECLARE_FINAL_TYPE (MetaDrmBufferDumb,
@ -30,6 +31,15 @@ G_DECLARE_FINAL_TYPE (MetaDrmBufferDumb,
META, DRM_BUFFER_DUMB,
MetaDrmBuffer)
MetaDrmBufferDumb * meta_drm_buffer_dumb_new (uint32_t dumb_fb_id);
MetaDrmBufferDumb * meta_drm_buffer_dumb_new (MetaKmsDevice *device,
int width,
int height,
uint32_t format,
GError **error);
int meta_drm_buffer_dumb_ensure_dmabuf_fd (MetaDrmBufferDumb *buffer_dumb,
GError **error);
void * meta_drm_buffer_dumb_get_data (MetaDrmBufferDumb *buffer_dumb);
#endif /* META_DRM_BUFFER_DUMB_H */

View File

@ -23,7 +23,6 @@
#include "config.h"
#include "backends/native/meta-cogl-utils.h"
#include "backends/native/meta-drm-buffer-gbm.h"
#include <drm_fourcc.h>
@ -31,18 +30,16 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#define INVALID_FB_ID 0U
#include "backends/native/meta-drm-buffer-private.h"
#include "backends/native/meta-cogl-utils.h"
struct _MetaDrmBufferGbm
{
MetaDrmBuffer parent;
MetaGpuKms *gpu_kms;
struct gbm_surface *surface;
struct gbm_bo *bo;
uint32_t fb_id;
};
static void
@ -58,13 +55,45 @@ meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm)
return buffer_gbm->bo;
}
static int
meta_drm_buffer_gbm_get_width (MetaDrmBuffer *buffer)
{
MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer);
return gbm_bo_get_width (buffer_gbm->bo);
}
static int
meta_drm_buffer_gbm_get_height (MetaDrmBuffer *buffer)
{
MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer);
return gbm_bo_get_height (buffer_gbm->bo);
}
static int
meta_drm_buffer_gbm_get_stride (MetaDrmBuffer *buffer)
{
MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer);
return gbm_bo_get_stride (buffer_gbm->bo);
}
static uint32_t
meta_drm_buffer_gbm_get_format (MetaDrmBuffer *buffer)
{
MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer);
return gbm_bo_get_format (buffer_gbm->bo);
}
static gboolean
init_fb_id (MetaDrmBufferGbm *buffer_gbm,
struct gbm_bo *bo,
gboolean use_modifiers,
GError **error)
{
MetaGpuKmsFBArgs fb_args = { 0, };
MetaDrmFbArgs fb_args = { 0, };
if (gbm_bo_get_handle_for_plane (bo, 0).s32 == -1)
{
@ -91,10 +120,8 @@ init_fb_id (MetaDrmBufferGbm *buffer_gbm,
fb_args.height = gbm_bo_get_height (bo);
fb_args.format = gbm_bo_get_format (bo);
if (!meta_gpu_kms_add_fb (buffer_gbm->gpu_kms,
use_modifiers,
&fb_args,
&buffer_gbm->fb_id, error))
if (!meta_drm_buffer_ensure_fb_id (META_DRM_BUFFER (buffer_gbm),
use_modifiers, &fb_args, error))
return FALSE;
return TRUE;
@ -119,15 +146,16 @@ lock_front_buffer (MetaDrmBufferGbm *buffer_gbm,
}
MetaDrmBufferGbm *
meta_drm_buffer_gbm_new_lock_front (MetaGpuKms *gpu_kms,
meta_drm_buffer_gbm_new_lock_front (MetaKmsDevice *device,
struct gbm_surface *gbm_surface,
gboolean use_modifiers,
GError **error)
{
MetaDrmBufferGbm *buffer_gbm;
buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM, NULL);
buffer_gbm->gpu_kms = gpu_kms;
buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM,
"device", device,
NULL);
buffer_gbm->surface = gbm_surface;
if (!lock_front_buffer (buffer_gbm, use_modifiers, error))
@ -140,15 +168,16 @@ meta_drm_buffer_gbm_new_lock_front (MetaGpuKms *gpu_kms,
}
MetaDrmBufferGbm *
meta_drm_buffer_gbm_new_take (MetaGpuKms *gpu_kms,
meta_drm_buffer_gbm_new_take (MetaKmsDevice *device,
struct gbm_bo *bo,
gboolean use_modifiers,
GError **error)
{
MetaDrmBufferGbm *buffer_gbm;
buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM, NULL);
buffer_gbm->gpu_kms = gpu_kms;
buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM,
"device", device,
NULL);
if (!init_fb_id (buffer_gbm, bo, use_modifiers, error))
{
@ -161,12 +190,6 @@ meta_drm_buffer_gbm_new_take (MetaGpuKms *gpu_kms,
return buffer_gbm;
}
static uint32_t
meta_drm_buffer_gbm_get_fb_id (MetaDrmBuffer *buffer)
{
return META_DRM_BUFFER_GBM (buffer)->fb_id;
}
static gboolean
meta_drm_buffer_gbm_blit_to_framebuffer (CoglScanout *scanout,
CoglFramebuffer *framebuffer,
@ -308,14 +331,6 @@ meta_drm_buffer_gbm_finalize (GObject *object)
{
MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (object);
if (buffer_gbm->fb_id != INVALID_FB_ID)
{
int kms_fd;
kms_fd = meta_gpu_kms_get_fd (buffer_gbm->gpu_kms);
drmModeRmFB (kms_fd, buffer_gbm->fb_id);
}
if (buffer_gbm->bo)
{
if (buffer_gbm->surface)
@ -340,5 +355,8 @@ meta_drm_buffer_gbm_class_init (MetaDrmBufferGbmClass *klass)
object_class->finalize = meta_drm_buffer_gbm_finalize;
buffer_class->get_fb_id = meta_drm_buffer_gbm_get_fb_id;
buffer_class->get_width = meta_drm_buffer_gbm_get_width;
buffer_class->get_height = meta_drm_buffer_gbm_get_height;
buffer_class->get_stride = meta_drm_buffer_gbm_get_stride;
buffer_class->get_format = meta_drm_buffer_gbm_get_format;
}

View File

@ -24,7 +24,7 @@
#include <gbm.h>
#include "backends/native/meta-drm-buffer.h"
#include "backends/native/meta-drm-buffer-private.h"
#include "backends/native/meta-gpu-kms.h"
#define META_TYPE_DRM_BUFFER_GBM (meta_drm_buffer_gbm_get_type ())
@ -33,13 +33,13 @@ G_DECLARE_FINAL_TYPE (MetaDrmBufferGbm,
META, DRM_BUFFER_GBM,
MetaDrmBuffer)
MetaDrmBufferGbm * meta_drm_buffer_gbm_new_lock_front (MetaGpuKms *gpu_kms,
MetaDrmBufferGbm * meta_drm_buffer_gbm_new_lock_front (MetaKmsDevice *device,
struct gbm_surface *gbm_surface,
gboolean use_modifiers,
GError **error);
MetaDrmBufferGbm * meta_drm_buffer_gbm_new_take (MetaGpuKms *gpu_kms,
MetaDrmBufferGbm * meta_drm_buffer_gbm_new_take (MetaKmsDevice *device,
struct gbm_bo *gbm_bo,
gboolean use_modifiers,
GError **error);

View File

@ -34,22 +34,48 @@
#include "backends/native/meta-kms-utils.h"
#include "backends/native/meta-renderer-native.h"
#define INVALID_FB_ID 0U
struct _MetaDrmBufferImport
{
MetaDrmBuffer parent;
MetaGpuKms *gpu_kms;
MetaDrmBufferGbm *importee;
uint32_t fb_id;
};
G_DEFINE_TYPE (MetaDrmBufferImport, meta_drm_buffer_import,
META_TYPE_DRM_BUFFER)
static int
meta_drm_buffer_import_get_width (MetaDrmBuffer *buffer)
{
MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer);
return meta_drm_buffer_get_width (META_DRM_BUFFER (buffer_import->importee));
}
static int
meta_drm_buffer_import_get_height (MetaDrmBuffer *buffer)
{
MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer);
return meta_drm_buffer_get_height (META_DRM_BUFFER (buffer_import->importee));
}
static int
meta_drm_buffer_import_get_stride (MetaDrmBuffer *buffer)
{
MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer);
return meta_drm_buffer_get_stride (META_DRM_BUFFER (buffer_import->importee));
}
static uint32_t
meta_drm_buffer_import_get_format (MetaDrmBuffer *buffer)
{
MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer);
return meta_drm_buffer_get_format (META_DRM_BUFFER (buffer_import->importee));
}
static struct gbm_bo *
dmabuf_to_gbm_bo (struct gbm_device *importer,
int dmabuf_fd,
@ -74,19 +100,15 @@ dmabuf_to_gbm_bo (struct gbm_device *importer,
static gboolean
import_gbm_buffer (MetaDrmBufferImport *buffer_import,
struct gbm_device *importer,
GError **error)
{
MetaGpuKmsFBArgs fb_args = { 0, };
MetaDrmFbArgs fb_args = { 0, };
struct gbm_bo *primary_bo;
struct gbm_device *importer;
struct gbm_bo *imported_bo;
int dmabuf_fd;
gboolean ret;
g_assert (buffer_import->fb_id == INVALID_FB_ID);
importer = meta_gbm_device_from_gpu (buffer_import->gpu_kms);
primary_bo = meta_drm_buffer_gbm_get_bo (buffer_import->importee);
dmabuf_fd = gbm_bo_get_fd (primary_bo);
@ -122,11 +144,10 @@ import_gbm_buffer (MetaDrmBufferImport *buffer_import,
fb_args.handles[0] = gbm_bo_get_handle (imported_bo).u32;
ret = meta_gpu_kms_add_fb (buffer_import->gpu_kms,
FALSE /* use_modifiers */,
&fb_args,
&buffer_import->fb_id,
error);
ret = meta_drm_buffer_ensure_fb_id (META_DRM_BUFFER (buffer_import),
FALSE /* use_modifiers */,
&fb_args,
error);
gbm_bo_destroy (imported_bo);
@ -137,17 +158,19 @@ out_close:
}
MetaDrmBufferImport *
meta_drm_buffer_import_new (MetaGpuKms *gpu_kms,
MetaDrmBufferGbm *buffer_gbm,
GError **error)
meta_drm_buffer_import_new (MetaKmsDevice *device,
struct gbm_device *gbm_device,
MetaDrmBufferGbm *buffer_gbm,
GError **error)
{
MetaDrmBufferImport *buffer_import;
buffer_import = g_object_new (META_TYPE_DRM_BUFFER_IMPORT, NULL);
buffer_import->gpu_kms = gpu_kms;
buffer_import = g_object_new (META_TYPE_DRM_BUFFER_IMPORT,
"device", device,
NULL);
g_set_object (&buffer_import->importee, buffer_gbm);
if (!import_gbm_buffer (buffer_import, error))
if (!import_gbm_buffer (buffer_import, gbm_device, error))
{
g_object_unref (buffer_import);
return NULL;
@ -156,25 +179,11 @@ meta_drm_buffer_import_new (MetaGpuKms *gpu_kms,
return buffer_import;
}
static uint32_t
meta_drm_buffer_import_get_fb_id (MetaDrmBuffer *buffer)
{
return META_DRM_BUFFER_IMPORT (buffer)->fb_id;
}
static void
meta_drm_buffer_import_finalize (GObject *object)
{
MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (object);
if (buffer_import->fb_id != INVALID_FB_ID)
{
int kms_fd;
kms_fd = meta_gpu_kms_get_fd (buffer_import->gpu_kms);
drmModeRmFB (kms_fd, buffer_import->fb_id);
}
g_clear_object (&buffer_import->importee);
G_OBJECT_CLASS (meta_drm_buffer_import_parent_class)->finalize (object);
@ -193,5 +202,8 @@ meta_drm_buffer_import_class_init (MetaDrmBufferImportClass *klass)
object_class->finalize = meta_drm_buffer_import_finalize;
buffer_class->get_fb_id = meta_drm_buffer_import_get_fb_id;
buffer_class->get_width = meta_drm_buffer_import_get_width;
buffer_class->get_height = meta_drm_buffer_import_get_height;
buffer_class->get_stride = meta_drm_buffer_import_get_stride;
buffer_class->get_format = meta_drm_buffer_import_get_format;
}

View File

@ -47,8 +47,9 @@ G_DECLARE_FINAL_TYPE (MetaDrmBufferImport,
* The import has a high chance of failing under normal operating
* conditions and needs to be handled with fallbacks to something else.
*/
MetaDrmBufferImport * meta_drm_buffer_import_new (MetaGpuKms *gpu_kms,
MetaDrmBufferGbm *buffer_gbm,
GError **error);
MetaDrmBufferImport * meta_drm_buffer_import_new (MetaKmsDevice *device,
struct gbm_device *gbm_device,
MetaDrmBufferGbm *buffer_gbm,
GError **error);
#endif /* META_DRM_BUFFER_IMPORT_H */

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2018 Canonical Ltd.
* Copyright (C) 2019-2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_DRM_BUFFER_PRIVATE_H
#define META_DRM_BUFFER_PRIVATE_H
#include "backends/native/meta-drm-buffer.h"
#include "backends/native/meta-kms-device.h"
typedef struct _MetaDrmFbArgs
{
uint32_t width;
uint32_t height;
uint32_t format;
uint32_t handles[4];
uint32_t offsets[4];
uint32_t strides[4];
uint64_t modifiers[4];
} MetaDrmFbArgs;
struct _MetaDrmBufferClass
{
GObjectClass parent_class;
int (* get_width) (MetaDrmBuffer *buffer);
int (* get_height) (MetaDrmBuffer *buffer);
int (* get_stride) (MetaDrmBuffer *buffer);
uint32_t (* get_format) (MetaDrmBuffer *buffer);
};
MetaKmsDevice * meta_drm_buffer_get_device (MetaDrmBuffer *buffer);
gboolean meta_drm_buffer_ensure_fb_id (MetaDrmBuffer *buffer,
gboolean use_modifiers,
const MetaDrmFbArgs *fb_args,
GError **error);
gboolean meta_drm_buffer_ensure_fb_in_impl (MetaDrmBuffer *buffer,
gboolean use_modifiers,
const MetaDrmFbArgs *fb_args,
GError **error);
#endif /* META_DRM_BUFFER_PRIVATE_H */

View File

@ -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);
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2018 Canonical Ltd.
* Copyright (C) 2019-2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -31,16 +32,14 @@ G_DECLARE_DERIVABLE_TYPE (MetaDrmBuffer,
META, DRM_BUFFER,
GObject)
struct _MetaDrmBufferClass
{
GObjectClass parent_class;
uint32_t (* get_fb_id) (MetaDrmBuffer *buffer);
};
MetaDrmBuffer *
meta_drm_buffer_new_from_dumb (uint32_t dumb_fb_id);
uint32_t meta_drm_buffer_get_fb_id (MetaDrmBuffer *buffer);
int meta_drm_buffer_get_width (MetaDrmBuffer *buffer);
int meta_drm_buffer_get_height (MetaDrmBuffer *buffer);
int meta_drm_buffer_get_stride (MetaDrmBuffer *buffer);
uint32_t meta_drm_buffer_get_format (MetaDrmBuffer *buffer);
#endif /* META_DRM_BUFFER_H */

View File

@ -64,80 +64,6 @@ struct _MetaGpuKms
G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU)
gboolean
meta_gpu_kms_add_fb (MetaGpuKms *gpu_kms,
gboolean use_modifiers,
const MetaGpuKmsFBArgs *args,
uint32_t *fb_id_out,
GError **error)
{
MetaDrmFormatBuf tmp;
uint32_t fb_id;
if (use_modifiers && args->modifiers[0] != DRM_FORMAT_MOD_INVALID)
{
if (drmModeAddFB2WithModifiers (gpu_kms->fd,
args->width,
args->height,
args->format,
args->handles,
args->strides,
args->offsets,
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 (gpu_kms->fd,
args->width,
args->height,
args->format,
args->handles,
args->strides,
args->offsets,
&fb_id,
0))
{
if (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, args->format),
args->format);
return FALSE;
}
if (drmModeAddFB (gpu_kms->fd,
args->width,
args->height,
24,
32,
args->strides[0],
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;
}
}
*fb_id_out = fb_id;
return TRUE;
}
gboolean
meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
MetaCrtc *crtc)

View File

@ -75,21 +75,4 @@ MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu
void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
typedef struct _MetaGpuKmsFBArgs
{
uint32_t width;
uint32_t height;
uint32_t format;
uint32_t handles[4];
uint32_t offsets[4];
uint32_t strides[4];
uint64_t modifiers[4];
} MetaGpuKmsFBArgs;
gboolean meta_gpu_kms_add_fb (MetaGpuKms *gpu_kms,
gboolean use_modifiers,
const MetaGpuKmsFBArgs *args,
uint32_t *fb_id_out,
GError **error);
#endif /* META_GPU_KMS_H */

View File

@ -39,15 +39,12 @@
#include <drm_fourcc.h>
#include <errno.h>
#include <fcntl.h>
#include <gbm.h>
#include <gio/gio.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <xf86drm.h>
#include "backends/meta-backend-private.h"
#include "backends/meta-crtc.h"
@ -129,19 +126,6 @@ typedef struct _MetaRendererNativeGpuData
} secondary;
} MetaRendererNativeGpuData;
typedef struct _MetaDumbBuffer
{
uint32_t fb_id;
uint32_t handle;
void *map;
uint64_t map_size;
int width;
int height;
int stride_bytes;
uint32_t drm_format;
int dmabuf_fd;
} MetaDumbBuffer;
typedef enum _MetaSharedFramebufferImportStatus
{
/* Not tried importing yet. */
@ -166,8 +150,8 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
} gbm;
struct {
MetaDumbBuffer *dumb_fb;
MetaDumbBuffer dumb_fbs[2];
MetaDrmBufferDumb *current_dumb_fb;
MetaDrmBufferDumb *dumb_fbs[2];
} cpu;
gboolean noted_primary_gpu_copy_ok;
@ -194,7 +178,7 @@ typedef struct _MetaOnscreenNative
struct {
EGLStreamKHR stream;
MetaDumbBuffer dumb_fb;
MetaDrmBufferDumb *dumb_fb;
} egl;
#endif
@ -235,22 +219,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaRendererNative,
static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
static const CoglWinsysVtable *parent_vtable;
static void
release_dumb_fb (MetaDumbBuffer *dumb_fb,
MetaGpuKms *gpu_kms);
static gboolean
init_dumb_fb (MetaDumbBuffer *dumb_fb,
MetaGpuKms *gpu_kms,
int width,
int height,
uint32_t format,
GError **error);
static int
meta_dumb_buffer_ensure_dmabuf_fd (MetaDumbBuffer *dumb_fb,
MetaGpuKms *gpu_kms);
static MetaEgl *
meta_renderer_native_get_egl (MetaRendererNative *renderer_native);
@ -530,11 +498,10 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_nat
static void
secondary_gpu_release_dumb (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
{
MetaGpuKms *gpu_kms = secondary_gpu_state->gpu_kms;
unsigned i;
for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++)
release_dumb_fb (&secondary_gpu_state->cpu.dumb_fbs[i], gpu_kms);
g_clear_object (&secondary_gpu_state->cpu.dumb_fbs[i]);
}
static void
@ -635,6 +602,7 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_nat
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
MetaGpuKms *gpu_kms;
MetaKmsDevice *kms_device;
int width, height;
unsigned int i;
uint32_t drm_format;
@ -652,6 +620,7 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_nat
height = cogl_framebuffer_get_height (framebuffer);
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc));
kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
g_debug ("Secondary GPU %s using DRM format '%s' (0x%x) for a %dx%d output.",
meta_gpu_kms_get_file_path (gpu_kms),
meta_drm_format_to_string (&tmp, drm_format),
@ -665,13 +634,12 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_nat
for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++)
{
MetaDumbBuffer *dumb_fb = &secondary_gpu_state->cpu.dumb_fbs[i];
if (!init_dumb_fb (dumb_fb,
gpu_kms,
width, height,
drm_format,
error))
secondary_gpu_state->cpu.dumb_fbs[i] =
meta_drm_buffer_dumb_new (kms_device,
width, height,
drm_format,
error);
if (!secondary_gpu_state->cpu.dumb_fbs[i])
{
secondary_gpu_state_free (secondary_gpu_state);
return FALSE;
@ -1367,11 +1335,12 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen,
#ifdef HAVE_EGL_DEVICE
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
{
uint32_t fb_id;
MetaDrmBuffer *buffer;
fb_id = onscreen_native->egl.dumb_fb.fb_id;
buffer = META_DRM_BUFFER (onscreen_native->egl.dumb_fb);
meta_crtc_kms_assign_primary_plane (crtc_kms,
fb_id, kms_update);
meta_drm_buffer_get_fb_id (buffer),
kms_update);
break;
}
#endif
@ -1403,13 +1372,20 @@ import_shared_framebuffer (CoglOnscreen *onscreen,
{
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaGpuKms *gpu_kms;
MetaKmsDevice *kms_device;
struct gbm_device *gbm_device;
MetaDrmBufferGbm *buffer_gbm;
MetaDrmBufferImport *buffer_import;
g_autoptr (GError) error = NULL;
buffer_gbm = META_DRM_BUFFER_GBM (onscreen_native->gbm.next_fb);
buffer_import = meta_drm_buffer_import_new (secondary_gpu_state->gpu_kms,
gpu_kms = secondary_gpu_state->gpu_kms;
kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
gbm_device = meta_gbm_device_from_gpu (gpu_kms);
buffer_import = meta_drm_buffer_import_new (kms_device,
gbm_device,
buffer_gbm,
&error);
if (!buffer_import)
@ -1475,6 +1451,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
MetaEgl *egl = meta_renderer_native_get_egl (renderer_native);
GError *error = NULL;
MetaKmsDevice *kms_device;
MetaDrmBufferGbm *buffer_gbm;
struct gbm_bo *bo;
@ -1523,8 +1500,9 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
return;
}
kms_device = meta_gpu_kms_get_kms_device (secondary_gpu_state->gpu_kms);
buffer_gbm =
meta_drm_buffer_gbm_new_lock_front (secondary_gpu_state->gpu_kms,
meta_drm_buffer_gbm_new_lock_front (kms_device,
secondary_gpu_state->gbm.surface,
renderer_native->use_modifiers,
&error);
@ -1539,16 +1517,16 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_gbm);
}
static MetaDumbBuffer *
static MetaDrmBufferDumb *
secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
{
MetaDumbBuffer *current_dumb_fb;
MetaDrmBufferDumb *current_dumb_fb;
current_dumb_fb = secondary_gpu_state->cpu.dumb_fb;
if (current_dumb_fb == &secondary_gpu_state->cpu.dumb_fbs[0])
return &secondary_gpu_state->cpu.dumb_fbs[1];
current_dumb_fb = secondary_gpu_state->cpu.current_dumb_fb;
if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[0])
return secondary_gpu_state->cpu.dumb_fbs[1];
else
return &secondary_gpu_state->cpu.dumb_fbs[0];
return secondary_gpu_state->cpu.dumb_fbs[0];
}
static CoglContext *
@ -1648,7 +1626,9 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
MetaRendererNativeGpuData *primary_gpu_data;
MetaDrmBufferDumb *buffer_dumb;
MetaDumbBuffer *dumb_fb;
MetaDrmBuffer *buffer;
int width, height, stride;
uint32_t drm_format;
CoglFramebuffer *dmabuf_fb;
int dmabuf_fd;
g_autoptr (GError) error = NULL;
@ -1664,28 +1644,36 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre
if (!primary_gpu_data->secondary.has_EGL_EXT_image_dma_buf_import_modifiers)
return FALSE;
dumb_fb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
buffer = META_DRM_BUFFER (buffer_dumb);
g_assert (cogl_framebuffer_get_width (framebuffer) == dumb_fb->width);
g_assert (cogl_framebuffer_get_height (framebuffer) == dumb_fb->height);
width = meta_drm_buffer_get_width (buffer);
height = meta_drm_buffer_get_height (buffer);
stride = meta_drm_buffer_get_stride (buffer);
drm_format = meta_drm_buffer_get_format (buffer);
ret = meta_cogl_pixel_format_from_drm_format (dumb_fb->drm_format,
g_assert (cogl_framebuffer_get_width (framebuffer) == width);
g_assert (cogl_framebuffer_get_height (framebuffer) == height);
ret = meta_cogl_pixel_format_from_drm_format (drm_format,
&cogl_format,
NULL);
g_assert (ret);
dmabuf_fd = meta_dumb_buffer_ensure_dmabuf_fd (dumb_fb,
secondary_gpu_state->gpu_kms);
if (dmabuf_fd == -1)
return FALSE;
dmabuf_fd = meta_drm_buffer_dumb_ensure_dmabuf_fd (buffer_dumb, &error);
if (!dmabuf_fd)
{
g_debug ("Failed to create DMA buffer: %s", error->message);
return FALSE;
}
dmabuf_fb = create_dma_buf_framebuffer (renderer_native,
dmabuf_fd,
dumb_fb->width,
dumb_fb->height,
dumb_fb->stride_bytes,
width,
height,
stride,
0, DRM_FORMAT_MOD_LINEAR,
dumb_fb->drm_format,
drm_format,
&error);
if (error)
@ -1697,8 +1685,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre
if (!cogl_blit_framebuffer (framebuffer, COGL_FRAMEBUFFER (dmabuf_fb),
0, 0, 0, 0,
dumb_fb->width,
dumb_fb->height,
width, height,
&error))
{
g_object_unref (dmabuf_fb);
@ -1708,9 +1695,8 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre
g_object_unref (dmabuf_fb);
g_clear_object (&secondary_gpu_state->gbm.next_fb);
buffer_dumb = meta_drm_buffer_dumb_new (dumb_fb->fb_id);
secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_dumb);
secondary_gpu_state->cpu.dumb_fb = dumb_fb;
secondary_gpu_state->gbm.next_fb = buffer;
secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb;
return TRUE;
}
@ -1722,31 +1708,41 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
MetaDumbBuffer *dumb_fb;
MetaDrmBufferDumb *buffer_dumb;
MetaDrmBuffer *buffer;
int width, height, stride;
uint32_t drm_format;
void *buffer_data;
CoglBitmap *dumb_bitmap;
CoglPixelFormat cogl_format;
gboolean ret;
MetaDrmBufferDumb *buffer_dumb;
COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferCpu,
"FB Copy (CPU)");
dumb_fb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state);
buffer = META_DRM_BUFFER (buffer_dumb);
g_assert (cogl_framebuffer_get_width (framebuffer) == dumb_fb->width);
g_assert (cogl_framebuffer_get_height (framebuffer) == dumb_fb->height);
width = meta_drm_buffer_get_width (buffer);
height = meta_drm_buffer_get_height (buffer);
stride = meta_drm_buffer_get_stride (buffer);
drm_format = meta_drm_buffer_get_format (buffer);
buffer_data = meta_drm_buffer_dumb_get_data (buffer_dumb);
ret = meta_cogl_pixel_format_from_drm_format (dumb_fb->drm_format,
g_assert (cogl_framebuffer_get_width (framebuffer) == width);
g_assert (cogl_framebuffer_get_height (framebuffer) == height);
ret = meta_cogl_pixel_format_from_drm_format (drm_format,
&cogl_format,
NULL);
g_assert (ret);
dumb_bitmap = cogl_bitmap_new_for_data (cogl_context,
dumb_fb->width,
dumb_fb->height,
width,
height,
cogl_format,
dumb_fb->stride_bytes,
dumb_fb->map);
stride,
buffer_data);
if (!cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
0 /* x */,
@ -1758,9 +1754,8 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
cogl_object_unref (dumb_bitmap);
g_clear_object (&secondary_gpu_state->gbm.next_fb);
buffer_dumb = meta_drm_buffer_dumb_new (dumb_fb->fb_id);
secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_dumb);
secondary_gpu_state->cpu.dumb_fb = dumb_fb;
secondary_gpu_state->gbm.next_fb = buffer;
secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb;
}
static void
@ -1946,6 +1941,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
MetaKmsDevice *render_kms_device = meta_gpu_kms_get_kms_device (render_gpu);
gboolean egl_context_changed = FALSE;
MetaPowerSave power_save_mode;
g_autoptr (GError) error = NULL;
@ -1971,7 +1967,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
g_clear_object (&onscreen_native->gbm.next_fb);
buffer_gbm =
meta_drm_buffer_gbm_new_lock_front (render_gpu,
meta_drm_buffer_gbm_new_lock_front (render_kms_device,
onscreen_native->gbm.surface,
renderer_native->use_modifiers,
&error);
@ -2427,154 +2423,6 @@ meta_renderer_native_create_surface_egl_device (CoglOnscreen *onscreen,
}
#endif /* HAVE_EGL_DEVICE */
static gboolean
init_dumb_fb (MetaDumbBuffer *dumb_fb,
MetaGpuKms *gpu_kms,
int width,
int height,
uint32_t format,
GError **error)
{
struct drm_mode_create_dumb create_arg;
struct drm_mode_destroy_dumb destroy_arg;
struct drm_mode_map_dumb map_arg;
uint32_t fb_id = 0;
void *map;
int kms_fd;
MetaGpuKmsFBArgs fb_args = {
.width = width,
.height = height,
.format = format,
};
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
create_arg = (struct drm_mode_create_dumb) {
.bpp = 32, /* RGBX8888 */
.width = width,
.height = height
};
if (drmIoctl (kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg) != 0)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Failed to create dumb drm buffer: %s",
g_strerror (errno));
goto err_ioctl;
}
fb_args.handles[0] = create_arg.handle;
fb_args.strides[0] = create_arg.pitch;
if (!meta_gpu_kms_add_fb (gpu_kms, FALSE, &fb_args, &fb_id, error))
goto err_add_fb;
map_arg = (struct drm_mode_map_dumb) {
.handle = create_arg.handle
};
if (drmIoctl (kms_fd, DRM_IOCTL_MODE_MAP_DUMB,
&map_arg) != 0)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Failed to map dumb drm buffer: %s",
g_strerror (errno));
goto err_map_dumb;
}
map = mmap (NULL, create_arg.size, PROT_WRITE, MAP_SHARED,
kms_fd, map_arg.offset);
if (map == MAP_FAILED)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Failed to mmap dumb drm buffer memory: %s",
g_strerror (errno));
goto err_mmap;
}
dumb_fb->fb_id = fb_id;
dumb_fb->handle = create_arg.handle;
dumb_fb->map = map;
dumb_fb->map_size = create_arg.size;
dumb_fb->width = width;
dumb_fb->height = height;
dumb_fb->stride_bytes = create_arg.pitch;
dumb_fb->drm_format = format;
dumb_fb->dmabuf_fd = -1;
return TRUE;
err_mmap:
err_map_dumb:
drmModeRmFB (kms_fd, fb_id);
err_add_fb:
destroy_arg = (struct drm_mode_destroy_dumb) {
.handle = create_arg.handle
};
drmIoctl (kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
err_ioctl:
return FALSE;
}
static int
meta_dumb_buffer_ensure_dmabuf_fd (MetaDumbBuffer *dumb_fb,
MetaGpuKms *gpu_kms)
{
int ret;
int kms_fd;
int dmabuf_fd;
if (dumb_fb->dmabuf_fd != -1)
return dumb_fb->dmabuf_fd;
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
ret = drmPrimeHandleToFD (kms_fd, dumb_fb->handle, DRM_CLOEXEC,
&dmabuf_fd);
if (ret)
{
g_debug ("Failed to export dumb drm buffer: %s",
g_strerror (errno));
return -1;
}
dumb_fb->dmabuf_fd = dmabuf_fd;
return dumb_fb->dmabuf_fd;
}
static void
release_dumb_fb (MetaDumbBuffer *dumb_fb,
MetaGpuKms *gpu_kms)
{
struct drm_mode_destroy_dumb destroy_arg;
int kms_fd;
if (!dumb_fb->map)
return;
if (dumb_fb->dmabuf_fd != -1)
close (dumb_fb->dmabuf_fd);
munmap (dumb_fb->map, dumb_fb->map_size);
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
drmModeRmFB (kms_fd, dumb_fb->fb_id);
destroy_arg = (struct drm_mode_destroy_dumb) {
.handle = dumb_fb->handle
};
drmIoctl (kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
*dumb_fb = (MetaDumbBuffer) {
.dmabuf_fd = -1,
};
}
static gboolean
meta_renderer_native_init_onscreen (CoglOnscreen *onscreen,
GError **error)
@ -2620,6 +2468,7 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen,
int width;
int height;
#ifdef HAVE_EGL_DEVICE
MetaKmsDevice *render_kms_device;
EGLStreamKHR egl_stream;
#endif
@ -2653,11 +2502,14 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen,
break;
#ifdef HAVE_EGL_DEVICE
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
if (!init_dumb_fb (&onscreen_native->egl.dumb_fb,
onscreen_native->render_gpu,
width, height,
DRM_FORMAT_XRGB8888,
error))
render_kms_device =
meta_gpu_kms_get_kms_device (onscreen_native->render_gpu);
onscreen_native->egl.dumb_fb =
meta_drm_buffer_dumb_new (render_kms_device,
width, height,
DRM_FORMAT_XRGB8888,
error);
if (!onscreen_native->egl.dumb_fb)
return FALSE;
if (!meta_renderer_native_create_surface_egl_device (onscreen,
@ -2750,8 +2602,7 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
break;
#ifdef HAVE_EGL_DEVICE
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
release_dumb_fb (&onscreen_native->egl.dumb_fb,
onscreen_native->render_gpu);
g_clear_object (&onscreen_native->egl.dumb_fb);
destroy_egl_surface (onscreen);

View File

@ -650,6 +650,7 @@ if have_native_backend
'backends/native/meta-drm-buffer-gbm.h',
'backends/native/meta-drm-buffer-import.c',
'backends/native/meta-drm-buffer-import.h',
'backends/native/meta-drm-buffer-private.h',
'backends/native/meta-drm-buffer.c',
'backends/native/meta-drm-buffer.h',
'backends/native/meta-gpu-kms.c',

View File

@ -687,6 +687,7 @@ try_acquire_egl_image_scanout (MetaWaylandBuffer *buffer,
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
MetaGpuKms *gpu_kms;
MetaKmsDevice *kms_device;
struct gbm_device *gbm_device;
struct gbm_bo *gbm_bo;
uint32_t drm_format;
@ -696,6 +697,7 @@ try_acquire_egl_image_scanout (MetaWaylandBuffer *buffer,
g_autoptr (GError) error = NULL;
gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native);
kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
gbm_device = meta_gbm_device_from_gpu (gpu_kms);
gbm_bo = gbm_bo_import (gbm_device,
@ -716,7 +718,7 @@ try_acquire_egl_image_scanout (MetaWaylandBuffer *buffer,
return NULL;
}
fb = meta_drm_buffer_gbm_new_take (gpu_kms, gbm_bo,
fb = meta_drm_buffer_gbm_new_take (kms_device, gbm_bo,
drm_modifier != DRM_FORMAT_MOD_INVALID,
&error);
if (!fb)

View File

@ -270,6 +270,7 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandDmaBufBuffer *dma_buf,
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
MetaGpuKms *gpu_kms;
MetaKmsDevice *kms_device;
int n_planes;
uint32_t drm_format;
uint64_t drm_modifier;
@ -295,6 +296,7 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandDmaBufBuffer *dma_buf,
return NULL;
gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native);
kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
gbm_bo = import_scanout_gbm_bo (dma_buf, gpu_kms, n_planes, &use_modifier);
if (!gbm_bo)
{
@ -302,7 +304,7 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandDmaBufBuffer *dma_buf,
return NULL;
}
fb = meta_drm_buffer_gbm_new_take (gpu_kms, gbm_bo,
fb = meta_drm_buffer_gbm_new_take (kms_device, gbm_bo,
use_modifier,
&error);
if (!fb)