mirror of
https://git.savannah.gnu.org/git/guix.git
synced 2026-04-06 21:20:33 +02:00
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 <efraim@flashner.co.il> Signed-off-by: 宋文武 <iyzsong@member.fsf.org>
This commit is contained in:
@@ -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 \
|
||||
|
||||
228
gnu/packages/patches/qtwebengine-revert-egl.patch
Normal file
228
gnu/packages/patches/qtwebengine-revert-egl.patch
Normal file
@@ -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 <moss.heim@qt.io>
|
||||
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 <pvarga@inf.u-szeged.hu>
|
||||
---
|
||||
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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user