Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions src/backends/native/meta-cursor-renderer-native.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "backends/meta-monitor-manager-private.h"
#include "backends/meta-output.h"
#include "backends/native/meta-crtc-kms.h"
#include "backends/native/meta-gpu-kms.h"
#include "backends/native/meta-kms-device.h"
#include "backends/native/meta-kms-update.h"
#include "backends/native/meta-kms.h"
Expand Down Expand Up @@ -98,6 +99,8 @@ typedef struct _MetaCursorRendererNativeGpuData

uint64_t cursor_width;
uint64_t cursor_height;

struct gbm_device *kms_gbm_device;
} MetaCursorRendererNativeGpuData;

typedef enum _MetaCursorGbmBoState
Expand Down Expand Up @@ -159,6 +162,15 @@ meta_cursor_renderer_native_gpu_data_from_gpu (MetaGpuKms *gpu_kms)
quark_cursor_renderer_native_gpu_data);
}

static void
cursor_renderer_native_gpu_data_free (gpointer data)
{
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data = data;

g_clear_pointer (&cursor_renderer_gpu_data->kms_gbm_device, gbm_device_destroy);
g_free (cursor_renderer_gpu_data);
}

static MetaCursorRendererNativeGpuData *
meta_create_cursor_renderer_native_gpu_data (MetaGpuKms *gpu_kms)
{
Expand All @@ -168,7 +180,7 @@ meta_create_cursor_renderer_native_gpu_data (MetaGpuKms *gpu_kms)
g_object_set_qdata_full (G_OBJECT (gpu_kms),
quark_cursor_renderer_native_gpu_data,
cursor_renderer_gpu_data,
g_free);
cursor_renderer_native_gpu_data_free);

return cursor_renderer_gpu_data;
}
Expand Down Expand Up @@ -1189,7 +1201,9 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native,
return;
}

gbm_device = meta_gbm_device_from_gpu (gpu_kms);
gbm_device = cursor_renderer_gpu_data->kms_gbm_device
? cursor_renderer_gpu_data->kms_gbm_device
: meta_gbm_device_from_gpu (gpu_kms);
if (gbm_device_is_format_supported (gbm_device, gbm_format,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
{
Expand Down Expand Up @@ -1685,6 +1699,12 @@ init_hw_cursor_support_for_gpu (MetaGpuKms *gpu_kms)

cursor_renderer_gpu_data->cursor_width = width;
cursor_renderer_gpu_data->cursor_height = height;

cursor_renderer_gpu_data->kms_gbm_device =
gbm_create_device (meta_gpu_kms_get_fd (gpu_kms));
if (!cursor_renderer_gpu_data->kms_gbm_device)
g_warning ("Failed to create KMS GBM device for cursor allocation, "
"HW cursor may not work");
}

static void
Expand Down
85 changes: 79 additions & 6 deletions src/backends/native/meta-drm-buffer-gbm.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

#include <drm_fourcc.h>
#include <errno.h>
#include <fcntl.h>
#include <gbm.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>

Expand Down Expand Up @@ -57,34 +60,93 @@ meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm)
return buffer_gbm->bo;
}

static void
close_kms_handle (int kms_fd, uint32_t handle)
{
struct drm_gem_close args = { .handle = handle };
drmIoctl (kms_fd, DRM_IOCTL_GEM_CLOSE, &args);
}

