1 | // Copyright (C) 2016 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 "qminimaleglscreen.h" |
5 | #include "qminimaleglwindow.h" |
6 | |
7 | #include <QtGui/private/qeglconvenience_p.h> |
8 | #ifndef QT_NO_OPENGL |
9 | # include <QtGui/private/qeglplatformcontext_p.h> |
10 | #endif |
11 | |
12 | #ifdef Q_OPENKODE |
13 | #include <KD/kd.h> |
14 | #include <KD/NV_initialize.h> |
15 | #endif //Q_OPENKODE |
16 | |
17 | QT_BEGIN_NAMESPACE |
18 | |
19 | // #define QEGL_EXTRA_DEBUG |
20 | |
21 | #ifndef QT_NO_OPENGL |
22 | |
23 | class QMinimalEglContext : public QEGLPlatformContext |
24 | { |
25 | public: |
26 | QMinimalEglContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display) |
27 | : QEGLPlatformContext(format, share, display) |
28 | { |
29 | } |
30 | |
31 | EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override |
32 | { |
33 | QMinimalEglWindow *window = static_cast<QMinimalEglWindow *>(surface); |
34 | QMinimalEglScreen *screen = static_cast<QMinimalEglScreen *>(window->screen()); |
35 | return screen->surface(); |
36 | } |
37 | }; |
38 | |
39 | #endif |
40 | |
41 | QMinimalEglScreen::QMinimalEglScreen(EGLNativeDisplayType display) |
42 | : m_depth(32) |
43 | , m_format(QImage::Format_Invalid) |
44 | , m_platformContext(nullptr) |
45 | , m_surface(nullptr) |
46 | { |
47 | #ifdef QEGL_EXTRA_DEBUG |
48 | qWarning("QEglScreen %p\n" , this); |
49 | #endif |
50 | |
51 | EGLint major, minor; |
52 | |
53 | if (Q_UNLIKELY(!eglBindAPI(EGL_OPENGL_ES_API))) { |
54 | qWarning(msg: "Could not bind GL_ES API\n" ); |
55 | qFatal(msg: "EGL error" ); |
56 | } |
57 | |
58 | m_dpy = eglGetDisplay(display_id: display); |
59 | if (Q_UNLIKELY(m_dpy == EGL_NO_DISPLAY)) { |
60 | qWarning(msg: "Could not open egl display\n" ); |
61 | qFatal(msg: "EGL error" ); |
62 | } |
63 | qWarning(msg: "Opened display %p\n" , m_dpy); |
64 | |
65 | if (Q_UNLIKELY(!eglInitialize(m_dpy, &major, &minor))) { |
66 | qWarning(msg: "Could not initialize egl display\n" ); |
67 | qFatal(msg: "EGL error" ); |
68 | } |
69 | |
70 | qWarning(msg: "Initialized display %d %d\n" , major, minor); |
71 | } |
72 | |
73 | QMinimalEglScreen::~QMinimalEglScreen() |
74 | { |
75 | if (m_surface) |
76 | eglDestroySurface(dpy: m_dpy, surface: m_surface); |
77 | |
78 | eglTerminate(dpy: m_dpy); |
79 | } |
80 | |
81 | void QMinimalEglScreen::createAndSetPlatformContext() const { |
82 | const_cast<QMinimalEglScreen *>(this)->createAndSetPlatformContext(); |
83 | } |
84 | |
85 | void QMinimalEglScreen::createAndSetPlatformContext() |
86 | { |
87 | QSurfaceFormat platformFormat; |
88 | |
89 | QByteArray depthString = qgetenv(varName: "QT_QPA_EGLFS_DEPTH" ); |
90 | if (depthString.toInt() == 16) { |
91 | platformFormat.setDepthBufferSize(16); |
92 | platformFormat.setRedBufferSize(5); |
93 | platformFormat.setGreenBufferSize(6); |
94 | platformFormat.setBlueBufferSize(5); |
95 | m_depth = 16; |
96 | m_format = QImage::Format_RGB16; |
97 | } else { |
98 | platformFormat.setDepthBufferSize(24); |
99 | platformFormat.setStencilBufferSize(8); |
100 | platformFormat.setRedBufferSize(8); |
101 | platformFormat.setGreenBufferSize(8); |
102 | platformFormat.setBlueBufferSize(8); |
103 | m_depth = 32; |
104 | m_format = QImage::Format_RGB32; |
105 | } |
106 | |
107 | if (!qEnvironmentVariableIsEmpty(varName: "QT_QPA_EGLFS_MULTISAMPLE" )) |
108 | platformFormat.setSamples(4); |
109 | |
110 | EGLConfig config = q_configFromGLFormat(display: m_dpy, format: platformFormat); |
111 | |
112 | EGLNativeWindowType eglWindow = 0; |
113 | #ifdef Q_OPENKODE |
114 | if (Q_UNLIKELY(kdInitializeNV() == KD_ENOTINITIALIZED)) |
115 | qFatal("Did not manage to initialize openkode" ); |
116 | |
117 | KDWindow *window = kdCreateWindow(m_dpy,config,0); |
118 | |
119 | kdRealizeWindow(window,&eglWindow); |
120 | #endif |
121 | |
122 | #ifdef QEGL_EXTRA_DEBUG |
123 | q_printEglConfig(m_dpy, config); |
124 | #endif |
125 | |
126 | m_surface = eglCreateWindowSurface(dpy: m_dpy, config, win: eglWindow, attrib_list: nullptr); |
127 | if (Q_UNLIKELY(m_surface == EGL_NO_SURFACE)) { |
128 | qWarning(msg: "Could not create the egl surface: error = 0x%x\n" , eglGetError()); |
129 | eglTerminate(dpy: m_dpy); |
130 | qFatal(msg: "EGL error" ); |
131 | } |
132 | // qWarning("Created surface %dx%d\n", w, h); |
133 | |
134 | #ifndef QT_NO_OPENGL |
135 | QEGLPlatformContext *platformContext = new QMinimalEglContext(platformFormat, nullptr, m_dpy); |
136 | m_platformContext = platformContext; |
137 | #endif |
138 | EGLint w,h; // screen size detection |
139 | eglQuerySurface(dpy: m_dpy, surface: m_surface, EGL_WIDTH, value: &w); |
140 | eglQuerySurface(dpy: m_dpy, surface: m_surface, EGL_HEIGHT, value: &h); |
141 | |
142 | m_geometry = QRect(0,0,w,h); |
143 | |
144 | } |
145 | |
146 | QRect QMinimalEglScreen::geometry() const |
147 | { |
148 | if (m_geometry.isNull()) { |
149 | createAndSetPlatformContext(); |
150 | } |
151 | return m_geometry; |
152 | } |
153 | |
154 | int QMinimalEglScreen::depth() const |
155 | { |
156 | return m_depth; |
157 | } |
158 | |
159 | QImage::Format QMinimalEglScreen::format() const |
160 | { |
161 | if (m_format == QImage::Format_Invalid) |
162 | createAndSetPlatformContext(); |
163 | return m_format; |
164 | } |
165 | #ifndef QT_NO_OPENGL |
166 | QPlatformOpenGLContext *QMinimalEglScreen::platformContext() const |
167 | { |
168 | if (!m_platformContext) { |
169 | QMinimalEglScreen *that = const_cast<QMinimalEglScreen *>(this); |
170 | that->createAndSetPlatformContext(); |
171 | } |
172 | return m_platformContext; |
173 | } |
174 | #endif |
175 | QT_END_NAMESPACE |
176 | |