From 4a2ea8fab61b13b453298ef007278d16cc591403 Mon Sep 17 00:00:00 2001 From: kestrel Date: Tue, 7 Oct 2025 20:13:27 +0300 Subject: [PATCH] gnu: qtwebengine: Fix GPU rendering with mesa-25.2.0. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * gnu/packages/qt.scm (qtwebengine)[source]: Add patch. * gnu/packages/patches/qtwebengine-revert-egl.patch: New file. * gnu/local.mk (dist_patch_DATA): Register it. Fixes: guix/guix#3222 Change-Id: Id0cb3d956d3faf30f737fa2a689cd936270c2413 Signed-off-by: Efraim Flashner Signed-off-by: 宋文武 --- gnu/local.mk | 1 + .../patches/qtwebengine-revert-egl.patch | 228 ++++++++++++++++++ gnu/packages/qt.scm | 3 + 3 files changed, 232 insertions(+) create mode 100644 gnu/packages/patches/qtwebengine-revert-egl.patch diff --git a/gnu/local.mk b/gnu/local.mk index 554c96d8edfca125a2ce12b11e93ae4c9c4f1bc8..79f07f882470dd267452e5a8ab7410207a64a855 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -2074,6 +2074,7 @@ dist_patch_DATA = \ %D%/packages/patches/qtdeclarative-5-disable-qmlcache.patch \ %D%/packages/patches/qtdeclarative-disable-qmlcache.patch \ %D%/packages/patches/qtlocation-5.15.8-mapboxgl-gcc13.patch \ + %D%/packages/patches/qtwebengine-revert-egl.patch \ %D%/packages/patches/quodlibet-disable-bundled-packages.patch \ %D%/packages/patches/qxlsx-fix-include-directory.patch \ %D%/packages/patches/schiffbruch-fix-build-for-gcc-13.patch \ diff --git a/gnu/packages/patches/qtwebengine-revert-egl.patch b/gnu/packages/patches/qtwebengine-revert-egl.patch new file mode 100644 index 0000000000000000000000000000000000000000..a13747f473388d761ab648e775dd7ad3ae23cf6e --- /dev/null +++ b/gnu/packages/patches/qtwebengine-revert-egl.patch @@ -0,0 +1,228 @@ +https://codereview.qt-project.org/c/qt/qtwebengine/+/675112 +From 3cc88e0f85113e38ccb1bfdadb7d150c2389b1bc Mon Sep 17 00:00:00 2001 +From: Moss Heim +Date: Thu, 11 Sep 2025 13:47:04 +0200 +Subject: [PATCH] Return to supporting eglCreateImage in EGLHelper::queryDmaBuf + +eglCreateDRMImageMESA was removed in mesa 25.2. +Keep using it where we can since this fixes support for +panthor/panfrost, otherwise fall back to the old use of EGL API. + +Includes a revert of the following commits: +Revert "Create EGLImage with eglCreateDRMImageMESA() for exporting dma_buf" +This reverts commit 2ed5f9632292c6e531f353dae800cb12274af91a. +Revert "Remove leftover QOffscreenSurface from EGLHelper" +This reverts commit bcee2dbf412cc655c1b467091b581c696d234e3f. + +Pick-to: 6.9 6.10 6.10.0 +Task-number: QTBUG-136257 +Task-number: QTBUG-139424 +Change-Id: Ie115bd6373ce0a80651781aa568405477010ee25 +Reviewed-by: Peter Varga +--- + src/core/ozone/egl_helper.cpp | 142 +++++++++++++++++++++++++++++++--- + src/core/ozone/egl_helper.h | 4 + + 2 files changed, 134 insertions(+), 12 deletions(-) + +diff --git a/src/core/ozone/egl_helper.cpp b/src/core/ozone/egl_helper.cpp +index 76e1c2a4663..68e45ffd446 100644 +--- a/src/core/ozone/egl_helper.cpp ++++ b/src/core/ozone/egl_helper.cpp +@@ -3,10 +3,14 @@ + // Qt-Security score:significant reason:default + + #include "egl_helper.h" ++ ++#include "compositor/compositor.h" + #include "ozone_util_qt.h" + #include "web_engine_context.h" + ++#include + #include ++#include + #include + #include + #include +@@ -57,6 +61,84 @@ static const char *getEGLErrorString(uint32_t error) + + QT_BEGIN_NAMESPACE + ++class ScopedGLContext ++{ ++public: ++ ScopedGLContext(QOffscreenSurface *surface, EGLHelper::EGLFunctions *eglFun) ++ : m_context(new QOpenGLContext()), m_eglFun(eglFun) ++ { ++ if ((m_previousEGLContext = m_eglFun->eglGetCurrentContext())) { ++ m_previousEGLDrawSurface = m_eglFun->eglGetCurrentSurface(EGL_DRAW); ++ m_previousEGLReadSurface = m_eglFun->eglGetCurrentSurface(EGL_READ); ++ m_previousEGLDisplay = m_eglFun->eglGetCurrentDisplay(); ++ } ++ ++ if (!m_context->create()) { ++ qWarning("Failed to create OpenGL context."); ++ return; ++ } ++ ++ Q_ASSERT(surface->isValid()); ++ if (!m_context->makeCurrent(surface)) { ++ qWarning("Failed to make OpenGL context current."); ++ return; ++ } ++ } ++ ++ ~ScopedGLContext() ++ { ++ if (!m_textures.empty()) { ++ auto *glFun = m_context->functions(); ++ glFun->glDeleteTextures(m_textures.size(), m_textures.data()); ++ } ++ ++ if (m_previousEGLContext) { ++ // Make sure the scoped context is not current when restoring the previous ++ // EGL context otherwise the QOpenGLContext destructor resets the restored ++ // current context. ++ m_context->doneCurrent(); ++ ++ m_eglFun->eglMakeCurrent(m_previousEGLDisplay, m_previousEGLDrawSurface, ++ m_previousEGLReadSurface, m_previousEGLContext); ++ if (m_eglFun->eglGetError() != EGL_SUCCESS) ++ qWarning("Failed to restore EGL context."); ++ } ++ } ++ ++ bool isValid() const { return m_context->isValid() && (m_context->surface() != nullptr); } ++ ++ EGLContext eglContext() const ++ { ++ QNativeInterface::QEGLContext *nativeInterface = ++ m_context->nativeInterface(); ++ return nativeInterface->nativeContext(); ++ } ++ ++ uint createTexture(int width, int height) ++ { ++ auto *glFun = m_context->functions(); ++ ++ uint glTexture; ++ glFun->glGenTextures(1, &glTexture); ++ glFun->glBindTexture(GL_TEXTURE_2D, glTexture); ++ glFun->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ++ NULL); ++ glFun->glBindTexture(GL_TEXTURE_2D, 0); ++ ++ m_textures.push_back(glTexture); ++ return glTexture; ++ } ++ ++private: ++ QScopedPointer m_context; ++ EGLHelper::EGLFunctions *m_eglFun; ++ EGLContext m_previousEGLContext = nullptr; ++ EGLSurface m_previousEGLDrawSurface = nullptr; ++ EGLSurface m_previousEGLReadSurface = nullptr; ++ EGLDisplay m_previousEGLDisplay = nullptr; ++ std::vector m_textures; ++}; ++ + EGLHelper::EGLFunctions::EGLFunctions() + { + QOpenGLContext *context = OzoneUtilQt::getQOpenGLContext(); +@@ -117,8 +199,23 @@ EGLHelper::EGLHelper() + const char *displayExtensions = m_functions->eglQueryString(m_eglDisplay, EGL_EXTENSIONS); + m_isDmaBufSupported = strstr(displayExtensions, "EGL_EXT_image_dma_buf_import") + && strstr(displayExtensions, "EGL_EXT_image_dma_buf_import_modifiers") +- && strstr(displayExtensions, "EGL_MESA_drm_image") + && strstr(displayExtensions, "EGL_MESA_image_dma_buf_export"); ++ m_isCreateDRMImageMesaSupported = strstr(displayExtensions, "EGL_MESA_drm_image"); ++ if (!m_isDmaBufSupported) { ++ qCDebug(QtWebEngineCore::lcWebEngineCompositor, ++ "EGL: MESA extensions not found, will not use dma-buf"); ++ } else if (!m_isCreateDRMImageMesaSupported) { ++ qCDebug(QtWebEngineCore::lcWebEngineCompositor, ++ "EGL: MESA extensions found but missing EGL_MESA_drm_image, will use dma-buf, " ++ "some older graphics cards may not be supported"); ++ m_offscreenSurface.reset(new QOffscreenSurface()); ++ Q_ASSERT(QThread::currentThread() == qApp->thread()); ++ m_offscreenSurface->create(); ++ } else { ++ qCDebug(QtWebEngineCore::lcWebEngineCompositor, ++ "EGL: MESA extensions and EGL_MESA_drm_image found, will use dma-buf with GEM " ++ "buffer allocation"); ++ } + } + + // Try to create dma-buf. +@@ -138,17 +235,38 @@ void EGLHelper::queryDmaBuf(const int width, const int height, int *fd, int *str + if (!m_isDmaBufSupported) + return; + +- // clang-format off +- EGLint attribs[] = { +- EGL_WIDTH, width, +- EGL_HEIGHT, height, +- EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, +- EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA, +- EGL_NONE +- }; +- // clang-format on +- +- EGLImage eglImage = m_functions->eglCreateDRMImageMESA(m_eglDisplay, attribs); ++ EGLImage eglImage = EGL_NO_IMAGE; ++ // Probably doesn't need to live to the end of the function, but just in case. ++ std::unique_ptr glContext; ++ if (m_isCreateDRMImageMesaSupported) { ++ // This approach is slightly worse for security and no longer supported in mesa 25.2, ++ // but it allows us to keep support for the Panthor driver prior to that mesa version. ++ // clang-format off ++ EGLint attribs[] = { ++ EGL_WIDTH, width, ++ EGL_HEIGHT, height, ++ EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, ++ EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA, ++ EGL_NONE ++ }; ++ // clang-format on ++ eglImage = m_functions->eglCreateDRMImageMESA(m_eglDisplay, attribs); ++ } else { ++ glContext = std::make_unique(m_offscreenSurface.get(), m_functions.get()); ++ if (!glContext->isValid()) ++ return; ++ ++ EGLContext eglContext = glContext->eglContext(); ++ if (!eglContext) { ++ qWarning("EGL: No EGLContext."); ++ return; ++ } ++ ++ uint64_t textureId = glContext->createTexture(width, height); ++ eglImage = m_functions->eglCreateImage(m_eglDisplay, eglContext, EGL_GL_TEXTURE_2D, ++ (EGLClientBuffer)textureId, NULL); ++ } ++ + if (eglImage == EGL_NO_IMAGE) { + qWarning("EGL: Failed to create EGLImage: %s", getLastEGLErrorString()); + return; +diff --git a/src/core/ozone/egl_helper.h b/src/core/ozone/egl_helper.h +index 6233ef87e4d..6e059baecb4 100644 +--- a/src/core/ozone/egl_helper.h ++++ b/src/core/ozone/egl_helper.h +@@ -25,6 +25,8 @@ + + QT_BEGIN_NAMESPACE + ++class QOffscreenSurface; ++ + class EGLHelper + { + public: +@@ -59,7 +61,9 @@ class EGLHelper + + EGLDisplay m_eglDisplay = EGL_NO_DISPLAY; + QScopedPointer m_functions; ++ QScopedPointer m_offscreenSurface; + bool m_isDmaBufSupported = false; ++ bool m_isCreateDRMImageMesaSupported = false; + }; + + QT_END_NAMESPACE diff --git a/gnu/packages/qt.scm b/gnu/packages/qt.scm index 738b6ca2e286dad7217f6f1a4c47fc80cdd1dd30..7ac66e6c05798829018ae99276b9dd5055d36c54 100644 --- a/gnu/packages/qt.scm +++ b/gnu/packages/qt.scm @@ -3729,6 +3729,9 @@ and binaries removed, and adds modular support for using system libraries.") (srfi srfi-1) (srfi srfi-26) (guix build utils))) + ;; This is only needed until 6.10, where it arrived upstream. + ;; https://codereview.qt-project.org/c/qt/qtwebengine/+/675112 + (patches (search-patches "qtwebengine-revert-egl.patch")) (snippet #~(begin ;; Note: Anything under a 'third_party/' directory that needs to