projects/guix·blob python-team · refs

228 lines · 8.6 KiB

1https://codereview.qt-project.org/c/qt/qtwebengine/+/675112
2From 3cc88e0f85113e38ccb1bfdadb7d150c2389b1bc Mon Sep 17 00:00:00 2001
3From: Moss Heim <[email protected]>
4Date: Thu, 11 Sep 2025 13:47:04 +0200
5Subject: [PATCH] Return to supporting eglCreateImage in EGLHelper::queryDmaBuf
6
7eglCreateDRMImageMESA was removed in mesa 25.2.
8Keep using it where we can since this fixes support for
9panthor/panfrost, otherwise fall back to the old use of EGL API.
10
11Includes a revert of the following commits:
12Revert "Create EGLImage with eglCreateDRMImageMESA() for exporting dma_buf"
13This reverts commit 2ed5f9632292c6e531f353dae800cb12274af91a.
14Revert "Remove leftover QOffscreenSurface from EGLHelper"
15This reverts commit bcee2dbf412cc655c1b467091b581c696d234e3f.
16
17Pick-to: 6.9 6.10 6.10.0
18Task-number: QTBUG-136257
19Task-number: QTBUG-139424
20Change-Id: Ie115bd6373ce0a80651781aa568405477010ee25
21Reviewed-by: Peter Varga <[email protected]>
22---
23 src/core/ozone/egl_helper.cpp | 142 +++++++++++++++++++++++++++++++---
24 src/core/ozone/egl_helper.h | 4 +
25 2 files changed, 134 insertions(+), 12 deletions(-)
26
27diff --git a/src/core/ozone/egl_helper.cpp b/src/core/ozone/egl_helper.cpp
28index 76e1c2a4663..68e45ffd446 100644
29--- a/src/core/ozone/egl_helper.cpp
30+++ b/src/core/ozone/egl_helper.cpp
31@@ -3,10 +3,14 @@
32 // Qt-Security score:significant reason:default
33
34 #include "egl_helper.h"
35+
36+#include "compositor/compositor.h"
37 #include "ozone_util_qt.h"
38 #include "web_engine_context.h"
39
40+#include <QtCore/qthread.h>
41 #include <QtGui/qguiapplication.h>
42+#include <QtGui/qoffscreensurface.h>
43 #include <QtGui/qopenglcontext.h>
44 #include <QtGui/qopenglfunctions.h>
45 #include <qpa/qplatformnativeinterface.h>
46@@ -57,6 +61,84 @@ static const char *getEGLErrorString(uint32_t error)
47
48 QT_BEGIN_NAMESPACE
49
50+class ScopedGLContext
51+{
52+public:
53+ ScopedGLContext(QOffscreenSurface *surface, EGLHelper::EGLFunctions *eglFun)
54+ : m_context(new QOpenGLContext()), m_eglFun(eglFun)
55+ {
56+ if ((m_previousEGLContext = m_eglFun->eglGetCurrentContext())) {
57+ m_previousEGLDrawSurface = m_eglFun->eglGetCurrentSurface(EGL_DRAW);
58+ m_previousEGLReadSurface = m_eglFun->eglGetCurrentSurface(EGL_READ);
59+ m_previousEGLDisplay = m_eglFun->eglGetCurrentDisplay();
60+ }
61+
62+ if (!m_context->create()) {
63+ qWarning("Failed to create OpenGL context.");
64+ return;
65+ }
66+
67+ Q_ASSERT(surface->isValid());
68+ if (!m_context->makeCurrent(surface)) {
69+ qWarning("Failed to make OpenGL context current.");
70+ return;
71+ }
72+ }
73+
74+ ~ScopedGLContext()
75+ {
76+ if (!m_textures.empty()) {
77+ auto *glFun = m_context->functions();
78+ glFun->glDeleteTextures(m_textures.size(), m_textures.data());
79+ }
80+
81+ if (m_previousEGLContext) {
82+ // Make sure the scoped context is not current when restoring the previous
83+ // EGL context otherwise the QOpenGLContext destructor resets the restored
84+ // current context.
85+ m_context->doneCurrent();
86+
87+ m_eglFun->eglMakeCurrent(m_previousEGLDisplay, m_previousEGLDrawSurface,
88+ m_previousEGLReadSurface, m_previousEGLContext);
89+ if (m_eglFun->eglGetError() != EGL_SUCCESS)
90+ qWarning("Failed to restore EGL context.");
91+ }
92+ }
93+
94+ bool isValid() const { return m_context->isValid() && (m_context->surface() != nullptr); }
95+
96+ EGLContext eglContext() const
97+ {
98+ QNativeInterface::QEGLContext *nativeInterface =
99+ m_context->nativeInterface<QNativeInterface::QEGLContext>();
100+ return nativeInterface->nativeContext();
101+ }
102+
103+ uint createTexture(int width, int height)
104+ {
105+ auto *glFun = m_context->functions();
106+
107+ uint glTexture;
108+ glFun->glGenTextures(1, &glTexture);
109+ glFun->glBindTexture(GL_TEXTURE_2D, glTexture);
110+ glFun->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
111+ NULL);
112+ glFun->glBindTexture(GL_TEXTURE_2D, 0);
113+
114+ m_textures.push_back(glTexture);
115+ return glTexture;
116+ }
117+
118+private:
119+ QScopedPointer<QOpenGLContext> m_context;
120+ EGLHelper::EGLFunctions *m_eglFun;
121+ EGLContext m_previousEGLContext = nullptr;
122+ EGLSurface m_previousEGLDrawSurface = nullptr;
123+ EGLSurface m_previousEGLReadSurface = nullptr;
124+ EGLDisplay m_previousEGLDisplay = nullptr;
125+ std::vector<uint> m_textures;
126+};
127+
128 EGLHelper::EGLFunctions::EGLFunctions()
129 {
130 QOpenGLContext *context = OzoneUtilQt::getQOpenGLContext();
131@@ -117,8 +199,23 @@ EGLHelper::EGLHelper()
132 const char *displayExtensions = m_functions->eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
133 m_isDmaBufSupported = strstr(displayExtensions, "EGL_EXT_image_dma_buf_import")
134 && strstr(displayExtensions, "EGL_EXT_image_dma_buf_import_modifiers")
135- && strstr(displayExtensions, "EGL_MESA_drm_image")
136 && strstr(displayExtensions, "EGL_MESA_image_dma_buf_export");
137+ m_isCreateDRMImageMesaSupported = strstr(displayExtensions, "EGL_MESA_drm_image");
138+ if (!m_isDmaBufSupported) {
139+ qCDebug(QtWebEngineCore::lcWebEngineCompositor,
140+ "EGL: MESA extensions not found, will not use dma-buf");
141+ } else if (!m_isCreateDRMImageMesaSupported) {
142+ qCDebug(QtWebEngineCore::lcWebEngineCompositor,
143+ "EGL: MESA extensions found but missing EGL_MESA_drm_image, will use dma-buf, "
144+ "some older graphics cards may not be supported");
145+ m_offscreenSurface.reset(new QOffscreenSurface());
146+ Q_ASSERT(QThread::currentThread() == qApp->thread());
147+ m_offscreenSurface->create();
148+ } else {
149+ qCDebug(QtWebEngineCore::lcWebEngineCompositor,
150+ "EGL: MESA extensions and EGL_MESA_drm_image found, will use dma-buf with GEM "
151+ "buffer allocation");
152+ }
153 }
154
155 // Try to create dma-buf.
156@@ -138,17 +235,38 @@ void EGLHelper::queryDmaBuf(const int width, const int height, int *fd, int *str
157 if (!m_isDmaBufSupported)
158 return;
159
160- // clang-format off
161- EGLint attribs[] = {
162- EGL_WIDTH, width,
163- EGL_HEIGHT, height,
164- EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
165- EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA,
166- EGL_NONE
167- };
168- // clang-format on
169-
170- EGLImage eglImage = m_functions->eglCreateDRMImageMESA(m_eglDisplay, attribs);
171+ EGLImage eglImage = EGL_NO_IMAGE;
172+ // Probably doesn't need to live to the end of the function, but just in case.
173+ std::unique_ptr<ScopedGLContext> glContext;
174+ if (m_isCreateDRMImageMesaSupported) {
175+ // This approach is slightly worse for security and no longer supported in mesa 25.2,
176+ // but it allows us to keep support for the Panthor driver prior to that mesa version.
177+ // clang-format off
178+ EGLint attribs[] = {
179+ EGL_WIDTH, width,
180+ EGL_HEIGHT, height,
181+ EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
182+ EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA,
183+ EGL_NONE
184+ };
185+ // clang-format on
186+ eglImage = m_functions->eglCreateDRMImageMESA(m_eglDisplay, attribs);
187+ } else {
188+ glContext = std::make_unique<ScopedGLContext>(m_offscreenSurface.get(), m_functions.get());
189+ if (!glContext->isValid())
190+ return;
191+
192+ EGLContext eglContext = glContext->eglContext();
193+ if (!eglContext) {
194+ qWarning("EGL: No EGLContext.");
195+ return;
196+ }
197+
198+ uint64_t textureId = glContext->createTexture(width, height);
199+ eglImage = m_functions->eglCreateImage(m_eglDisplay, eglContext, EGL_GL_TEXTURE_2D,
200+ (EGLClientBuffer)textureId, NULL);
201+ }
202+
203 if (eglImage == EGL_NO_IMAGE) {
204 qWarning("EGL: Failed to create EGLImage: %s", getLastEGLErrorString());
205 return;
206diff --git a/src/core/ozone/egl_helper.h b/src/core/ozone/egl_helper.h
207index 6233ef87e4d..6e059baecb4 100644
208--- a/src/core/ozone/egl_helper.h
209+++ b/src/core/ozone/egl_helper.h
210@@ -25,6 +25,8 @@
211
212 QT_BEGIN_NAMESPACE
213
214+class QOffscreenSurface;
215+
216 class EGLHelper
217 {
218 public:
219@@ -59,7 +61,9 @@ class EGLHelper
220
221 EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
222 QScopedPointer<EGLFunctions> m_functions;
223+ QScopedPointer<QOffscreenSurface> m_offscreenSurface;
224 bool m_isDmaBufSupported = false;
225+ bool m_isCreateDRMImageMesaSupported = false;
226 };
227
228 QT_END_NAMESPACE