Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqnxeglwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2013 - 2014 BlackBerry Limited. All rights reserved.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
7#include "qqnxscreen.h"
9
10#include <QDebug>
11
12#include <errno.h>
13
15
16Q_LOGGING_CATEGORY(lcQpaWindowEgl, "qt.qpa.window.egl");
17
18QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context, bool needRootWindow) :
19 QQnxWindow(window, context, needRootWindow),
21 m_eglDisplay(EGL_NO_DISPLAY),
22 m_eglSurface(EGL_NO_SURFACE)
23{
24 initWindow();
25
26 m_requestedBufferSize = shouldMakeFullScreen() ? screen()->geometry().size() : window->geometry().size();
27}
28
30{
31 // Cleanup EGL surface if it exists
32 destroyEGLSurface();
33}
34
36{
37 return m_eglSurface != EGL_NO_SURFACE;
38}
39
41{
42 if (m_newSurfaceRequested.testAndSetOrdered(true, false)) {
43 const QMutexLocker locker(&m_mutex); // Set geometry must not reset the requestedBufferSize till
44 // the surface is created
45
46 if (m_requestedBufferSize != bufferSize() || m_eglSurface == EGL_NO_SURFACE) {
47 if (m_eglSurface != EGL_NO_SURFACE) {
48 context->doneCurrent();
49 destroyEGLSurface();
50 }
51 createEGLSurface(context);
52 } else {
53 // Must've been a sequence of unprocessed changes returning us to the original size.
55 }
56 }
57}
58
59void QQnxEglWindow::createEGLSurface(QQnxGLContext *context)
60{
61 if (context->format().renderableType() != QSurfaceFormat::OpenGLES) {
62 qFatal("QQnxEglWindow: renderable type is not OpenGLES");
63 return;
64 }
65
66 // Set window usage
67 int usage = SCREEN_USAGE_OPENGL_ES2;
69 if (context->format().majorVersion() == 3)
70 usage |= SCREEN_USAGE_OPENGL_ES3;
71#endif
72
73 const int result = screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_USAGE, &usage);
74 if (Q_UNLIKELY(result != 0))
75 qFatal("QQnxEglWindow: failed to set window usage, errno=%d", errno);
76
77 if (!m_requestedBufferSize.isValid()) {
78 qWarning("QQNX: Trying to create 0 size EGL surface. "
79 "Please set a valid window size before calling QOpenGLContext::makeCurrent()");
80 return;
81 }
82
83 m_eglDisplay = context->eglDisplay();
84 m_eglConfig = context->eglConfig();
85 m_format = context->format();
86
87 // update the window's buffers before we create the EGL surface
88 setBufferSize(m_requestedBufferSize);
89
90 const EGLint eglSurfaceAttrs[] =
91 {
92 EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
93 EGL_NONE
94 };
95
96 qCDebug(lcQpaWindowEgl) << "Creating EGL surface from" << this << context
97 << window()->surfaceType() << window()->type();
98
99 // Create EGL surface
100 EGLSurface eglSurface = eglCreateWindowSurface(
101 m_eglDisplay,
102 m_eglConfig,
103 (EGLNativeWindowType) nativeHandle(),
104 eglSurfaceAttrs);
105
106 if (eglSurface == EGL_NO_SURFACE)
107 qWarning("QQNX: failed to create EGL surface, err=%d", eglGetError());
108
109 m_eglSurface = eglSurface;
110}
111
112void QQnxEglWindow::destroyEGLSurface()
113{
114 // Destroy EGL surface if it exists
115 if (m_eglSurface != EGL_NO_SURFACE) {
116 EGLBoolean eglResult = eglDestroySurface(m_eglDisplay, m_eglSurface);
117 if (Q_UNLIKELY(eglResult != EGL_TRUE))
118 qFatal("QQNX: failed to destroy EGL surface, err=%d", eglGetError());
119 }
120
121 m_eglSurface = EGL_NO_SURFACE;
122}
123
124EGLSurface QQnxEglWindow::surface() const
125{
126 return m_eglSurface;
127}
128
129void QQnxEglWindow::setGeometry(const QRect &rect)
130{
131 // In fullscreen mode, top-level windows are forced to screen geometry
132 const QRect &newGeometry = shouldMakeFullScreen() ? screen()->geometry() : rect;
133
134 //We need to request that the GL context updates
135 // the EGLsurface on which it is rendering.
136 {
137 // We want the setting of the atomic bool in the GL context to be atomic with
138 // setting m_requestedBufferSize and therefore extended the scope to include
139 // that test.
140 const QMutexLocker locker(&m_mutex);
141 m_requestedBufferSize = newGeometry.size();
142 if (isInitialized() && bufferSize() != newGeometry.size())
143 m_newSurfaceRequested.testAndSetRelease(false, true);
144 }
145 QQnxWindow::setGeometry(newGeometry);
146}
147
149{
150 // Extract size of color channels from window format
151 const int redSize = m_format.redBufferSize();
152 if (Q_UNLIKELY(redSize == -1))
153 qFatal("QQnxWindow: red size not defined");
154
155 const int greenSize = m_format.greenBufferSize();
156 if (Q_UNLIKELY(greenSize == -1))
157 qFatal("QQnxWindow: green size not defined");
158
159 const int blueSize = m_format.blueBufferSize();
160 if (Q_UNLIKELY(blueSize == -1))
161 qFatal("QQnxWindow: blue size not defined");
162
163 // select matching native format
164 if (redSize == 5 && greenSize == 6 && blueSize == 5)
165 return SCREEN_FORMAT_RGB565;
166 else if (redSize == 8 && greenSize == 8 && blueSize == 8)
167 return SCREEN_FORMAT_RGBA8888;
168
169 qFatal("QQnxWindow: unsupported pixel format");
170}
171
173{
174 m_requestedBufferSize = QSize();
175}
176
177QT_END_NAMESPACE
bool isInitialized() const
void resetBuffers() override
QQnxEglWindow(QWindow *window, screen_context_t context, bool needRootWindow)
int pixelFormat() const override
EGLSurface surface() const
void ensureInitialized(QQnxGLContext *context)
void setGeometry(const QRect &rect) override
This function is called by Qt whenever a window is moved or resized using the QWindow API.
void doneCurrent() override
The QQnxWindow is the base class of the various classes used as instances of QPlatformWindow in the Q...
Definition qqnxwindow.h:32
void initWindow()
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
#define _SCREEN_VERSION
Definition qqnxscreen.h:19
#define _SCREEN_MAKE_VERSION(major, minor, patch)
Definition qqnxscreen.h:18