egl: Introduce meta_egl_create_dmabuf_image

This bit of code was more or less duplicated in meta-renderer-native-gles3.c
and meta-wayland-dma-buf.c. Start consolidating the two implementations by
moving the *-gles3.c function into meta-egl.c and generalizing it so it could
also accommodate the meta-wayland-dma-buf.c usage.

The workaround in the *-gles3.c implementation is moved to the caller. It is
the caller's responsibility to check for the existence of the appropriate EGL
extensions.

Commit 6f59e4858e worked around the lack of
EGL_EXT_image_dma_buf_import_modifiers with the assumption that if the modifier
is linear, there is no need to pass it into EGL. The problem is that not
passing a modifier explicitly to EGL invokes implementation-defined behaviour,
so we should not have that workaround in meta-egl.c.

This patch intends to be pure refactoring, no behavioral changes. The one
change is the addition of g_assert to catch overwriting arbitrary memory.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/615
This commit is contained in:
Pekka Paalanen 2019-06-10 17:07:55 +03:00 committed by Jonas Ådahl
parent 6061abbf90
commit 9cd3b07472
3 changed files with 127 additions and 105 deletions

View File

@ -1,7 +1,8 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* /*
* Copyright (C) 2016 Red Hat Inc. * Copyright (C) 2016, 2017 Red Hat Inc.
* Copyright (C) 2018, 2019 DisplayLink (UK) Ltd.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@ -574,6 +575,97 @@ meta_egl_destroy_image (MetaEgl *egl,
return TRUE; return TRUE;
} }
EGLImageKHR
meta_egl_create_dmabuf_image (MetaEgl *egl,
EGLDisplay egl_display,
unsigned int width,
unsigned int height,
uint32_t drm_format,
uint32_t n_planes,
const int *fds,
const uint32_t *strides,
const uint32_t *offsets,
const uint64_t *modifiers,
GError **error)
{
EGLint attribs[37];
int atti = 0;
/* This requires the Mesa commit in
* Mesa 10.3 (08264e5dad4df448e7718e782ad9077902089a07) or
* Mesa 10.2.7 (55d28925e6109a4afd61f109e845a8a51bd17652).
* Otherwise Mesa closes the fd behind our back and re-importing
* will fail.
* https://bugs.freedesktop.org/show_bug.cgi?id=76188
*/
attribs[atti++] = EGL_WIDTH;
attribs[atti++] = width;
attribs[atti++] = EGL_HEIGHT;
attribs[atti++] = height;
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[atti++] = drm_format;
if (n_planes > 0)
{
attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
attribs[atti++] = fds[0];
attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
attribs[atti++] = offsets[0];
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
attribs[atti++] = strides[0];
if (modifiers)
{
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
attribs[atti++] = modifiers[0] & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
attribs[atti++] = modifiers[0] >> 32;
}
}
if (n_planes > 1)
{
attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
attribs[atti++] = fds[1];
attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
attribs[atti++] = offsets[1];
attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
attribs[atti++] = strides[1];
if (modifiers)
{
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
attribs[atti++] = modifiers[1] & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
attribs[atti++] = modifiers[1] >> 32;
}
}
if (n_planes > 2)
{
attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
attribs[atti++] = fds[2];
attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
attribs[atti++] = offsets[2];
attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
attribs[atti++] = strides[2];
if (modifiers)
{
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
attribs[atti++] = modifiers[2] & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
attribs[atti++] = modifiers[2] >> 32;
}
}
attribs[atti++] = EGL_NONE;
g_assert (atti <= G_N_ELEMENTS (attribs));
return meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT, NULL,
attribs,
error);
}
gboolean gboolean
meta_egl_make_current (MetaEgl *egl, meta_egl_make_current (MetaEgl *egl,
EGLDisplay display, EGLDisplay display,

View File

@ -2,6 +2,7 @@
/* /*
* Copyright (C) 2016 Red Hat Inc. * Copyright (C) 2016 Red Hat Inc.
* Copyright (C) 2019 DisplayLink (UK) Ltd.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@ -100,6 +101,18 @@ gboolean meta_egl_destroy_image (MetaEgl *egl,
EGLImageKHR image, EGLImageKHR image,
GError **error); GError **error);
EGLImageKHR meta_egl_create_dmabuf_image (MetaEgl *egl,
EGLDisplay egl_display,
unsigned int width,
unsigned int height,
uint32_t drm_format,
uint32_t n_planes,
const int *fds,
const uint32_t *strides,
const uint32_t *offsets,
const uint64_t *modifiers,
GError **error);
EGLSurface meta_egl_create_window_surface (MetaEgl *egl, EGLSurface meta_egl_create_window_surface (MetaEgl *egl,
EGLDisplay display, EGLDisplay display,
EGLConfig config, EGLConfig config,

View File

@ -45,101 +45,6 @@
#error "Somehow included OpenGL headers when we shouldn't have" #error "Somehow included OpenGL headers when we shouldn't have"
#endif #endif
static EGLImageKHR
create_egl_image (MetaEgl *egl,
EGLDisplay egl_display,
EGLContext egl_context,
unsigned int width,
unsigned int height,
uint32_t n_planes,
uint32_t *strides,
uint32_t *offsets,
uint64_t *modifiers,
uint32_t format,
int fd,
GError **error)
{
EGLint attribs[37];
int atti = 0;
gboolean has_modifier;
/* This requires the Mesa commit in
* Mesa 10.3 (08264e5dad4df448e7718e782ad9077902089a07) or
* Mesa 10.2.7 (55d28925e6109a4afd61f109e845a8a51bd17652).
* Otherwise Mesa closes the fd behind our back and re-importing
* will fail.
* https://bugs.freedesktop.org/show_bug.cgi?id=76188
*/
attribs[atti++] = EGL_WIDTH;
attribs[atti++] = width;
attribs[atti++] = EGL_HEIGHT;
attribs[atti++] = height;
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
attribs[atti++] = format;
has_modifier = (modifiers[0] != DRM_FORMAT_MOD_INVALID &&
modifiers[0] != DRM_FORMAT_MOD_LINEAR);
if (n_planes > 0)
{
attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
attribs[atti++] = fd;
attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
attribs[atti++] = offsets[0];
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
attribs[atti++] = strides[0];
if (has_modifier)
{
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
attribs[atti++] = modifiers[0] & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
attribs[atti++] = modifiers[0] >> 32;
}
}
if (n_planes > 1)
{
attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
attribs[atti++] = fd;
attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
attribs[atti++] = offsets[1];
attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
attribs[atti++] = strides[1];
if (has_modifier)
{
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
attribs[atti++] = modifiers[1] & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
attribs[atti++] = modifiers[1] >> 32;
}
}
if (n_planes > 2)
{
attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
attribs[atti++] = fd;
attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
attribs[atti++] = offsets[2];
attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
attribs[atti++] = strides[2];
if (has_modifier)
{
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
attribs[atti++] = modifiers[2] & 0xFFFFFFFF;
attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
attribs[atti++] = modifiers[2] >> 32;
}
}
attribs[atti++] = EGL_NONE;
return meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT, NULL,
attribs,
error);
}
static void static void
paint_egl_image (MetaGles3 *gles3, paint_egl_image (MetaGles3 *gles3,
EGLImageKHR egl_image, EGLImageKHR egl_image,
@ -195,8 +100,10 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
uint32_t strides[4] = { 0 }; uint32_t strides[4] = { 0 };
uint32_t offsets[4] = { 0 }; uint32_t offsets[4] = { 0 };
uint64_t modifiers[4] = { 0 }; uint64_t modifiers[4] = { 0 };
int fds[4] = { -1, -1, -1, -1 };
uint32_t format; uint32_t format;
EGLImageKHR egl_image; EGLImageKHR egl_image;
gboolean use_modifiers;
shared_bo_fd = gbm_bo_get_fd (shared_bo); shared_bo_fd = gbm_bo_get_fd (shared_bo);
if (shared_bo_fd < 0) if (shared_bo_fd < 0)
@ -216,17 +123,27 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl,
strides[i] = gbm_bo_get_stride_for_plane (shared_bo, i); strides[i] = gbm_bo_get_stride_for_plane (shared_bo, i);
offsets[i] = gbm_bo_get_offset (shared_bo, i); offsets[i] = gbm_bo_get_offset (shared_bo, i);
modifiers[i] = gbm_bo_get_modifier (shared_bo); modifiers[i] = gbm_bo_get_modifier (shared_bo);
fds[i] = shared_bo_fd;
} }
egl_image = create_egl_image (egl, /* Workaround for https://gitlab.gnome.org/GNOME/mutter/issues/18 */
egl_display, if (modifiers[0] == DRM_FORMAT_MOD_LINEAR ||
egl_context, modifiers[0] == DRM_FORMAT_MOD_INVALID)
width, height, use_modifiers = FALSE;
n_planes, else
strides, offsets, use_modifiers = TRUE;
modifiers, format,
shared_bo_fd, egl_image = meta_egl_create_dmabuf_image (egl,
error); egl_display,
width,
height,
format,
n_planes,
fds,
strides,
offsets,
use_modifiers ? modifiers : NULL,
error);
close (shared_bo_fd); close (shared_bo_fd);
if (!egl_image) if (!egl_image)