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