guix_mirror_bot pushed a commit to branch master
in repository guix.

commit 4a2ea8fab61b13b453298ef007278d16cc591403
Author: kestrel <[email protected]>
AuthorDate: Tue Oct 7 20:13:27 2025 +0300

    gnu: qtwebengine: Fix GPU rendering with mesa-25.2.0.
    
    * 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 <[email protected]>
    Signed-off-by: 宋文武 <[email protected]>
---
 gnu/local.mk                                      |   1 +
 gnu/packages/patches/qtwebengine-revert-egl.patch | 228 ++++++++++++++++++++++
 gnu/packages/qt.scm                               |   3 +
 3 files changed, 232 insertions(+)

diff --git a/gnu/local.mk b/gnu/local.mk
index 554c96d8ed..79f07f8824 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 0000000000..a13747f473
--- /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 <[email protected]>
+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 <[email protected]>
+---
+ 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 <QtCore/qthread.h>
+ #include <QtGui/qguiapplication.h>
++#include <QtGui/qoffscreensurface.h>
+ #include <QtGui/qopenglcontext.h>
+ #include <QtGui/qopenglfunctions.h>
+ #include <qpa/qplatformnativeinterface.h>
+@@ -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<QNativeInterface::QEGLContext>();
++        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<QOpenGLContext> m_context;
++    EGLHelper::EGLFunctions *m_eglFun;
++    EGLContext m_previousEGLContext = nullptr;
++    EGLSurface m_previousEGLDrawSurface = nullptr;
++    EGLSurface m_previousEGLReadSurface = nullptr;
++    EGLDisplay m_previousEGLDisplay = nullptr;
++    std::vector<uint> 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<ScopedGLContext> 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<ScopedGLContext>(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<EGLFunctions> m_functions;
++    QScopedPointer<QOffscreenSurface> 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 738b6ca2e2..7ac66e6c05 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

Reply via email to