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)