From 84bde805fe34611c3a4d1cef1dfd30221b33dcc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 29 Sep 2020 09:40:53 +0200 Subject: [PATCH] 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: --- src/backends/native/meta-drm-buffer-dumb.c | 299 +++++++++++++++- src/backends/native/meta-drm-buffer-dumb.h | 14 +- src/backends/native/meta-drm-buffer-gbm.c | 80 +++-- src/backends/native/meta-drm-buffer-gbm.h | 6 +- src/backends/native/meta-drm-buffer-import.c | 88 +++-- src/backends/native/meta-drm-buffer-import.h | 7 +- src/backends/native/meta-drm-buffer-private.h | 60 ++++ src/backends/native/meta-drm-buffer.c | 307 +++++++++++++++- src/backends/native/meta-drm-buffer.h | 19 +- src/backends/native/meta-gpu-kms.c | 74 ---- src/backends/native/meta-gpu-kms.h | 17 - src/backends/native/meta-renderer-native.c | 335 +++++------------- src/meson.build | 1 + src/wayland/meta-wayland-buffer.c | 4 +- src/wayland/meta-wayland-dma-buf.c | 4 +- 15 files changed, 880 insertions(+), 435 deletions(-) create mode 100644 src/backends/native/meta-drm-buffer-private.h diff --git a/src/backends/native/meta-drm-buffer-dumb.c b/src/backends/native/meta-drm-buffer-dumb.c index ccf5747f5..373eb5c73 100644 --- a/src/backends/native/meta-drm-buffer-dumb.c +++ b/src/backends/native/meta-drm-buffer-dumb.c @@ -25,41 +25,322 @@ #include "backends/native/meta-drm-buffer-dumb.h" +#include +#include +#include + +#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; } diff --git a/src/backends/native/meta-drm-buffer-dumb.h b/src/backends/native/meta-drm-buffer-dumb.h index f8b733f88..2d3e27c92 100644 --- a/src/backends/native/meta-drm-buffer-dumb.h +++ b/src/backends/native/meta-drm-buffer-dumb.h @@ -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 */ diff --git a/src/backends/native/meta-drm-buffer-gbm.c b/src/backends/native/meta-drm-buffer-gbm.c index 7acd97bc4..48ee9eb04 100644 --- a/src/backends/native/meta-drm-buffer-gbm.c +++ b/src/backends/native/meta-drm-buffer-gbm.c @@ -23,7 +23,6 @@ #include "config.h" -#include "backends/native/meta-cogl-utils.h" #include "backends/native/meta-drm-buffer-gbm.h" #include @@ -31,18 +30,16 @@ #include #include -#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; } diff --git a/src/backends/native/meta-drm-buffer-gbm.h b/src/backends/native/meta-drm-buffer-gbm.h index b46925ecc..43d7e2d8a 100644 --- a/src/backends/native/meta-drm-buffer-gbm.h +++ b/src/backends/native/meta-drm-buffer-gbm.h @@ -24,7 +24,7 @@ #include -#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); diff --git a/src/backends/native/meta-drm-buffer-import.c b/src/backends/native/meta-drm-buffer-import.c index b9d0e21d2..1e5a38246 100644 --- a/src/backends/native/meta-drm-buffer-import.c +++ b/src/backends/native/meta-drm-buffer-import.c @@ -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; } diff --git a/src/backends/native/meta-drm-buffer-import.h b/src/backends/native/meta-drm-buffer-import.h index 2c0962e5f..48c9bd190 100644 --- a/src/backends/native/meta-drm-buffer-import.h +++ b/src/backends/native/meta-drm-buffer-import.h @@ -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 */ diff --git a/src/backends/native/meta-drm-buffer-private.h b/src/backends/native/meta-drm-buffer-private.h new file mode 100644 index 000000000..2c77eb957 --- /dev/null +++ b/src/backends/native/meta-drm-buffer-private.h @@ -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 */ diff --git a/src/backends/native/meta-drm-buffer.c b/src/backends/native/meta-drm-buffer.c index 85b520825..81a36196e 100644 --- a/src/backends/native/meta-drm-buffer.c +++ b/src/backends/native/meta-drm-buffer.c @@ -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 + +#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); } diff --git a/src/backends/native/meta-drm-buffer.h b/src/backends/native/meta-drm-buffer.h index 94873ed40..1647d399e 100644 --- a/src/backends/native/meta-drm-buffer.h +++ b/src/backends/native/meta-drm-buffer.h @@ -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 */ diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c index f156cb056..dbf76abed 100644 --- a/src/backends/native/meta-gpu-kms.c +++ b/src/backends/native/meta-gpu-kms.c @@ -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) diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h index 77aac47ec..d75c8a40f 100644 --- a/src/backends/native/meta-gpu-kms.h +++ b/src/backends/native/meta-gpu-kms.h @@ -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 */ diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 3cb68c8b0..6171c886e 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -39,15 +39,12 @@ #include #include -#include #include #include #include #include #include -#include #include -#include #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); diff --git a/src/meson.build b/src/meson.build index 1dcddde3f..fb1d2ab56 100644 --- a/src/meson.build +++ b/src/meson.build @@ -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', diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c index 211c85ff0..5fd76cbfc 100644 --- a/src/wayland/meta-wayland-buffer.c +++ b/src/wayland/meta-wayland-buffer.c @@ -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) diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c index e5a8f9a75..799695848 100644 --- a/src/wayland/meta-wayland-dma-buf.c +++ b/src/wayland/meta-wayland-dma-buf.c @@ -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)