From 9cd3b07472b6f98a6558ae0377d0e18a982e2a22 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Mon, 10 Jun 2019 17:07:55 +0300 Subject: [PATCH] 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 6f59e4858e24c828e3ab0e611d36dfaaded1b272 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 --- src/backends/meta-egl.c | 94 ++++++++++++- src/backends/meta-egl.h | 13 ++ .../native/meta-renderer-native-gles3.c | 125 +++--------------- 3 files changed, 127 insertions(+), 105 deletions(-) diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c index 8b953449a..6554be935 100644 --- a/src/backends/meta-egl.c +++ b/src/backends/meta-egl.c @@ -1,7 +1,8 @@ /* -*- 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 * modify it under the terms of the GNU General Public License as @@ -574,6 +575,97 @@ meta_egl_destroy_image (MetaEgl *egl, 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 meta_egl_make_current (MetaEgl *egl, EGLDisplay display, diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h index ff37f124f..f2a816445 100644 --- a/src/backends/meta-egl.h +++ b/src/backends/meta-egl.h @@ -2,6 +2,7 @@ /* * Copyright (C) 2016 Red Hat Inc. + * Copyright (C) 2019 DisplayLink (UK) Ltd. * * This program is free software; you can redistribute it and/or * 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, 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, EGLDisplay display, EGLConfig config, diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c index 7afea8648..740b52ef6 100644 --- a/src/backends/native/meta-renderer-native-gles3.c +++ b/src/backends/native/meta-renderer-native-gles3.c @@ -45,101 +45,6 @@ #error "Somehow included OpenGL headers when we shouldn't have" #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 paint_egl_image (MetaGles3 *gles3, EGLImageKHR egl_image, @@ -195,8 +100,10 @@ meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, uint32_t strides[4] = { 0 }; uint32_t offsets[4] = { 0 }; uint64_t modifiers[4] = { 0 }; + int fds[4] = { -1, -1, -1, -1 }; uint32_t format; EGLImageKHR egl_image; + gboolean use_modifiers; shared_bo_fd = gbm_bo_get_fd (shared_bo); 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); offsets[i] = gbm_bo_get_offset (shared_bo, i); modifiers[i] = gbm_bo_get_modifier (shared_bo); + fds[i] = shared_bo_fd; } - egl_image = create_egl_image (egl, - egl_display, - egl_context, - width, height, - n_planes, - strides, offsets, - modifiers, format, - shared_bo_fd, - error); + /* Workaround for https://gitlab.gnome.org/GNOME/mutter/issues/18 */ + if (modifiers[0] == DRM_FORMAT_MOD_LINEAR || + modifiers[0] == DRM_FORMAT_MOD_INVALID) + use_modifiers = FALSE; + else + use_modifiers = TRUE; + + egl_image = meta_egl_create_dmabuf_image (egl, + egl_display, + width, + height, + format, + n_planes, + fds, + strides, + offsets, + use_modifiers ? modifiers : NULL, + error); close (shared_bo_fd); if (!egl_image)