Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qeglfswindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qtextstream.h>
5#include <qpa/qwindowsysteminterface.h>
6#include <qpa/qplatformintegration.h>
7#include <private/qguiapplication_p.h>
8#include <private/qwindow_p.h>
9#ifndef QT_NO_OPENGL
10# include <QtGui/private/qopenglcontext_p.h>
11# include <QtGui/QOpenGLContext>
12# include <QtOpenGL/private/qopenglcompositorbackingstore_p.h>
13#endif
14#include <QtGui/private/qeglconvenience_p.h>
15
16#include "qeglfswindow_p.h"
17#ifndef QT_NO_OPENGL
18# include "qeglfscursor_p.h"
19#endif
20#include "qeglfshooks_p.h"
22
24
25Q_DECLARE_LOGGING_CATEGORY(qLcEglDevDebug)
26
29#ifndef QT_NO_OPENGL
30 m_backingStore(nullptr),
31 m_rasterCompositingContext(nullptr),
32#endif
33 m_winId(0),
34 m_surface(EGL_NO_SURFACE),
35 m_window(0)
36{
37}
38
43
44static WId newWId()
45{
46 static WId id = 0;
47
48 if (id == std::numeric_limits<WId>::max())
49 qWarning("QEGLPlatformWindow: Out of window IDs");
50
51 return ++id;
52}
53
55{
56 if (m_flags.testFlag(Created))
57 return;
58
59 m_winId = newWId();
60
61 if (window()->type() == Qt::Desktop) {
62 QRect fullscreenRect(QPoint(), screen()->availableGeometry().size());
64 return;
65 }
66
68
69 if (window()->type() == Qt::Desktop)
70 return;
71
72 // Stop if there is already a window backed by a native window and surface. Additional
73 // raster windows will not have their own native window, surface and context. Instead,
74 // they will be composited onto the root window's surface.
75 QEglFSScreen *screen = this->screen();
76#ifndef QT_NO_OPENGL
78 if (screen->primarySurface() != EGL_NO_SURFACE) {
79 if (Q_UNLIKELY(isRaster() != (compositor->targetWindow() != nullptr))) {
80# ifndef Q_OS_ANDROID
81 // We can have either a single OpenGL window or multiple raster windows.
82 // Other combinations cannot work.
83 qFatal("EGLFS: OpenGL windows cannot be mixed with others.");
84# endif
85 return;
86 }
87 m_format = compositor->targetWindow()->format();
88 return;
89 }
90#endif // QT_NO_OPENGL
91
93 setGeometry(QRect()); // will become fullscreen
94
96
97 if (Q_UNLIKELY(m_surface == EGL_NO_SURFACE)) {
98 EGLint error = eglGetError();
99 eglTerminate(screen->display());
100 qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error);
101 }
102
103 screen->setPrimarySurface(m_surface);
104
105#ifndef QT_NO_OPENGL
106 compositor->setTargetWindow(window(), screen->rawGeometry());
107 compositor->setRotation(qEnvironmentVariableIntValue("QT_QPA_EGLFS_ROTATION"));
108#endif
109}
110
112{
113#ifndef QT_NO_OPENGL
120 qFatal("EGLFS: Failed to create compositing context");
121 // If there is a "root" window into which raster and QOpenGLWidget content is
122 // composited, all other contexts must share with its context.
125 }
127 compositor->setTargetContext(m_rasterCompositingContext);
128#endif
130}
131
133{
134 if (!m_flags.testFlag(Created))
135 return; // already destroyed
136
137#ifndef QT_NO_OPENGL
138 QOpenGLCompositor::instance()->removeWindow(this);
139#endif
140
141 QEglFSScreen *screen = this->screen();
142 if (m_flags.testFlag(HasNativeWindow)) {
143#ifndef QT_NO_OPENGL
144 QEglFSCursor *cursor = qobject_cast<QEglFSCursor *>(screen->cursor());
145 if (cursor)
146 cursor->resetResources();
147#endif
149 screen->setPrimarySurface(EGL_NO_SURFACE);
150
152
153#ifndef QT_NO_OPENGL
158#endif
159 }
160
161 m_flags = { };
162}
163
165{
166 if (m_surface != EGL_NO_SURFACE) {
167 qCDebug(qLcEglDevDebug) << Q_FUNC_INFO << " about to destroy EGLSurface: " << m_surface;
168
169 bool ok = eglDestroySurface(screen()->display(), m_surface);
170
171 if (!ok) {
172 qCWarning(qLcEglDevDebug, "QEglFSWindow::invalidateSurface() eglDestroySurface failed!"
173 " Follow-up errors or memory leaks are possible."
174 " eglGetError(): %x", eglGetError());
175 }
176
177 if (eglGetCurrentSurface(EGL_READ) == m_surface ||
178 eglGetCurrentSurface(EGL_DRAW) == m_surface) {
179 bool ok = eglMakeCurrent(eglGetCurrentDisplay(), EGL_NO_DISPLAY, EGL_NO_DISPLAY, EGL_NO_CONTEXT);
180 qCDebug(qLcEglDevDebug) << Q_FUNC_INFO << " due to eglDestroySurface on *currently* bound surface"
181 << "we just called eglMakeCurrent(..,0,0,0)! It returned: " << ok;
182 }
183
184 if (screen()->primarySurface() == m_surface)
185 screen()->setPrimarySurface(EGL_NO_SURFACE);
186
187
188 m_surface = EGL_NO_SURFACE;
189 m_flags = m_flags & ~Created;
190 }
192 m_window = 0;
193}
194
196{
198 QSurfaceFormat platformFormat = qt_egl_device_integration()->surfaceFormatFor(window()->requestedFormat());
199
201 m_format = q_glFormatFromConfig(display, m_config, platformFormat);
202 const QSize surfaceSize = screen()->rawGeometry().size();
204 m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr);
205}
206
207void QEglFSWindow::setVisible(bool visible)
208{
209#ifndef QT_NO_OPENGL
211 QList<QOpenGLCompositorWindow *> windows = compositor->windows();
212 QWindow *wnd = window();
213
214 if (wnd->type() != Qt::Desktop) {
215 if (visible) {
216 compositor->addWindow(this);
217 } else {
218 compositor->removeWindow(this);
219 windows = compositor->windows();
220 if (windows.size())
221 windows.last()->sourceWindow()->requestActivate();
222 }
223 }
224#else
225 QWindow *wnd = window();
226#endif
227 QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
228
229 if (visible)
231}
232
234{
235 QRect rect = r;
236 if (m_flags.testFlag(HasNativeWindow))
238
240
242
243 const QRect lastReportedGeometry = qt_window_private(window())->geometry;
244 if (rect != lastReportedGeometry)
246}
247
249{
250 // For yet-to-become-fullscreen windows report the geometry covering the entire
251 // screen. This is particularly important for Quick where the root object may get
252 // sized to some geometry queried before calling create().
253 if (!m_flags.testFlag(Created) && screen()->primarySurface() == EGL_NO_SURFACE)
254 return screen()->availableGeometry();
255
257}
258
260{
261#ifndef QT_NO_OPENGL
262 if (window()->type() != Qt::Desktop)
263 QOpenGLCompositor::instance()->moveToTop(this);
264#endif
265 QWindow *wnd = window();
267 QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
268}
269
271{
272 QWindow *wnd = window();
273 if (wnd->type() != Qt::Desktop) {
274#ifndef QT_NO_OPENGL
275 QOpenGLCompositor::instance()->moveToTop(this);
276#endif
277 QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
278 }
279}
280
282{
283#ifndef QT_NO_OPENGL
285 QList<QOpenGLCompositorWindow *> windows = compositor->windows();
286 if (window()->type() != Qt::Desktop && windows.size() > 1) {
287 int idx = windows.indexOf(this);
288 if (idx > 0) {
289 compositor->changeWindowIndex(this, idx - 1);
290 QWindowSystemInterface::handleExposeEvent(windows.last()->sourceWindow(),
291 QRect(QPoint(0, 0), windows.last()->sourceWindow()->geometry().size()));
292 }
293 }
294#endif
295}
296
298{
299 return m_surface != EGL_NO_SURFACE ? m_surface : screen()->primarySurface();
300}
301
303{
304 return m_format;
305}
306
307EGLNativeWindowType QEglFSWindow::eglWindow() const
308{
309 return m_window;
310}
311
313{
314 return static_cast<QEglFSScreen *>(QPlatformWindow::screen());
315}
316
322
323#ifndef QT_NO_OPENGL
325{
326 return window();
327}
328
330{
331 if (m_backingStore)
332 return m_backingStore->textures();
333
334 return nullptr;
335}
336
342#endif
343
345{
346 return m_winId;
347}
348
350{
351 if (!isRaster() && !backingStore())
352 qWarning("QEglFSWindow: Cannot set opacity for non-raster windows");
353
354 // Nothing to do here. The opacity is stored in the QWindow.
355}
356
virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const
virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format)
static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
virtual void destroyNativeWindow(EGLNativeWindowType window)
QPlatformCursor * cursor() const override
Reimplement this function in subclass to return the cursor of the screen.
virtual QRect rawGeometry() const
EGLSurface primarySurface() const
EGLDisplay display() const
EGLSurface m_surface
EGLConfig m_config
QWindow * sourceWindow() const override
void setOpacity(qreal) override
Reimplement to be able to let Qt set the opacity level of a window.
void invalidateSurface() override
Invalidates the window's surface by releasing its surface buffers.
void setVisible(bool visible) override
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
QOpenGLCompositorBackingStore * backingStore() const override
QSurfaceFormat m_format
EGLNativeWindowType eglWindow() const
void raise() override
Reimplement to be able to let Qt raise windows to the top of the desktop.
const QPlatformTextureList * textures() const override
QSurfaceFormat format() const override
Returns the actual surface format of the window.
virtual void resetSurface()
WId winId() const override
Reimplement in subclasses to return a handle to the native window.
void lower() override
Reimplement to be able to let Qt lower windows to the bottom of the desktop.
EGLSurface surface() const
QRect geometry() const override
Returns the current geometry of a window.
QOpenGLContext * m_rasterCompositingContext
EGLNativeWindowType m_window
void setGeometry(const QRect &) override
This function is called by Qt whenever a window is moved or resized using the QWindow API.
void requestActivateWindow() override
Reimplement to let Qt be able to request activation/focus for a window.
void setBackingStore(QOpenGLCompositorBackingStore *backingStore) override
QEglFSScreen * screen() const override
bool isRaster() const
void endCompositing() override
QOpenGLCompositorBackingStore * m_backingStore
@ ExcludeUserInputEvents
Definition qeventloop.h:27
A backing store implementation for OpenGL.
const QPlatformTextureList * textures() const
A generic OpenGL-based compositor.
static QOpenGLCompositor * instance()
\inmodule QtGui
bool create()
Attempts to create the OpenGL context with the current configuration.
void setScreen(QScreen *screen)
Sets the screen the OpenGL context should be valid for.
void setShareContext(QOpenGLContext *shareContext)
Makes this context share textures, shaders, and other OpenGL resources with shareContext.
void setFormat(const QSurfaceFormat &format)
Sets the format the OpenGL context should be compatible with.
virtual QRect availableGeometry() const
Reimplement in subclass to return the pixel geometry of the available space This normally is the desk...
The QPlatformWindow class provides an abstraction for top-level windows.
QWindow * window() const
Returns the window which belongs to the QPlatformWindow.
QPlatformScreen * screen() const override
Returns the platform screen handle corresponding to this platform window, or null if the window is no...
virtual void setGeometry(const QRect &rect)
This function is called by Qt whenever a window is moved or resized using the QWindow API.
virtual QRect geometry() const
Returns the current geometry of a window.
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:25
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
SurfaceType
The SurfaceType enum describes what type of surface this is.
Definition qsurface.h:30
@ RasterGLSurface
Definition qsurface.h:33
@ RasterSurface
Definition qsurface.h:31
static bool flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
Make Qt Gui process all events on the event queue immediately.
static void handleFocusWindowChanged(QWindow *window, Qt::FocusReason r=Qt::OtherFocusReason)
static void handleGeometryChange(QWindow *window, const QRect &newRect)
static bool handleExposeEvent(QWindow *window, const QRegion &region)
\inmodule QtGui
Definition qwindow.h:63
SurfaceType surfaceType() const override
Returns the surface type of the window.
Definition qwindow.cpp:665
QCursor cursor
rect
[4]
struct wl_display * display
Definition linuxdmabuf.h:41
Combined button and popup list for selecting options.
@ Desktop
Definition qnamespace.h:215
@ ActiveWindowFocusReason
#define Q_UNLIKELY(x)
#define Q_FUNC_INFO
DBusConnection const char DBusError * error
QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, const QSurfaceFormat &referenceFormat)
QEglFSDeviceIntegration * qt_egl_device_integration()
static WId newWId()
typedef EGLSurface(EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)(EGLDisplay dpy
typedef EGLDisplay(EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum platform
#define qWarning
Definition qlogging.h:166
#define qFatal
Definition qlogging.h:168
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
static QOpenGLCompositor * compositor
QOpenGLContext * qt_gl_global_share_context()
void qt_gl_set_global_share_context(QOpenGLContext *context)
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLenum GLuint id
[7]
GLenum type
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
double qreal
Definition qtypes.h:187
Q_GUI_EXPORT QWindowPrivate * qt_window_private(QWindow *window)
Definition qwindow.cpp:2950