1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the plugins of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qminimaleglscreen.h" |
41 | #include "qminimaleglwindow.h" |
42 | |
43 | #include <QtEglSupport/private/qeglconvenience_p.h> |
44 | #ifndef QT_NO_OPENGL |
45 | # include <QtEglSupport/private/qeglplatformcontext_p.h> |
46 | #endif |
47 | |
48 | #ifdef Q_OPENKODE |
49 | #include <KD/kd.h> |
50 | #include <KD/NV_initialize.h> |
51 | #endif //Q_OPENKODE |
52 | |
53 | QT_BEGIN_NAMESPACE |
54 | |
55 | // #define QEGL_EXTRA_DEBUG |
56 | |
57 | #ifndef QT_NO_OPENGL |
58 | |
59 | class QMinimalEglContext : public QEGLPlatformContext |
60 | { |
61 | public: |
62 | QMinimalEglContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display) |
63 | : QEGLPlatformContext(format, share, display) |
64 | { |
65 | } |
66 | |
67 | EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override |
68 | { |
69 | QMinimalEglWindow *window = static_cast<QMinimalEglWindow *>(surface); |
70 | QMinimalEglScreen *screen = static_cast<QMinimalEglScreen *>(window->screen()); |
71 | return screen->surface(); |
72 | } |
73 | }; |
74 | |
75 | #endif |
76 | |
77 | QMinimalEglScreen::QMinimalEglScreen(EGLNativeDisplayType display) |
78 | : m_depth(32) |
79 | , m_format(QImage::Format_Invalid) |
80 | , m_platformContext(0) |
81 | , m_surface(0) |
82 | { |
83 | #ifdef QEGL_EXTRA_DEBUG |
84 | qWarning("QEglScreen %p\n" , this); |
85 | #endif |
86 | |
87 | EGLint major, minor; |
88 | |
89 | if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API))) { |
90 | qWarning(msg: "Could not bind GL_ES API\n" ); |
91 | qFatal(msg: "EGL error" ); |
92 | } |
93 | |
94 | m_dpy = eglGetDisplay(display_id: display); |
95 | if (Q_UNLIKELY(m_dpy == EGL_NO_DISPLAY)) { |
96 | qWarning(msg: "Could not open egl display\n" ); |
97 | qFatal(msg: "EGL error" ); |
98 | } |
99 | qWarning(msg: "Opened display %p\n" , m_dpy); |
100 | |
101 | if (Q_UNLIKELY(!eglInitialize(m_dpy, &major, &minor))) { |
102 | qWarning(msg: "Could not initialize egl display\n" ); |
103 | qFatal(msg: "EGL error" ); |
104 | } |
105 | |
106 | qWarning(msg: "Initialized display %d %d\n" , major, minor); |
107 | } |
108 | |
109 | QMinimalEglScreen::~QMinimalEglScreen() |
110 | { |
111 | if (m_surface) |
112 | eglDestroySurface(dpy: m_dpy, surface: m_surface); |
113 | |
114 | eglTerminate(dpy: m_dpy); |
115 | } |
116 | |
117 | void QMinimalEglScreen::createAndSetPlatformContext() const { |
118 | const_cast<QMinimalEglScreen *>(this)->createAndSetPlatformContext(); |
119 | } |
120 | |
121 | void QMinimalEglScreen::createAndSetPlatformContext() |
122 | { |
123 | QSurfaceFormat platformFormat; |
124 | |
125 | QByteArray depthString = qgetenv(varName: "QT_QPA_EGLFS_DEPTH" ); |
126 | if (depthString.toInt() == 16) { |
127 | platformFormat.setDepthBufferSize(16); |
128 | platformFormat.setRedBufferSize(5); |
129 | platformFormat.setGreenBufferSize(6); |
130 | platformFormat.setBlueBufferSize(5); |
131 | m_depth = 16; |
132 | m_format = QImage::Format_RGB16; |
133 | } else { |
134 | platformFormat.setDepthBufferSize(24); |
135 | platformFormat.setStencilBufferSize(8); |
136 | platformFormat.setRedBufferSize(8); |
137 | platformFormat.setGreenBufferSize(8); |
138 | platformFormat.setBlueBufferSize(8); |
139 | m_depth = 32; |
140 | m_format = QImage::Format_RGB32; |
141 | } |
142 | |
143 | if (!qEnvironmentVariableIsEmpty(varName: "QT_QPA_EGLFS_MULTISAMPLE" )) |
144 | platformFormat.setSamples(4); |
145 | |
146 | EGLConfig config = q_configFromGLFormat(display: m_dpy, format: platformFormat); |
147 | |
148 | EGLNativeWindowType eglWindow = 0; |
149 | #ifdef Q_OPENKODE |
150 | if (Q_UNLIKELY(kdInitializeNV() == KD_ENOTINITIALIZED)) |
151 | qFatal("Did not manage to initialize openkode" ); |
152 | |
153 | KDWindow *window = kdCreateWindow(m_dpy,config,0); |
154 | |
155 | kdRealizeWindow(window,&eglWindow); |
156 | #endif |
157 | |
158 | #ifdef QEGL_EXTRA_DEBUG |
159 | q_printEglConfig(m_dpy, config); |
160 | #endif |
161 | |
162 | m_surface = eglCreateWindowSurface(dpy: m_dpy, config, win: eglWindow, NULL); |
163 | if (Q_UNLIKELY(m_surface == EGL_NO_SURFACE)) { |
164 | qWarning(msg: "Could not create the egl surface: error = 0x%x\n" , eglGetError()); |
165 | eglTerminate(dpy: m_dpy); |
166 | qFatal(msg: "EGL error" ); |
167 | } |
168 | // qWarning("Created surface %dx%d\n", w, h); |
169 | |
170 | #ifndef QT_NO_OPENGL |
171 | QEGLPlatformContext *platformContext = new QMinimalEglContext(platformFormat, 0, m_dpy); |
172 | m_platformContext = platformContext; |
173 | #endif |
174 | EGLint w,h; // screen size detection |
175 | eglQuerySurface(dpy: m_dpy, surface: m_surface, EGL_WIDTH, value: &w); |
176 | eglQuerySurface(dpy: m_dpy, surface: m_surface, EGL_HEIGHT, value: &h); |
177 | |
178 | m_geometry = QRect(0,0,w,h); |
179 | |
180 | } |
181 | |
182 | QRect QMinimalEglScreen::geometry() const |
183 | { |
184 | if (m_geometry.isNull()) { |
185 | createAndSetPlatformContext(); |
186 | } |
187 | return m_geometry; |
188 | } |
189 | |
190 | int QMinimalEglScreen::depth() const |
191 | { |
192 | return m_depth; |
193 | } |
194 | |
195 | QImage::Format QMinimalEglScreen::format() const |
196 | { |
197 | if (m_format == QImage::Format_Invalid) |
198 | createAndSetPlatformContext(); |
199 | return m_format; |
200 | } |
201 | #ifndef QT_NO_OPENGL |
202 | QPlatformOpenGLContext *QMinimalEglScreen::platformContext() const |
203 | { |
204 | if (!m_platformContext) { |
205 | QMinimalEglScreen *that = const_cast<QMinimalEglScreen *>(this); |
206 | that->createAndSetPlatformContext(); |
207 | } |
208 | return m_platformContext; |
209 | } |
210 | #endif |
211 | QT_END_NAMESPACE |
212 | |