static gboolean
init_fb_id (MetaDrmBufferGbm *buffer_gbm,
struct gbm_bo *bo,
gboolean use_modifiers,
GError **error)
{
MetaGpuKmsFBArgs fb_args = { 0, };
int gbm_fd = gbm_device_get_fd (gbm_bo_get_device (bo));
int kms_fd = meta_gpu_kms_get_fd (buffer_gbm->gpu_kms);
gboolean need_prime = (gbm_fd != kms_fd);
uint32_t imported_handles[4] = { 0, 0, 0, 0 };
int n_imported = 0;
int i;

if (gbm_bo_get_handle_for_plane (bo, 0).s32 == -1)
{
/* Failed to fetch handle to plane, falling back to old method */
fb_args.strides[0] = gbm_bo_get_stride (bo);
fb_args.handles[0] = gbm_bo_get_handle (bo).u32;
fb_args.offsets[0] = 0;
fb_args.modifiers[0] = DRM_FORMAT_MOD_INVALID;

if (need_prime)
{
int prime_fd = -1;
if (drmPrimeHandleToFD (gbm_fd, gbm_bo_get_handle (bo).u32,
DRM_CLOEXEC, &prime_fd) != 0 ||
drmPrimeFDToHandle (kms_fd, prime_fd, &imported_handles[0]) != 0)
{
if (prime_fd >= 0)
close (prime_fd);
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"Failed to import GBM buffer via prime: %s",
g_strerror (errno));
return FALSE;
}
close (prime_fd);
n_imported = 1;
fb_args.handles[0] = imported_handles[0];
}
else
{
fb_args.handles[0] = gbm_bo_get_handle (bo).u32;
}
}
else
{
int i;
int n_planes = gbm_bo_get_plane_count (bo);

for (i = 0; i < gbm_bo_get_plane_count (bo); i++)
for (i = 0; i < n_planes; i++)
{
fb_args.strides[i] = gbm_bo_get_stride_for_plane (bo, i);
fb_args.handles[i] = gbm_bo_get_handle_for_plane (bo, i).u32;
fb_args.offsets[i] = gbm_bo_get_offset (bo, i);
fb_args.modifiers[i] = gbm_bo_get_modifier (bo);

if (need_prime)
{
int prime_fd = -1;
if (drmPrimeHandleToFD (gbm_fd,
gbm_bo_get_handle_for_plane (bo, i).u32,
DRM_CLOEXEC, &prime_fd) != 0 ||
drmPrimeFDToHandle (kms_fd, prime_fd,
&imported_handles[i]) != 0)
{
if (prime_fd >= 0)
close (prime_fd);
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"Failed to import GBM buffer plane %d via prime: %s",
i, g_strerror (errno));
goto out_close_imported;
}
close (prime_fd);
n_imported = i + 1;
fb_args.handles[i] = imported_handles[i];
}
else
{
fb_args.handles[i] = gbm_bo_get_handle_for_plane (bo, i).u32;
}
}
}
}

fb_args.width = gbm_bo_get_width (bo);
fb_args.height = gbm_bo_get_height (bo);
Expand All @@ -94,8 +156,19 @@ init_fb_id (MetaDrmBufferGbm *buffer_gbm,
use_modifiers,
&fb_args,
&buffer_gbm->fb_id, error))
return FALSE;
goto out_close_imported;

/* The kernel now holds a reference to the GEM objects via the FB;
* close our local imported handles. */
for (i = 0; i < n_imported; i++)
close_kms_handle (kms_fd, imported_handles[i]);

return TRUE;

out_close_imported:
for (i = 0; i < n_imported; i++)
close_kms_handle (kms_fd, imported_handles[i]);
return FALSE;
}

static gboolean
Expand Down
5 changes: 5 additions & 0 deletions src/backends/native/meta-kms-impl-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,11 @@ meta_kms_impl_device_new (MetaKmsDevice *device,
return NULL;
}

ret = drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1);
if (ret != 0)
g_warning ("DRM_CLIENT_CAP_ATOMIC not supported on this kernel/device: %s",
g_strerror (-ret));

drm_resources = drmModeGetResources (fd);
if (!drm_resources)
{
Expand Down
39 changes: 34 additions & 5 deletions src/backends/native/meta-renderer-native.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ typedef struct _MetaRendererNativeGpuData

struct {
struct gbm_device *device;
int fd;
} gbm;

#ifdef HAVE_EGL_DEVICE
Expand Down Expand Up @@ -283,6 +284,8 @@ meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data
meta_egl_terminate (egl, renderer_gpu_data->egl_display, NULL);

g_clear_pointer (&renderer_gpu_data->gbm.device, gbm_device_destroy);
if (renderer_gpu_data->gbm.fd >= 0)
close (renderer_gpu_data->gbm.fd);
g_free (renderer_gpu_data);
}

Expand Down Expand Up @@ -322,7 +325,9 @@ meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_native)
static MetaRendererNativeGpuData *
meta_create_renderer_native_gpu_data (MetaGpuKms *gpu_kms)
{
return g_new0 (MetaRendererNativeGpuData, 1);
MetaRendererNativeGpuData *data = g_new0 (MetaRendererNativeGpuData, 1);
data->gbm.fd = -1;
return data;
}

static MetaEgl *
Expand Down Expand Up @@ -3442,6 +3447,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
}

