| 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 "qeglplatformcontext_p.h" |
| 41 | #include "qeglconvenience_p.h" |
| 42 | #include "qeglpbuffer_p.h" |
| 43 | #include <qpa/qplatformwindow.h> |
| 44 | #include <QOpenGLContext> |
| 45 | #include <QtPlatformHeaders/QEGLNativeContext> |
| 46 | #include <QDebug> |
| 47 | |
| 48 | #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) |
| 49 | #include <QtCore/private/qjnihelpers_p.h> |
| 50 | #endif |
| 51 | #ifndef Q_OS_WIN |
| 52 | #include <dlfcn.h> |
| 53 | #endif |
| 54 | |
| 55 | QT_BEGIN_NAMESPACE |
| 56 | |
| 57 | /*! |
| 58 | \class QEGLPlatformContext |
| 59 | \brief An EGL context implementation. |
| 60 | \since 5.2 |
| 61 | \internal |
| 62 | \ingroup qpa |
| 63 | |
| 64 | Implement QPlatformOpenGLContext using EGL. To use it in platform |
| 65 | plugins a subclass must be created since |
| 66 | eglSurfaceForPlatformSurface() has to be reimplemented. This |
| 67 | function is used for mapping platform surfaces (windows) to EGL |
| 68 | surfaces and is necessary since different platform plugins may |
| 69 | have different ways of handling native windows (for example, a |
| 70 | plugin may choose not to back every platform window by a real EGL |
| 71 | surface). Other than that, no further customization is necessary. |
| 72 | */ |
| 73 | |
| 74 | // Constants from EGL_KHR_create_context |
| 75 | #ifndef EGL_CONTEXT_MINOR_VERSION_KHR |
| 76 | #define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB |
| 77 | #endif |
| 78 | #ifndef EGL_CONTEXT_FLAGS_KHR |
| 79 | #define EGL_CONTEXT_FLAGS_KHR 0x30FC |
| 80 | #endif |
| 81 | #ifndef EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR |
| 82 | #define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD |
| 83 | #endif |
| 84 | #ifndef EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
| 85 | #define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 |
| 86 | #endif |
| 87 | #ifndef EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR |
| 88 | #define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 |
| 89 | #endif |
| 90 | #ifndef EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR |
| 91 | #define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 |
| 92 | #endif |
| 93 | #ifndef EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR |
| 94 | #define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 |
| 95 | #endif |
| 96 | |
| 97 | // Constants for OpenGL which are not available in the ES headers. |
| 98 | #ifndef GL_CONTEXT_FLAGS |
| 99 | #define GL_CONTEXT_FLAGS 0x821E |
| 100 | #endif |
| 101 | #ifndef GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT |
| 102 | #define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 |
| 103 | #endif |
| 104 | #ifndef GL_CONTEXT_FLAG_DEBUG_BIT |
| 105 | #define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 |
| 106 | #endif |
| 107 | #ifndef GL_CONTEXT_PROFILE_MASK |
| 108 | #define GL_CONTEXT_PROFILE_MASK 0x9126 |
| 109 | #endif |
| 110 | #ifndef GL_CONTEXT_CORE_PROFILE_BIT |
| 111 | #define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 |
| 112 | #endif |
| 113 | #ifndef GL_CONTEXT_COMPATIBILITY_PROFILE_BIT |
| 114 | #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 |
| 115 | #endif |
| 116 | |
| 117 | QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, |
| 118 | EGLConfig *config, const QVariant &nativeHandle, Flags flags) |
| 119 | : m_eglDisplay(display) |
| 120 | , m_swapInterval(-1) |
| 121 | , m_swapIntervalEnvChecked(false) |
| 122 | , m_swapIntervalFromEnv(-1) |
| 123 | , m_flags(flags) |
| 124 | { |
| 125 | if (nativeHandle.isNull()) { |
| 126 | m_eglConfig = config ? *config : q_configFromGLFormat(display, format); |
| 127 | m_ownsContext = true; |
| 128 | init(format, share); |
| 129 | } else { |
| 130 | m_ownsContext = false; |
| 131 | adopt(nativeHandle, share); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share) |
| 136 | { |
| 137 | m_format = q_glFormatFromConfig(display: m_eglDisplay, config: m_eglConfig, referenceFormat: format); |
| 138 | // m_format now has the renderableType() resolved (it cannot be Default anymore) |
| 139 | // but does not yet contain version, profile, options. |
| 140 | m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : nullptr; |
| 141 | |
| 142 | QVector<EGLint> contextAttrs; |
| 143 | contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); |
| 144 | contextAttrs.append(t: format.majorVersion()); |
| 145 | const bool hasKHRCreateContext = q_hasEglExtension(display: m_eglDisplay, extensionName: "EGL_KHR_create_context" ); |
| 146 | if (hasKHRCreateContext) { |
| 147 | contextAttrs.append(EGL_CONTEXT_MINOR_VERSION_KHR); |
| 148 | contextAttrs.append(t: format.minorVersion()); |
| 149 | int flags = 0; |
| 150 | // The debug bit is supported both for OpenGL and OpenGL ES. |
| 151 | if (format.testOption(option: QSurfaceFormat::DebugContext)) |
| 152 | flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; |
| 153 | // The fwdcompat bit is only for OpenGL 3.0+. |
| 154 | if (m_format.renderableType() == QSurfaceFormat::OpenGL |
| 155 | && format.majorVersion() >= 3 |
| 156 | && !format.testOption(option: QSurfaceFormat::DeprecatedFunctions)) |
| 157 | flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; |
| 158 | if (flags) { |
| 159 | contextAttrs.append(EGL_CONTEXT_FLAGS_KHR); |
| 160 | contextAttrs.append(t: flags); |
| 161 | } |
| 162 | // Profiles are OpenGL only and mandatory in 3.2+. The value is silently ignored for < 3.2. |
| 163 | if (m_format.renderableType() == QSurfaceFormat::OpenGL) { |
| 164 | contextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR); |
| 165 | contextAttrs.append(t: format.profile() == QSurfaceFormat::CoreProfile |
| 166 | ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR |
| 167 | : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR); |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | // Special Options for OpenVG surfaces |
| 172 | if (m_format.renderableType() == QSurfaceFormat::OpenVG) { |
| 173 | contextAttrs.append(EGL_ALPHA_MASK_SIZE); |
| 174 | contextAttrs.append(t: 8); |
| 175 | } |
| 176 | |
| 177 | contextAttrs.append(EGL_NONE); |
| 178 | m_contextAttrs = contextAttrs; |
| 179 | |
| 180 | switch (m_format.renderableType()) { |
| 181 | case QSurfaceFormat::OpenVG: |
| 182 | m_api = EGL_OPENVG_API; |
| 183 | break; |
| 184 | #ifdef EGL_VERSION_1_4 |
| 185 | case QSurfaceFormat::OpenGL: |
| 186 | m_api = EGL_OPENGL_API; |
| 187 | break; |
| 188 | #endif // EGL_VERSION_1_4 |
| 189 | default: |
| 190 | m_api = EGL_OPENGL_ES_API; |
| 191 | break; |
| 192 | } |
| 193 | |
| 194 | eglBindAPI(api: m_api); |
| 195 | m_eglContext = eglCreateContext(dpy: m_eglDisplay, config: m_eglConfig, share_context: m_shareContext, attrib_list: contextAttrs.constData()); |
| 196 | if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) { |
| 197 | m_shareContext = nullptr; |
| 198 | m_eglContext = eglCreateContext(dpy: m_eglDisplay, config: m_eglConfig, share_context: nullptr, attrib_list: contextAttrs.constData()); |
| 199 | } |
| 200 | |
| 201 | if (m_eglContext == EGL_NO_CONTEXT) { |
| 202 | qWarning(msg: "QEGLPlatformContext: Failed to create context: %x" , eglGetError()); |
| 203 | return; |
| 204 | } |
| 205 | |
| 206 | static const bool printConfig = qEnvironmentVariableIntValue(varName: "QT_QPA_EGLFS_DEBUG" ); |
| 207 | if (printConfig) { |
| 208 | qDebug() << "Created context for format" << format << "with config:" ; |
| 209 | q_printEglConfig(display: m_eglDisplay, config: m_eglConfig); |
| 210 | } |
| 211 | |
| 212 | // Cannot just call updateFormatFromGL() since it relies on virtuals. Defer it to initialize(). |
| 213 | } |
| 214 | |
| 215 | void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLContext *share) |
| 216 | { |
| 217 | if (!nativeHandle.canConvert<QEGLNativeContext>()) { |
| 218 | qWarning(msg: "QEGLPlatformContext: Requires a QEGLNativeContext" ); |
| 219 | return; |
| 220 | } |
| 221 | QEGLNativeContext handle = qvariant_cast<QEGLNativeContext>(v: nativeHandle); |
| 222 | EGLContext context = handle.context(); |
| 223 | if (!context) { |
| 224 | qWarning(msg: "QEGLPlatformContext: No EGLContext given" ); |
| 225 | return; |
| 226 | } |
| 227 | |
| 228 | // A context belonging to a given EGLDisplay cannot be used with another one. |
| 229 | if (handle.display() != m_eglDisplay) { |
| 230 | qWarning(msg: "QEGLPlatformContext: Cannot adopt context from different display" ); |
| 231 | return; |
| 232 | } |
| 233 | |
| 234 | // Figure out the EGLConfig. |
| 235 | EGLint value = 0; |
| 236 | eglQueryContext(dpy: m_eglDisplay, ctx: context, EGL_CONFIG_ID, value: &value); |
| 237 | EGLint n = 0; |
| 238 | EGLConfig cfg; |
| 239 | const EGLint attribs[] = { EGL_CONFIG_ID, value, EGL_NONE }; |
| 240 | if (eglChooseConfig(dpy: m_eglDisplay, attrib_list: attribs, configs: &cfg, config_size: 1, num_config: &n) && n == 1) { |
| 241 | m_eglConfig = cfg; |
| 242 | m_format = q_glFormatFromConfig(display: m_eglDisplay, config: m_eglConfig); |
| 243 | } else { |
| 244 | qWarning(msg: "QEGLPlatformContext: Failed to get framebuffer configuration for context" ); |
| 245 | } |
| 246 | |
| 247 | // Fetch client API type. |
| 248 | value = 0; |
| 249 | eglQueryContext(dpy: m_eglDisplay, ctx: context, EGL_CONTEXT_CLIENT_TYPE, value: &value); |
| 250 | if (value == EGL_OPENGL_API || value == EGL_OPENGL_ES_API) { |
| 251 | // if EGL config supports both OpenGL and OpenGL ES render type, |
| 252 | // q_glFormatFromConfig() with the default "referenceFormat" parameter |
| 253 | // will always figure it out as OpenGL render type. |
| 254 | // We can override it to match user's real render type. |
| 255 | if (value == EGL_OPENGL_ES_API) |
| 256 | m_format.setRenderableType(QSurfaceFormat::OpenGLES); |
| 257 | m_api = value; |
| 258 | eglBindAPI(api: m_api); |
| 259 | } else { |
| 260 | qWarning(msg: "QEGLPlatformContext: Failed to get client API type" ); |
| 261 | m_api = EGL_OPENGL_ES_API; |
| 262 | } |
| 263 | |
| 264 | m_eglContext = context; |
| 265 | m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : nullptr; |
| 266 | updateFormatFromGL(); |
| 267 | } |
| 268 | |
| 269 | void QEGLPlatformContext::initialize() |
| 270 | { |
| 271 | if (m_eglContext != EGL_NO_CONTEXT) |
| 272 | updateFormatFromGL(); |
| 273 | } |
| 274 | |
| 275 | // Base implementation for pbuffers. Subclasses will handle the specialized cases for |
| 276 | // platforms without pbuffers. |
| 277 | EGLSurface QEGLPlatformContext::createTemporaryOffscreenSurface() |
| 278 | { |
| 279 | // Make the context current to ensure the GL version query works. This needs a surface too. |
| 280 | const EGLint pbufferAttributes[] = { |
| 281 | EGL_WIDTH, 1, |
| 282 | EGL_HEIGHT, 1, |
| 283 | EGL_LARGEST_PBUFFER, EGL_FALSE, |
| 284 | EGL_NONE |
| 285 | }; |
| 286 | |
| 287 | // Cannot just pass m_eglConfig because it may not be suitable for pbuffers. Instead, |
| 288 | // do what QEGLPbuffer would do: request a config with the same attributes but with |
| 289 | // PBUFFER_BIT set. |
| 290 | EGLConfig config = q_configFromGLFormat(display: m_eglDisplay, format: m_format, highestPixelFormat: false, EGL_PBUFFER_BIT); |
| 291 | |
| 292 | return eglCreatePbufferSurface(dpy: m_eglDisplay, config, attrib_list: pbufferAttributes); |
| 293 | } |
| 294 | |
| 295 | void QEGLPlatformContext::destroyTemporaryOffscreenSurface(EGLSurface surface) |
| 296 | { |
| 297 | eglDestroySurface(dpy: m_eglDisplay, surface); |
| 298 | } |
| 299 | |
| 300 | void QEGLPlatformContext::runGLChecks() |
| 301 | { |
| 302 | // Nothing to do here, subclasses may override in order to perform OpenGL |
| 303 | // queries needing a context. |
| 304 | } |
| 305 | |
| 306 | void QEGLPlatformContext::updateFormatFromGL() |
| 307 | { |
| 308 | #ifndef QT_NO_OPENGL |
| 309 | // Have to save & restore to prevent QOpenGLContext::currentContext() from becoming |
| 310 | // inconsistent after QOpenGLContext::create(). |
| 311 | EGLDisplay prevDisplay = eglGetCurrentDisplay(); |
| 312 | if (prevDisplay == EGL_NO_DISPLAY) // when no context is current |
| 313 | prevDisplay = m_eglDisplay; |
| 314 | EGLContext prevContext = eglGetCurrentContext(); |
| 315 | EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW); |
| 316 | EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ); |
| 317 | |
| 318 | // Rely on the surfaceless extension, if available. This is beneficial since we can |
| 319 | // avoid creating an extra pbuffer surface which is apparently troublesome with some |
| 320 | // drivers (Mesa) when certain attributes are present (multisampling). |
| 321 | EGLSurface tempSurface = EGL_NO_SURFACE; |
| 322 | EGLContext tempContext = EGL_NO_CONTEXT; |
| 323 | if (m_flags.testFlag(flag: NoSurfaceless) || !q_hasEglExtension(display: m_eglDisplay, extensionName: "EGL_KHR_surfaceless_context" )) |
| 324 | tempSurface = createTemporaryOffscreenSurface(); |
| 325 | |
| 326 | EGLBoolean ok = eglMakeCurrent(dpy: m_eglDisplay, draw: tempSurface, read: tempSurface, ctx: m_eglContext); |
| 327 | if (!ok) { |
| 328 | EGLConfig config = q_configFromGLFormat(display: m_eglDisplay, format: m_format, highestPixelFormat: false, EGL_PBUFFER_BIT); |
| 329 | tempContext = eglCreateContext(dpy: m_eglDisplay, config, share_context: nullptr, attrib_list: m_contextAttrs.constData()); |
| 330 | if (tempContext != EGL_NO_CONTEXT) |
| 331 | ok = eglMakeCurrent(dpy: m_eglDisplay, draw: tempSurface, read: tempSurface, ctx: tempContext); |
| 332 | } |
| 333 | if (ok) { |
| 334 | if (m_format.renderableType() == QSurfaceFormat::OpenGL |
| 335 | || m_format.renderableType() == QSurfaceFormat::OpenGLES) { |
| 336 | const GLubyte *s = glGetString(GL_VERSION); |
| 337 | if (s) { |
| 338 | QByteArray version = QByteArray(reinterpret_cast<const char *>(s)); |
| 339 | int major, minor; |
| 340 | if (QPlatformOpenGLContext::parseOpenGLVersion(versionString: version, major, minor)) { |
| 341 | m_format.setMajorVersion(major); |
| 342 | m_format.setMinorVersion(minor); |
| 343 | } |
| 344 | } |
| 345 | m_format.setProfile(QSurfaceFormat::NoProfile); |
| 346 | m_format.setOptions(QSurfaceFormat::FormatOptions()); |
| 347 | if (m_format.renderableType() == QSurfaceFormat::OpenGL) { |
| 348 | // Check profile and options. |
| 349 | if (m_format.majorVersion() < 3) { |
| 350 | m_format.setOption(option: QSurfaceFormat::DeprecatedFunctions); |
| 351 | } else { |
| 352 | GLint value = 0; |
| 353 | glGetIntegerv(GL_CONTEXT_FLAGS, params: &value); |
| 354 | if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)) |
| 355 | m_format.setOption(option: QSurfaceFormat::DeprecatedFunctions); |
| 356 | if (value & GL_CONTEXT_FLAG_DEBUG_BIT) |
| 357 | m_format.setOption(option: QSurfaceFormat::DebugContext); |
| 358 | if (m_format.version() >= qMakePair(x: 3, y: 2)) { |
| 359 | value = 0; |
| 360 | glGetIntegerv(GL_CONTEXT_PROFILE_MASK, params: &value); |
| 361 | if (value & GL_CONTEXT_CORE_PROFILE_BIT) |
| 362 | m_format.setProfile(QSurfaceFormat::CoreProfile); |
| 363 | else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) |
| 364 | m_format.setProfile(QSurfaceFormat::CompatibilityProfile); |
| 365 | } |
| 366 | } |
| 367 | } |
| 368 | } |
| 369 | runGLChecks(); |
| 370 | eglMakeCurrent(dpy: prevDisplay, draw: prevSurfaceDraw, read: prevSurfaceRead, ctx: prevContext); |
| 371 | } else { |
| 372 | qWarning(msg: "QEGLPlatformContext: Failed to make temporary surface current, format not updated (%x)" , eglGetError()); |
| 373 | } |
| 374 | if (tempSurface != EGL_NO_SURFACE) |
| 375 | destroyTemporaryOffscreenSurface(surface: tempSurface); |
| 376 | if (tempContext != EGL_NO_CONTEXT) |
| 377 | eglDestroyContext(dpy: m_eglDisplay, ctx: tempContext); |
| 378 | #endif // QT_NO_OPENGL |
| 379 | } |
| 380 | |
| 381 | bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) |
| 382 | { |
| 383 | Q_ASSERT(surface->surface()->supportsOpenGL()); |
| 384 | |
| 385 | eglBindAPI(api: m_api); |
| 386 | |
| 387 | EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface); |
| 388 | |
| 389 | // shortcut: on some GPUs, eglMakeCurrent is not a cheap operation |
| 390 | if (eglGetCurrentContext() == m_eglContext && |
| 391 | eglGetCurrentDisplay() == m_eglDisplay && |
| 392 | eglGetCurrentSurface(EGL_READ) == eglSurface && |
| 393 | eglGetCurrentSurface(EGL_DRAW) == eglSurface) { |
| 394 | return true; |
| 395 | } |
| 396 | |
| 397 | const bool ok = eglMakeCurrent(dpy: m_eglDisplay, draw: eglSurface, read: eglSurface, ctx: m_eglContext); |
| 398 | if (ok) { |
| 399 | if (!m_swapIntervalEnvChecked) { |
| 400 | m_swapIntervalEnvChecked = true; |
| 401 | if (qEnvironmentVariableIsSet(varName: "QT_QPA_EGLFS_SWAPINTERVAL" )) { |
| 402 | QByteArray swapIntervalString = qgetenv(varName: "QT_QPA_EGLFS_SWAPINTERVAL" ); |
| 403 | bool intervalOk; |
| 404 | const int swapInterval = swapIntervalString.toInt(ok: &intervalOk); |
| 405 | if (intervalOk) |
| 406 | m_swapIntervalFromEnv = swapInterval; |
| 407 | } |
| 408 | } |
| 409 | const int requestedSwapInterval = m_swapIntervalFromEnv >= 0 |
| 410 | ? m_swapIntervalFromEnv |
| 411 | : surface->format().swapInterval(); |
| 412 | if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) { |
| 413 | m_swapInterval = requestedSwapInterval; |
| 414 | if (eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context |
| 415 | eglSwapInterval(dpy: eglDisplay(), interval: m_swapInterval); |
| 416 | } |
| 417 | } else { |
| 418 | qWarning(msg: "QEGLPlatformContext: eglMakeCurrent failed: %x" , eglGetError()); |
| 419 | } |
| 420 | |
| 421 | return ok; |
| 422 | } |
| 423 | |
| 424 | QEGLPlatformContext::~QEGLPlatformContext() |
| 425 | { |
| 426 | if (m_ownsContext && m_eglContext != EGL_NO_CONTEXT) |
| 427 | eglDestroyContext(dpy: m_eglDisplay, ctx: m_eglContext); |
| 428 | |
| 429 | m_eglContext = EGL_NO_CONTEXT; |
| 430 | } |
| 431 | |
| 432 | void QEGLPlatformContext::doneCurrent() |
| 433 | { |
| 434 | eglBindAPI(api: m_api); |
| 435 | bool ok = eglMakeCurrent(dpy: m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
| 436 | if (!ok) |
| 437 | qWarning(msg: "QEGLPlatformContext: eglMakeCurrent failed: %x" , eglGetError()); |
| 438 | } |
| 439 | |
| 440 | void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface) |
| 441 | { |
| 442 | eglBindAPI(api: m_api); |
| 443 | EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface); |
| 444 | if (eglSurface != EGL_NO_SURFACE) { // skip if using surfaceless context |
| 445 | bool ok = eglSwapBuffers(dpy: m_eglDisplay, surface: eglSurface); |
| 446 | if (!ok) |
| 447 | qWarning(msg: "QEGLPlatformContext: eglSwapBuffers failed: %x" , eglGetError()); |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | QFunctionPointer QEGLPlatformContext::getProcAddress(const char *procName) |
| 452 | { |
| 453 | eglBindAPI(api: m_api); |
| 454 | QFunctionPointer proc = (QFunctionPointer) eglGetProcAddress(procname: procName); |
| 455 | #if !defined(Q_OS_WIN) && !defined(Q_OS_INTEGRITY) |
| 456 | if (!proc) |
| 457 | proc = (QFunctionPointer) dlsym(RTLD_DEFAULT, name: procName); |
| 458 | #elif !defined(QT_OPENGL_DYNAMIC) |
| 459 | // On systems without KHR_get_all_proc_addresses and without |
| 460 | // dynamic linking there still has to be a way to access the |
| 461 | // standard GLES functions. QOpenGL(Extra)Functions never makes |
| 462 | // direct GL API calls since Qt 5.7, so all such workarounds are |
| 463 | // expected to be handled in the platform plugin. |
| 464 | if (!proc) { |
| 465 | static struct StdFunc { |
| 466 | const char *name; |
| 467 | QFunctionPointer func; |
| 468 | } standardFuncs[] = { |
| 469 | #ifdef QT_OPENGL_ES_2 |
| 470 | { "glBindTexture" , (QFunctionPointer) ::glBindTexture }, |
| 471 | { "glBlendFunc" , (QFunctionPointer) ::glBlendFunc }, |
| 472 | { "glClear" , (QFunctionPointer) ::glClear }, |
| 473 | { "glClearColor" , (QFunctionPointer) ::glClearColor }, |
| 474 | { "glClearStencil" , (QFunctionPointer) ::glClearStencil }, |
| 475 | { "glColorMask" , (QFunctionPointer) ::glColorMask }, |
| 476 | { "glCopyTexImage2D" , (QFunctionPointer) ::glCopyTexImage2D }, |
| 477 | { "glCopyTexSubImage2D" , (QFunctionPointer) ::glCopyTexSubImage2D }, |
| 478 | { "glCullFace" , (QFunctionPointer) ::glCullFace }, |
| 479 | { "glDeleteTextures" , (QFunctionPointer) ::glDeleteTextures }, |
| 480 | { "glDepthFunc" , (QFunctionPointer) ::glDepthFunc }, |
| 481 | { "glDepthMask" , (QFunctionPointer) ::glDepthMask }, |
| 482 | { "glDisable" , (QFunctionPointer) ::glDisable }, |
| 483 | { "glDrawArrays" , (QFunctionPointer) ::glDrawArrays }, |
| 484 | { "glDrawElements" , (QFunctionPointer) ::glDrawElements }, |
| 485 | { "glEnable" , (QFunctionPointer) ::glEnable }, |
| 486 | { "glFinish" , (QFunctionPointer) ::glFinish }, |
| 487 | { "glFlush" , (QFunctionPointer) ::glFlush }, |
| 488 | { "glFrontFace" , (QFunctionPointer) ::glFrontFace }, |
| 489 | { "glGenTextures" , (QFunctionPointer) ::glGenTextures }, |
| 490 | { "glGetBooleanv" , (QFunctionPointer) ::glGetBooleanv }, |
| 491 | { "glGetError" , (QFunctionPointer) ::glGetError }, |
| 492 | { "glGetFloatv" , (QFunctionPointer) ::glGetFloatv }, |
| 493 | { "glGetIntegerv" , (QFunctionPointer) ::glGetIntegerv }, |
| 494 | { "glGetString" , (QFunctionPointer) ::glGetString }, |
| 495 | { "glGetTexParameterfv" , (QFunctionPointer) ::glGetTexParameterfv }, |
| 496 | { "glGetTexParameteriv" , (QFunctionPointer) ::glGetTexParameteriv }, |
| 497 | { "glHint" , (QFunctionPointer) ::glHint }, |
| 498 | { "glIsEnabled" , (QFunctionPointer) ::glIsEnabled }, |
| 499 | { "glIsTexture" , (QFunctionPointer) ::glIsTexture }, |
| 500 | { "glLineWidth" , (QFunctionPointer) ::glLineWidth }, |
| 501 | { "glPixelStorei" , (QFunctionPointer) ::glPixelStorei }, |
| 502 | { "glPolygonOffset" , (QFunctionPointer) ::glPolygonOffset }, |
| 503 | { "glReadPixels" , (QFunctionPointer) ::glReadPixels }, |
| 504 | { "glScissor" , (QFunctionPointer) ::glScissor }, |
| 505 | { "glStencilFunc" , (QFunctionPointer) ::glStencilFunc }, |
| 506 | { "glStencilMask" , (QFunctionPointer) ::glStencilMask }, |
| 507 | { "glStencilOp" , (QFunctionPointer) ::glStencilOp }, |
| 508 | { "glTexImage2D" , (QFunctionPointer) ::glTexImage2D }, |
| 509 | { "glTexParameterf" , (QFunctionPointer) ::glTexParameterf }, |
| 510 | { "glTexParameterfv" , (QFunctionPointer) ::glTexParameterfv }, |
| 511 | { "glTexParameteri" , (QFunctionPointer) ::glTexParameteri }, |
| 512 | { "glTexParameteriv" , (QFunctionPointer) ::glTexParameteriv }, |
| 513 | { "glTexSubImage2D" , (QFunctionPointer) ::glTexSubImage2D }, |
| 514 | { "glViewport" , (QFunctionPointer) ::glViewport }, |
| 515 | |
| 516 | { "glActiveTexture" , (QFunctionPointer) ::glActiveTexture }, |
| 517 | { "glAttachShader" , (QFunctionPointer) ::glAttachShader }, |
| 518 | { "glBindAttribLocation" , (QFunctionPointer) ::glBindAttribLocation }, |
| 519 | { "glBindBuffer" , (QFunctionPointer) ::glBindBuffer }, |
| 520 | { "glBindFramebuffer" , (QFunctionPointer) ::glBindFramebuffer }, |
| 521 | { "glBindRenderbuffer" , (QFunctionPointer) ::glBindRenderbuffer }, |
| 522 | { "glBlendColor" , (QFunctionPointer) ::glBlendColor }, |
| 523 | { "glBlendEquation" , (QFunctionPointer) ::glBlendEquation }, |
| 524 | { "glBlendEquationSeparate" , (QFunctionPointer) ::glBlendEquationSeparate }, |
| 525 | { "glBlendFuncSeparate" , (QFunctionPointer) ::glBlendFuncSeparate }, |
| 526 | { "glBufferData" , (QFunctionPointer) ::glBufferData }, |
| 527 | { "glBufferSubData" , (QFunctionPointer) ::glBufferSubData }, |
| 528 | { "glCheckFramebufferStatus" , (QFunctionPointer) ::glCheckFramebufferStatus }, |
| 529 | { "glCompileShader" , (QFunctionPointer) ::glCompileShader }, |
| 530 | { "glCompressedTexImage2D" , (QFunctionPointer) ::glCompressedTexImage2D }, |
| 531 | { "glCompressedTexSubImage2D" , (QFunctionPointer) ::glCompressedTexSubImage2D }, |
| 532 | { "glCreateProgram" , (QFunctionPointer) ::glCreateProgram }, |
| 533 | { "glCreateShader" , (QFunctionPointer) ::glCreateShader }, |
| 534 | { "glDeleteBuffers" , (QFunctionPointer) ::glDeleteBuffers }, |
| 535 | { "glDeleteFramebuffers" , (QFunctionPointer) ::glDeleteFramebuffers }, |
| 536 | { "glDeleteProgram" , (QFunctionPointer) ::glDeleteProgram }, |
| 537 | { "glDeleteRenderbuffers" , (QFunctionPointer) ::glDeleteRenderbuffers }, |
| 538 | { "glDeleteShader" , (QFunctionPointer) ::glDeleteShader }, |
| 539 | { "glDetachShader" , (QFunctionPointer) ::glDetachShader }, |
| 540 | { "glDisableVertexAttribArray" , (QFunctionPointer) ::glDisableVertexAttribArray }, |
| 541 | { "glEnableVertexAttribArray" , (QFunctionPointer) ::glEnableVertexAttribArray }, |
| 542 | { "glFramebufferRenderbuffer" , (QFunctionPointer) ::glFramebufferRenderbuffer }, |
| 543 | { "glFramebufferTexture2D" , (QFunctionPointer) ::glFramebufferTexture2D }, |
| 544 | { "glGenBuffers" , (QFunctionPointer) ::glGenBuffers }, |
| 545 | { "glGenerateMipmap" , (QFunctionPointer) ::glGenerateMipmap }, |
| 546 | { "glGenFramebuffers" , (QFunctionPointer) ::glGenFramebuffers }, |
| 547 | { "glGenRenderbuffers" , (QFunctionPointer) ::glGenRenderbuffers }, |
| 548 | { "glGetActiveAttrib" , (QFunctionPointer) ::glGetActiveAttrib }, |
| 549 | { "glGetActiveUniform" , (QFunctionPointer) ::glGetActiveUniform }, |
| 550 | { "glGetAttachedShaders" , (QFunctionPointer) ::glGetAttachedShaders }, |
| 551 | { "glGetAttribLocation" , (QFunctionPointer) ::glGetAttribLocation }, |
| 552 | { "glGetBufferParameteriv" , (QFunctionPointer) ::glGetBufferParameteriv }, |
| 553 | { "glGetFramebufferAttachmentParameteriv" , (QFunctionPointer) ::glGetFramebufferAttachmentParameteriv }, |
| 554 | { "glGetProgramiv" , (QFunctionPointer) ::glGetProgramiv }, |
| 555 | { "glGetProgramInfoLog" , (QFunctionPointer) ::glGetProgramInfoLog }, |
| 556 | { "glGetRenderbufferParameteriv" , (QFunctionPointer) ::glGetRenderbufferParameteriv }, |
| 557 | { "glGetShaderiv" , (QFunctionPointer) ::glGetShaderiv }, |
| 558 | { "glGetShaderInfoLog" , (QFunctionPointer) ::glGetShaderInfoLog }, |
| 559 | { "glGetShaderPrecisionFormat" , (QFunctionPointer) ::glGetShaderPrecisionFormat }, |
| 560 | { "glGetShaderSource" , (QFunctionPointer) ::glGetShaderSource }, |
| 561 | { "glGetUniformfv" , (QFunctionPointer) ::glGetUniformfv }, |
| 562 | { "glGetUniformiv" , (QFunctionPointer) ::glGetUniformiv }, |
| 563 | { "glGetUniformLocation" , (QFunctionPointer) ::glGetUniformLocation }, |
| 564 | { "glGetVertexAttribfv" , (QFunctionPointer) ::glGetVertexAttribfv }, |
| 565 | { "glGetVertexAttribiv" , (QFunctionPointer) ::glGetVertexAttribiv }, |
| 566 | { "glGetVertexAttribPointerv" , (QFunctionPointer) ::glGetVertexAttribPointerv }, |
| 567 | { "glIsBuffer" , (QFunctionPointer) ::glIsBuffer }, |
| 568 | { "glIsFramebuffer" , (QFunctionPointer) ::glIsFramebuffer }, |
| 569 | { "glIsProgram" , (QFunctionPointer) ::glIsProgram }, |
| 570 | { "glIsRenderbuffer" , (QFunctionPointer) ::glIsRenderbuffer }, |
| 571 | { "glIsShader" , (QFunctionPointer) ::glIsShader }, |
| 572 | { "glLinkProgram" , (QFunctionPointer) ::glLinkProgram }, |
| 573 | { "glReleaseShaderCompiler" , (QFunctionPointer) ::glReleaseShaderCompiler }, |
| 574 | { "glRenderbufferStorage" , (QFunctionPointer) ::glRenderbufferStorage }, |
| 575 | { "glSampleCoverage" , (QFunctionPointer) ::glSampleCoverage }, |
| 576 | { "glShaderBinary" , (QFunctionPointer) ::glShaderBinary }, |
| 577 | { "glShaderSource" , (QFunctionPointer) ::glShaderSource }, |
| 578 | { "glStencilFuncSeparate" , (QFunctionPointer) ::glStencilFuncSeparate }, |
| 579 | { "glStencilMaskSeparate" , (QFunctionPointer) ::glStencilMaskSeparate }, |
| 580 | { "glStencilOpSeparate" , (QFunctionPointer) ::glStencilOpSeparate }, |
| 581 | { "glUniform1f" , (QFunctionPointer) ::glUniform1f }, |
| 582 | { "glUniform1fv" , (QFunctionPointer) ::glUniform1fv }, |
| 583 | { "glUniform1i" , (QFunctionPointer) ::glUniform1i }, |
| 584 | { "glUniform1iv" , (QFunctionPointer) ::glUniform1iv }, |
| 585 | { "glUniform2f" , (QFunctionPointer) ::glUniform2f }, |
| 586 | { "glUniform2fv" , (QFunctionPointer) ::glUniform2fv }, |
| 587 | { "glUniform2i" , (QFunctionPointer) ::glUniform2i }, |
| 588 | { "glUniform2iv" , (QFunctionPointer) ::glUniform2iv }, |
| 589 | { "glUniform3f" , (QFunctionPointer) ::glUniform3f }, |
| 590 | { "glUniform3fv" , (QFunctionPointer) ::glUniform3fv }, |
| 591 | { "glUniform3i" , (QFunctionPointer) ::glUniform3i }, |
| 592 | { "glUniform3iv" , (QFunctionPointer) ::glUniform3iv }, |
| 593 | { "glUniform4f" , (QFunctionPointer) ::glUniform4f }, |
| 594 | { "glUniform4fv" , (QFunctionPointer) ::glUniform4fv }, |
| 595 | { "glUniform4i" , (QFunctionPointer) ::glUniform4i }, |
| 596 | { "glUniform4iv" , (QFunctionPointer) ::glUniform4iv }, |
| 597 | { "glUniformMatrix2fv" , (QFunctionPointer) ::glUniformMatrix2fv }, |
| 598 | { "glUniformMatrix3fv" , (QFunctionPointer) ::glUniformMatrix3fv }, |
| 599 | { "glUniformMatrix4fv" , (QFunctionPointer) ::glUniformMatrix4fv }, |
| 600 | { "glUseProgram" , (QFunctionPointer) ::glUseProgram }, |
| 601 | { "glValidateProgram" , (QFunctionPointer) ::glValidateProgram }, |
| 602 | { "glVertexAttrib1f" , (QFunctionPointer) ::glVertexAttrib1f }, |
| 603 | { "glVertexAttrib1fv" , (QFunctionPointer) ::glVertexAttrib1fv }, |
| 604 | { "glVertexAttrib2f" , (QFunctionPointer) ::glVertexAttrib2f }, |
| 605 | { "glVertexAttrib2fv" , (QFunctionPointer) ::glVertexAttrib2fv }, |
| 606 | { "glVertexAttrib3f" , (QFunctionPointer) ::glVertexAttrib3f }, |
| 607 | { "glVertexAttrib3fv" , (QFunctionPointer) ::glVertexAttrib3fv }, |
| 608 | { "glVertexAttrib4f" , (QFunctionPointer) ::glVertexAttrib4f }, |
| 609 | { "glVertexAttrib4fv" , (QFunctionPointer) ::glVertexAttrib4fv }, |
| 610 | { "glVertexAttribPointer" , (QFunctionPointer) ::glVertexAttribPointer }, |
| 611 | |
| 612 | { "glClearDepthf" , (QFunctionPointer) ::glClearDepthf }, |
| 613 | { "glDepthRangef" , (QFunctionPointer) ::glDepthRangef }, |
| 614 | #endif // QT_OPENGL_ES_2 |
| 615 | |
| 616 | #ifdef QT_OPENGL_ES_3 |
| 617 | { "glBeginQuery" , (QFunctionPointer) ::glBeginQuery }, |
| 618 | { "glBeginTransformFeedback" , (QFunctionPointer) ::glBeginTransformFeedback }, |
| 619 | { "glBindBufferBase" , (QFunctionPointer) ::glBindBufferBase }, |
| 620 | { "glBindBufferRange" , (QFunctionPointer) ::glBindBufferRange }, |
| 621 | { "glBindSampler" , (QFunctionPointer) ::glBindSampler }, |
| 622 | { "glBindTransformFeedback" , (QFunctionPointer) ::glBindTransformFeedback }, |
| 623 | { "glBindVertexArray" , (QFunctionPointer) ::glBindVertexArray }, |
| 624 | { "glBlitFramebuffer" , (QFunctionPointer) ::glBlitFramebuffer }, |
| 625 | { "glClearBufferfi" , (QFunctionPointer) ::glClearBufferfi }, |
| 626 | { "glClearBufferfv" , (QFunctionPointer) ::glClearBufferfv }, |
| 627 | { "glClearBufferiv" , (QFunctionPointer) ::glClearBufferiv }, |
| 628 | { "glClearBufferuiv" , (QFunctionPointer) ::glClearBufferuiv }, |
| 629 | { "glClientWaitSync" , (QFunctionPointer) ::glClientWaitSync }, |
| 630 | { "glCompressedTexImage3D" , (QFunctionPointer) ::glCompressedTexImage3D }, |
| 631 | { "glCompressedTexSubImage3D" , (QFunctionPointer) ::glCompressedTexSubImage3D }, |
| 632 | { "glCopyBufferSubData" , (QFunctionPointer) ::glCopyBufferSubData }, |
| 633 | { "glCopyTexSubImage3D" , (QFunctionPointer) ::glCopyTexSubImage3D }, |
| 634 | { "glDeleteQueries" , (QFunctionPointer) ::glDeleteQueries }, |
| 635 | { "glDeleteSamplers" , (QFunctionPointer) ::glDeleteSamplers }, |
| 636 | { "glDeleteSync" , (QFunctionPointer) ::glDeleteSync }, |
| 637 | { "glDeleteTransformFeedbacks" , (QFunctionPointer) ::glDeleteTransformFeedbacks }, |
| 638 | { "glDeleteVertexArrays" , (QFunctionPointer) ::glDeleteVertexArrays }, |
| 639 | { "glDrawArraysInstanced" , (QFunctionPointer) ::glDrawArraysInstanced }, |
| 640 | { "glDrawBuffers" , (QFunctionPointer) ::glDrawBuffers }, |
| 641 | { "glDrawElementsInstanced" , (QFunctionPointer) ::glDrawElementsInstanced }, |
| 642 | { "glDrawRangeElements" , (QFunctionPointer) ::glDrawRangeElements }, |
| 643 | { "glEndQuery" , (QFunctionPointer) ::glEndQuery }, |
| 644 | { "glEndTransformFeedback" , (QFunctionPointer) ::glEndTransformFeedback }, |
| 645 | { "glFenceSync" , (QFunctionPointer) ::glFenceSync }, |
| 646 | { "glFlushMappedBufferRange" , (QFunctionPointer) ::glFlushMappedBufferRange }, |
| 647 | { "glFramebufferTextureLayer" , (QFunctionPointer) ::glFramebufferTextureLayer }, |
| 648 | { "glGenQueries" , (QFunctionPointer) ::glGenQueries }, |
| 649 | { "glGenSamplers" , (QFunctionPointer) ::glGenSamplers }, |
| 650 | { "glGenTransformFeedbacks" , (QFunctionPointer) ::glGenTransformFeedbacks }, |
| 651 | { "glGenVertexArrays" , (QFunctionPointer) ::glGenVertexArrays }, |
| 652 | { "glGetActiveUniformBlockName" , (QFunctionPointer) ::glGetActiveUniformBlockName }, |
| 653 | { "glGetActiveUniformBlockiv" , (QFunctionPointer) ::glGetActiveUniformBlockiv }, |
| 654 | { "glGetActiveUniformsiv" , (QFunctionPointer) ::glGetActiveUniformsiv }, |
| 655 | { "glGetBufferParameteri64v" , (QFunctionPointer) ::glGetBufferParameteri64v }, |
| 656 | { "glGetBufferPointerv" , (QFunctionPointer) ::glGetBufferPointerv }, |
| 657 | { "glGetFragDataLocation" , (QFunctionPointer) ::glGetFragDataLocation }, |
| 658 | { "glGetInteger64i_v" , (QFunctionPointer) ::glGetInteger64i_v }, |
| 659 | { "glGetInteger64v" , (QFunctionPointer) ::glGetInteger64v }, |
| 660 | { "glGetIntegeri_v" , (QFunctionPointer) ::glGetIntegeri_v }, |
| 661 | { "glGetInternalformativ" , (QFunctionPointer) ::glGetInternalformativ }, |
| 662 | { "glGetProgramBinary" , (QFunctionPointer) ::glGetProgramBinary }, |
| 663 | { "glGetQueryObjectuiv" , (QFunctionPointer) ::glGetQueryObjectuiv }, |
| 664 | { "glGetQueryiv" , (QFunctionPointer) ::glGetQueryiv }, |
| 665 | { "glGetSamplerParameterfv" , (QFunctionPointer) ::glGetSamplerParameterfv }, |
| 666 | { "glGetSamplerParameteriv" , (QFunctionPointer) ::glGetSamplerParameteriv }, |
| 667 | { "glGetStringi" , (QFunctionPointer) ::glGetStringi }, |
| 668 | { "glGetSynciv" , (QFunctionPointer) ::glGetSynciv }, |
| 669 | { "glGetTransformFeedbackVarying" , (QFunctionPointer) ::glGetTransformFeedbackVarying }, |
| 670 | { "glGetUniformBlockIndex" , (QFunctionPointer) ::glGetUniformBlockIndex }, |
| 671 | { "glGetUniformIndices" , (QFunctionPointer) ::glGetUniformIndices }, |
| 672 | { "glGetUniformuiv" , (QFunctionPointer) ::glGetUniformuiv }, |
| 673 | { "glGetVertexAttribIiv" , (QFunctionPointer) ::glGetVertexAttribIiv }, |
| 674 | { "glGetVertexAttribIuiv" , (QFunctionPointer) ::glGetVertexAttribIuiv }, |
| 675 | { "glInvalidateFramebuffer" , (QFunctionPointer) ::glInvalidateFramebuffer }, |
| 676 | { "glInvalidateSubFramebuffer" , (QFunctionPointer) ::glInvalidateSubFramebuffer }, |
| 677 | { "glIsQuery" , (QFunctionPointer) ::glIsQuery }, |
| 678 | { "glIsSampler" , (QFunctionPointer) ::glIsSampler }, |
| 679 | { "glIsSync" , (QFunctionPointer) ::glIsSync }, |
| 680 | { "glIsTransformFeedback" , (QFunctionPointer) ::glIsTransformFeedback }, |
| 681 | { "glIsVertexArray" , (QFunctionPointer) ::glIsVertexArray }, |
| 682 | { "glMapBufferRange" , (QFunctionPointer) ::glMapBufferRange }, |
| 683 | { "glPauseTransformFeedback" , (QFunctionPointer) ::glPauseTransformFeedback }, |
| 684 | { "glProgramBinary" , (QFunctionPointer) ::glProgramBinary }, |
| 685 | { "glProgramParameteri" , (QFunctionPointer) ::glProgramParameteri }, |
| 686 | { "glReadBuffer" , (QFunctionPointer) ::glReadBuffer }, |
| 687 | { "glRenderbufferStorageMultisample" , (QFunctionPointer) ::glRenderbufferStorageMultisample }, |
| 688 | { "glResumeTransformFeedback" , (QFunctionPointer) ::glResumeTransformFeedback }, |
| 689 | { "glSamplerParameterf" , (QFunctionPointer) ::glSamplerParameterf }, |
| 690 | { "glSamplerParameterfv" , (QFunctionPointer) ::glSamplerParameterfv }, |
| 691 | { "glSamplerParameteri" , (QFunctionPointer) ::glSamplerParameteri }, |
| 692 | { "glSamplerParameteriv" , (QFunctionPointer) ::glSamplerParameteriv }, |
| 693 | { "glTexImage3D" , (QFunctionPointer) ::glTexImage3D }, |
| 694 | { "glTexStorage2D" , (QFunctionPointer) ::glTexStorage2D }, |
| 695 | { "glTexStorage3D" , (QFunctionPointer) ::glTexStorage3D }, |
| 696 | { "glTexSubImage3D" , (QFunctionPointer) ::glTexSubImage3D }, |
| 697 | { "glTransformFeedbackVaryings" , (QFunctionPointer) ::glTransformFeedbackVaryings }, |
| 698 | { "glUniform1ui" , (QFunctionPointer) ::glUniform1ui }, |
| 699 | { "glUniform1uiv" , (QFunctionPointer) ::glUniform1uiv }, |
| 700 | { "glUniform2ui" , (QFunctionPointer) ::glUniform2ui }, |
| 701 | { "glUniform2uiv" , (QFunctionPointer) ::glUniform2uiv }, |
| 702 | { "glUniform3ui" , (QFunctionPointer) ::glUniform3ui }, |
| 703 | { "glUniform3uiv" , (QFunctionPointer) ::glUniform3uiv }, |
| 704 | { "glUniform4ui" , (QFunctionPointer) ::glUniform4ui }, |
| 705 | { "glUniform4uiv" , (QFunctionPointer) ::glUniform4uiv }, |
| 706 | { "glUniformBlockBinding" , (QFunctionPointer) ::glUniformBlockBinding }, |
| 707 | { "glUniformMatrix2x3fv" , (QFunctionPointer) ::glUniformMatrix2x3fv }, |
| 708 | { "glUniformMatrix2x4fv" , (QFunctionPointer) ::glUniformMatrix2x4fv }, |
| 709 | { "glUniformMatrix3x2fv" , (QFunctionPointer) ::glUniformMatrix3x2fv }, |
| 710 | { "glUniformMatrix3x4fv" , (QFunctionPointer) ::glUniformMatrix3x4fv }, |
| 711 | { "glUniformMatrix4x2fv" , (QFunctionPointer) ::glUniformMatrix4x2fv }, |
| 712 | { "glUniformMatrix4x3fv" , (QFunctionPointer) ::glUniformMatrix4x3fv }, |
| 713 | { "glUnmapBuffer" , (QFunctionPointer) ::glUnmapBuffer }, |
| 714 | { "glVertexAttribDivisor" , (QFunctionPointer) ::glVertexAttribDivisor }, |
| 715 | { "glVertexAttribI4i" , (QFunctionPointer) ::glVertexAttribI4i }, |
| 716 | { "glVertexAttribI4iv" , (QFunctionPointer) ::glVertexAttribI4iv }, |
| 717 | { "glVertexAttribI4ui" , (QFunctionPointer) ::glVertexAttribI4ui }, |
| 718 | { "glVertexAttribI4uiv" , (QFunctionPointer) ::glVertexAttribI4uiv }, |
| 719 | { "glVertexAttribIPointer" , (QFunctionPointer) ::glVertexAttribIPointer }, |
| 720 | { "glWaitSync" , (QFunctionPointer) ::glWaitSync }, |
| 721 | #endif // QT_OPENGL_ES_3 |
| 722 | |
| 723 | #ifdef QT_OPENGL_ES_3_1 |
| 724 | { "glActiveShaderProgram" , (QFunctionPointer) ::glActiveShaderProgram }, |
| 725 | { "glBindImageTexture" , (QFunctionPointer) ::glBindImageTexture }, |
| 726 | { "glBindProgramPipeline" , (QFunctionPointer) ::glBindProgramPipeline }, |
| 727 | { "glBindVertexBuffer" , (QFunctionPointer) ::glBindVertexBuffer }, |
| 728 | { "glCreateShaderProgramv" , (QFunctionPointer) ::glCreateShaderProgramv }, |
| 729 | { "glDeleteProgramPipelines" , (QFunctionPointer) ::glDeleteProgramPipelines }, |
| 730 | { "glDispatchCompute" , (QFunctionPointer) ::glDispatchCompute }, |
| 731 | { "glDispatchComputeIndirect" , (QFunctionPointer) ::glDispatchComputeIndirect }, |
| 732 | { "glDrawArraysIndirect" , (QFunctionPointer) ::glDrawArraysIndirect }, |
| 733 | { "glDrawElementsIndirect" , (QFunctionPointer) ::glDrawElementsIndirect }, |
| 734 | { "glFramebufferParameteri" , (QFunctionPointer) ::glFramebufferParameteri }, |
| 735 | { "glGenProgramPipelines" , (QFunctionPointer) ::glGenProgramPipelines }, |
| 736 | { "glGetBooleani_v" , (QFunctionPointer) ::glGetBooleani_v }, |
| 737 | { "glGetFramebufferParameteriv" , (QFunctionPointer) ::glGetFramebufferParameteriv }, |
| 738 | { "glGetMultisamplefv" , (QFunctionPointer) ::glGetMultisamplefv }, |
| 739 | { "glGetProgramInterfaceiv" , (QFunctionPointer) ::glGetProgramInterfaceiv }, |
| 740 | { "glGetProgramPipelineInfoLog" , (QFunctionPointer) ::glGetProgramPipelineInfoLog }, |
| 741 | { "glGetProgramPipelineiv" , (QFunctionPointer) ::glGetProgramPipelineiv }, |
| 742 | { "glGetProgramResourceIndex" , (QFunctionPointer) ::glGetProgramResourceIndex }, |
| 743 | { "glGetProgramResourceLocation" , (QFunctionPointer) ::glGetProgramResourceLocation }, |
| 744 | { "glGetProgramResourceName" , (QFunctionPointer) ::glGetProgramResourceName }, |
| 745 | { "glGetProgramResourceiv" , (QFunctionPointer) ::glGetProgramResourceiv }, |
| 746 | { "glGetTexLevelParameterfv" , (QFunctionPointer) ::glGetTexLevelParameterfv }, |
| 747 | { "glGetTexLevelParameteriv" , (QFunctionPointer) ::glGetTexLevelParameteriv }, |
| 748 | { "glIsProgramPipeline" , (QFunctionPointer) ::glIsProgramPipeline }, |
| 749 | { "glMemoryBarrier" , (QFunctionPointer) ::glMemoryBarrier }, |
| 750 | { "glMemoryBarrierByRegion" , (QFunctionPointer) ::glMemoryBarrierByRegion }, |
| 751 | { "glProgramUniform1f" , (QFunctionPointer) ::glProgramUniform1f }, |
| 752 | { "glProgramUniform1fv" , (QFunctionPointer) ::glProgramUniform1fv }, |
| 753 | { "glProgramUniform1i" , (QFunctionPointer) ::glProgramUniform1i }, |
| 754 | { "glProgramUniform1iv" , (QFunctionPointer) ::glProgramUniform1iv }, |
| 755 | { "glProgramUniform1ui" , (QFunctionPointer) ::glProgramUniform1ui }, |
| 756 | { "glProgramUniform1uiv" , (QFunctionPointer) ::glProgramUniform1uiv }, |
| 757 | { "glProgramUniform2f" , (QFunctionPointer) ::glProgramUniform2f }, |
| 758 | { "glProgramUniform2fv" , (QFunctionPointer) ::glProgramUniform2fv }, |
| 759 | { "glProgramUniform2i" , (QFunctionPointer) ::glProgramUniform2i }, |
| 760 | { "glProgramUniform2iv" , (QFunctionPointer) ::glProgramUniform2iv }, |
| 761 | { "glProgramUniform2ui" , (QFunctionPointer) ::glProgramUniform2ui }, |
| 762 | { "glProgramUniform2uiv" , (QFunctionPointer) ::glProgramUniform2uiv }, |
| 763 | { "glProgramUniform3f" , (QFunctionPointer) ::glProgramUniform3f }, |
| 764 | { "glProgramUniform3fv" , (QFunctionPointer) ::glProgramUniform3fv }, |
| 765 | { "glProgramUniform3i" , (QFunctionPointer) ::glProgramUniform3i }, |
| 766 | { "glProgramUniform3iv" , (QFunctionPointer) ::glProgramUniform3iv }, |
| 767 | { "glProgramUniform3ui" , (QFunctionPointer) ::glProgramUniform3ui }, |
| 768 | { "glProgramUniform3uiv" , (QFunctionPointer) ::glProgramUniform3uiv }, |
| 769 | { "glProgramUniform4f" , (QFunctionPointer) ::glProgramUniform4f }, |
| 770 | { "glProgramUniform4fv" , (QFunctionPointer) ::glProgramUniform4fv }, |
| 771 | { "glProgramUniform4i" , (QFunctionPointer) ::glProgramUniform4i }, |
| 772 | { "glProgramUniform4iv" , (QFunctionPointer) ::glProgramUniform4iv }, |
| 773 | { "glProgramUniform4ui" , (QFunctionPointer) ::glProgramUniform4ui }, |
| 774 | { "glProgramUniform4uiv" , (QFunctionPointer) ::glProgramUniform4uiv }, |
| 775 | { "glProgramUniformMatrix2fv" , (QFunctionPointer) ::glProgramUniformMatrix2fv }, |
| 776 | { "glProgramUniformMatrix2x3fv" , (QFunctionPointer) ::glProgramUniformMatrix2x3fv }, |
| 777 | { "glProgramUniformMatrix2x4fv" , (QFunctionPointer) ::glProgramUniformMatrix2x4fv }, |
| 778 | { "glProgramUniformMatrix3fv" , (QFunctionPointer) ::glProgramUniformMatrix3fv }, |
| 779 | { "glProgramUniformMatrix3x2fv" , (QFunctionPointer) ::glProgramUniformMatrix3x2fv }, |
| 780 | { "glProgramUniformMatrix3x4fv" , (QFunctionPointer) ::glProgramUniformMatrix3x4fv }, |
| 781 | { "glProgramUniformMatrix4fv" , (QFunctionPointer) ::glProgramUniformMatrix4fv }, |
| 782 | { "glProgramUniformMatrix4x2fv" , (QFunctionPointer) ::glProgramUniformMatrix4x2fv }, |
| 783 | { "glProgramUniformMatrix4x3fv" , (QFunctionPointer) ::glProgramUniformMatrix4x3fv }, |
| 784 | { "glSampleMaski" , (QFunctionPointer) ::glSampleMaski }, |
| 785 | { "glTexStorage2DMultisample" , (QFunctionPointer) ::glTexStorage2DMultisample }, |
| 786 | { "glUseProgramStages" , (QFunctionPointer) ::glUseProgramStages }, |
| 787 | { "glValidateProgramPipeline" , (QFunctionPointer) ::glValidateProgramPipeline }, |
| 788 | { "glVertexAttribBinding" , (QFunctionPointer) ::glVertexAttribBinding }, |
| 789 | { "glVertexAttribFormat" , (QFunctionPointer) ::glVertexAttribFormat }, |
| 790 | { "glVertexAttribIFormat" , (QFunctionPointer) ::glVertexAttribIFormat }, |
| 791 | { "glVertexBindingDivisor" , (QFunctionPointer) ::glVertexBindingDivisor }, |
| 792 | #endif // QT_OPENGL_ES_3_1 |
| 793 | |
| 794 | #ifdef QT_OPENGL_ES_3_2 |
| 795 | { "glBlendBarrier" , (QFunctionPointer) ::glBlendBarrier }, |
| 796 | { "glCopyImageSubData" , (QFunctionPointer) ::glCopyImageSubData }, |
| 797 | { "glDebugMessageControl" , (QFunctionPointer) ::glDebugMessageControl }, |
| 798 | { "glDebugMessageInsert" , (QFunctionPointer) ::glDebugMessageInsert }, |
| 799 | { "glDebugMessageCallback" , (QFunctionPointer) ::glDebugMessageCallback }, |
| 800 | { "glGetDebugMessageLog" , (QFunctionPointer) ::glGetDebugMessageLog }, |
| 801 | { "glPushDebugGroup" , (QFunctionPointer) ::glPushDebugGroup }, |
| 802 | { "glPopDebugGroup" , (QFunctionPointer) ::glPopDebugGroup }, |
| 803 | { "glObjectLabel" , (QFunctionPointer) ::glObjectLabel }, |
| 804 | { "glGetObjectLabel" , (QFunctionPointer) ::glGetObjectLabel }, |
| 805 | { "glObjectPtrLabel" , (QFunctionPointer) ::glObjectPtrLabel }, |
| 806 | { "glGetObjectPtrLabel" , (QFunctionPointer) ::glGetObjectPtrLabel }, |
| 807 | { "glGetPointerv" , (QFunctionPointer) ::glGetPointerv }, |
| 808 | { "glEnablei" , (QFunctionPointer) ::glEnablei }, |
| 809 | { "glDisablei" , (QFunctionPointer) ::glDisablei }, |
| 810 | { "glBlendEquationi" , (QFunctionPointer) ::glBlendEquationi }, |
| 811 | { "glBlendEquationSeparatei" , (QFunctionPointer) ::glBlendEquationSeparatei }, |
| 812 | { "glBlendFunci" , (QFunctionPointer) ::glBlendFunci }, |
| 813 | { "glBlendFuncSeparatei" , (QFunctionPointer) ::glBlendFuncSeparatei }, |
| 814 | { "glColorMaski" , (QFunctionPointer) ::glColorMaski }, |
| 815 | { "glIsEnabledi" , (QFunctionPointer) ::glIsEnabledi }, |
| 816 | { "glDrawElementsBaseVertex" , (QFunctionPointer) ::glDrawElementsBaseVertex }, |
| 817 | { "glDrawRangeElementsBaseVertex" , (QFunctionPointer) ::glDrawRangeElementsBaseVertex }, |
| 818 | { "glDrawElementsInstancedBaseVertex" , (QFunctionPointer) ::glDrawElementsInstancedBaseVertex }, |
| 819 | { "glFramebufferTexture" , (QFunctionPointer) ::glFramebufferTexture }, |
| 820 | { "glPrimitiveBoundingBox" , (QFunctionPointer) ::glPrimitiveBoundingBox }, |
| 821 | { "glGetGraphicsResetStatus" , (QFunctionPointer) ::glGetGraphicsResetStatus }, |
| 822 | { "glReadnPixels" , (QFunctionPointer) ::glReadnPixels }, |
| 823 | { "glGetnUniformfv" , (QFunctionPointer) ::glGetnUniformfv }, |
| 824 | { "glGetnUniformiv" , (QFunctionPointer) ::glGetnUniformiv }, |
| 825 | { "glGetnUniformuiv" , (QFunctionPointer) ::glGetnUniformuiv }, |
| 826 | { "glMinSampleShading" , (QFunctionPointer) ::glMinSampleShading }, |
| 827 | { "glPatchParameteri" , (QFunctionPointer) ::glPatchParameteri }, |
| 828 | { "glTexParameterIiv" , (QFunctionPointer) ::glTexParameterIiv }, |
| 829 | { "glTexParameterIuiv" , (QFunctionPointer) ::glTexParameterIuiv }, |
| 830 | { "glGetTexParameterIiv" , (QFunctionPointer) ::glGetTexParameterIiv }, |
| 831 | { "glGetTexParameterIuiv" , (QFunctionPointer) ::glGetTexParameterIuiv }, |
| 832 | { "glSamplerParameterIiv" , (QFunctionPointer) ::glSamplerParameterIiv }, |
| 833 | { "glSamplerParameterIuiv" , (QFunctionPointer) ::glSamplerParameterIuiv }, |
| 834 | { "glGetSamplerParameterIiv" , (QFunctionPointer) ::glGetSamplerParameterIiv }, |
| 835 | { "glGetSamplerParameterIuiv" , (QFunctionPointer) ::glGetSamplerParameterIuiv }, |
| 836 | { "glTexBuffer" , (QFunctionPointer) ::glTexBuffer }, |
| 837 | { "glTexBufferRange" , (QFunctionPointer) ::glTexBufferRange }, |
| 838 | { "glTexStorage3DMultisample" , (QFunctionPointer) ::glTexStorage3DMultisample }, |
| 839 | #endif // QT_OPENGL_ES_3_2 |
| 840 | }; |
| 841 | |
| 842 | for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i) { |
| 843 | if (!qstrcmp(procName, standardFuncs[i].name)) { |
| 844 | proc = standardFuncs[i].func; |
| 845 | break; |
| 846 | } |
| 847 | } |
| 848 | } |
| 849 | #endif |
| 850 | |
| 851 | return proc; |
| 852 | } |
| 853 | |
| 854 | QSurfaceFormat QEGLPlatformContext::format() const |
| 855 | { |
| 856 | return m_format; |
| 857 | } |
| 858 | |
| 859 | EGLContext QEGLPlatformContext::eglContext() const |
| 860 | { |
| 861 | return m_eglContext; |
| 862 | } |
| 863 | |
| 864 | EGLDisplay QEGLPlatformContext::eglDisplay() const |
| 865 | { |
| 866 | return m_eglDisplay; |
| 867 | } |
| 868 | |
| 869 | EGLConfig QEGLPlatformContext::eglConfig() const |
| 870 | { |
| 871 | return m_eglConfig; |
| 872 | } |
| 873 | |
| 874 | QT_END_NAMESPACE |
| 875 | |