renderer_str = (const char *) glGetString (GL_RENDERER);
g_message ("GL renderer: %s", renderer_str);
if (g_str_has_prefix (renderer_str, "llvmpipe") ||
g_str_has_prefix (renderer_str, "softpipe") ||
g_str_has_prefix (renderer_str, "swrast"))
Expand Down Expand Up @@ -3569,12 +3575,34 @@ create_renderer_gpu_data_gbm (MetaRendererNative *renderer_native,
{
struct gbm_device *gbm_device;
int kms_fd;
int gbm_fd = -1;
char *render_node_path;
MetaRendererNativeGpuData *renderer_gpu_data;
g_autoptr (GError) local_error = NULL;

kms_fd = meta_gpu_kms_get_fd (gpu_kms);

gbm_device = gbm_create_device (kms_fd);
/* Open the render node directly so GBM gets a clean fd with no KMS client
* caps set on it. This matches how wlroots-based compositors initialize
* rendering and avoids hardware-specific issues with reusing the KMS fd. */
render_node_path = drmGetRenderDeviceNameFromFd (kms_fd);
if (render_node_path)
{
do
gbm_fd = open (render_node_path, O_RDWR | O_CLOEXEC);
while (gbm_fd < 0 && errno == EINTR);
free (render_node_path);
}

gbm_device = gbm_create_device (gbm_fd >= 0 ? gbm_fd : kms_fd);
if (!gbm_device && gbm_fd >= 0)
{
g_warning ("Failed to create gbm device from render node, retrying with primary fd");
close (gbm_fd);
gbm_fd = -1;
gbm_device = gbm_create_device (kms_fd);
}

if (!gbm_device)
{
g_set_error (error, G_IO_ERROR,
Expand All @@ -3586,16 +3614,17 @@ create_renderer_gpu_data_gbm (MetaRendererNative *renderer_native,
renderer_gpu_data = meta_create_renderer_native_gpu_data (gpu_kms);
renderer_gpu_data->renderer_native = renderer_native;
renderer_gpu_data->gbm.device = gbm_device;
renderer_gpu_data->gbm.fd = gbm_fd;
renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_GBM;

renderer_gpu_data->egl_display = init_gbm_egl_display (renderer_native,
gbm_device,
&local_error);
if (renderer_gpu_data->egl_display == EGL_NO_DISPLAY)
{
g_debug ("GBM EGL init for %s failed: %s",
meta_gpu_kms_get_file_path (gpu_kms),
local_error->message);
g_warning ("GBM EGL init for %s failed: %s",
meta_gpu_kms_get_file_path (gpu_kms),
local_error->message);

init_secondary_gpu_data_cpu (renderer_gpu_data);
return renderer_gpu_data;
Expand Down
3 changes: 3 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,8 @@ if have_wayland
'wayland/meta-wayland-data-source-primary.h',
'wayland/meta-wayland-dma-buf.c',
'wayland/meta-wayland-dma-buf.h',
'wayland/meta-wayland-drm.c',
'wayland/meta-wayland-drm.h',
'wayland/meta-wayland-dnd-surface.c',
'wayland/meta-wayland-dnd-surface.h',
'wayland/meta-wayland-gtk-shell.c',
Expand Down Expand Up @@ -842,6 +844,7 @@ if have_wayland
['xdg-toplevel-icon-v1', 'private', ],
['xapp-shell', 'private', ],
['xwayland-keyboard-grab', 'unstable', 'v1', ],
['wayland-drm', 'private', ],
]
if have_wayland_eglstream
wayland_eglstream_protocols_dir = wayland_eglstream_protocols_dep.get_variable(pkgconfig: 'pkgdatadir')
Expand Down
2 changes: 2 additions & 0 deletions src/wayland/meta-wayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "wayland/meta-wayland-cursor-shape.h"
#include "wayland/meta-wayland-data-device.h"
#include "wayland/meta-wayland-dma-buf.h"
#include "wayland/meta-wayland-drm.h"
#include "wayland/meta-wayland-egl-stream.h"
#include "wayland/meta-wayland-idle-inhibit.h"
#include "wayland/meta-wayland-inhibit-shortcuts-dialog.h"
Expand Down Expand Up @@ -444,6 +445,7 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor)
meta_wayland_xdg_foreign_init (compositor);
meta_wayland_legacy_xdg_foreign_init (compositor);
meta_wayland_dma_buf_init (compositor);
meta_wayland_drm_init (compositor);
meta_wayland_init_single_pixel_buffer_manager (compositor);
meta_wayland_keyboard_shortcuts_inhibit_init (compositor);
meta_wayland_surface_inhibit_shortcuts_dialog_init ();
Expand Down
Loading