summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowseglcontext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows/qwindowseglcontext.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp918
1 files changed, 0 insertions, 918 deletions
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
deleted file mode 100644
index d0b3568dad..0000000000
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ /dev/null
@@ -1,918 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwindowseglcontext.h"
-#include "qwindowscontext.h"
-#include "qwindowswindow.h"
-
-#include <QtCore/qdebug.h>
-#include <QtGui/qopenglcontext.h>
-
-#if QT_CONFIG(angle) || defined(QT_OPENGL_DYNAMIC)
-# include <EGL/eglext.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QWindowsEGLStaticContext
- \brief Static data for QWindowsEGLContext.
-
- Keeps the display. The class is shared via QSharedPointer in the windows, the
- contexts and in QWindowsIntegration. The display will be closed if the last instance
- is deleted.
-
- No EGL or OpenGL functions are called directly. Instead, they are resolved
- dynamically. This works even if the plugin links directly to libegl/libglesv2 so
- there is no need to differentiate between dynamic or Angle-only builds in here.
-
- \internal
-*/
-
-QWindowsLibEGL QWindowsEGLStaticContext::libEGL;
-QWindowsLibGLESv2 QWindowsEGLStaticContext::libGLESv2;
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
-
-#ifdef Q_CC_MINGW
-static void *resolveFunc(HMODULE lib, const char *name)
-{
- QString baseNameStr = QString::fromLatin1(name);
- QString nameStr;
- void *proc = 0;
-
- // Play nice with 32-bit mingw: Try func first, then func@0, func@4,
- // func@8, func@12, ..., func@64. The def file does not provide any aliases
- // in libEGL and libGLESv2 in these builds which results in exporting
- // function names like eglInitialize@12. This cannot be fixed without
- // breaking binary compatibility. So be flexible here instead.
-
- int argSize = -1;
- while (!proc && argSize <= 64) {
- nameStr = baseNameStr;
- if (argSize >= 0)
- nameStr += u'@' + QString::number(argSize);
- argSize = argSize < 0 ? 0 : argSize + 4;
- proc = (void *) ::GetProcAddress(lib, nameStr.toLatin1().constData());
- }
- return proc;
-}
-#else
-static inline void *resolveFunc(HMODULE lib, const char *name)
-{
- return ::GetProcAddress(lib, name);
-}
-#endif // Q_CC_MINGW
-
-void *QWindowsLibEGL::resolve(const char *name)
-{
- return m_lib ? resolveFunc(m_lib, name) : nullptr;
-}
-
-#endif // !QT_STATIC
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
-# define RESOLVE(signature, name) signature(resolve( #name ));
-#else
-# define RESOLVE(signature, name) signature(&::name);
-#endif
-
-bool QWindowsLibEGL::init()
-{
- const char dllName[] = QT_STRINGIFY(LIBEGL_NAME)
-#if defined(QT_DEBUG)
- "d"
-#endif
- "";
-
- qCDebug(lcQpaGl) << "Qt: Using EGL from" << dllName;
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
- m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16());
- if (!m_lib) {
- qErrnoWarning(::GetLastError(), "Failed to load %s", dllName);
- return false;
- }
-#endif
-
- eglGetError = RESOLVE((EGLint (EGLAPIENTRY *)(void)), eglGetError);
- eglGetDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLNativeDisplayType)), eglGetDisplay);
- eglInitialize = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLint *, EGLint *)), eglInitialize);
- eglTerminate = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay)), eglTerminate);
- eglChooseConfig = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)), eglChooseConfig);
- eglGetConfigAttrib = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLint, EGLint *)), eglGetConfigAttrib);
- eglCreateWindowSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLNativeWindowType, const EGLint *)), eglCreateWindowSurface);
- eglCreatePbufferSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLDisplay , EGLConfig, const EGLint *)), eglCreatePbufferSurface);
- eglDestroySurface = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface )), eglDestroySurface);
- eglBindAPI = RESOLVE((EGLBoolean (EGLAPIENTRY * )(EGLenum )), eglBindAPI);
- eglSwapInterval = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLint )), eglSwapInterval);
- eglCreateContext = RESOLVE((EGLContext (EGLAPIENTRY *)(EGLDisplay , EGLConfig , EGLContext , const EGLint *)), eglCreateContext);
- eglDestroyContext = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLContext)), eglDestroyContext);
- eglMakeCurrent = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface , EGLSurface , EGLContext )), eglMakeCurrent);
- eglGetCurrentContext = RESOLVE((EGLContext (EGLAPIENTRY *)(void)), eglGetCurrentContext);
- eglGetCurrentSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLint )), eglGetCurrentSurface);
- eglGetCurrentDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(void)), eglGetCurrentDisplay);
- eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers);
- eglGetProcAddress = RESOLVE((QFunctionPointer (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
-
- if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress)
- return false;
-
- eglGetPlatformDisplayEXT = nullptr;
-#ifdef EGL_ANGLE_platform_angle
- eglGetPlatformDisplayEXT = reinterpret_cast<EGLDisplay (EGLAPIENTRY *)(EGLenum, void *, const EGLint *)>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
-#endif
-
- return true;
-}
-
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
-void *QWindowsLibGLESv2::resolve(const char *name)
-{
- return m_lib ? resolveFunc(m_lib, name) : nullptr;
-}
-#endif // !QT_STATIC
-
-bool QWindowsLibGLESv2::init()
-{
-
- const char dllName[] = QT_STRINGIFY(LIBGLESV2_NAME)
-#if defined(QT_DEBUG)
- "d"
-#endif
- "";
-
- qCDebug(lcQpaGl) << "Qt: Using OpenGL ES 2.0 from" << dllName;
-#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
- m_lib = ::LoadLibraryW(reinterpret_cast<LPCWSTR>(QString::fromLatin1(dllName).utf16()));
- if (!m_lib) {
- qErrnoWarning(int(GetLastError()), "Failed to load %s", dllName);
- return false;
- }
-#endif // !QT_STATIC
-
- void (APIENTRY * glBindTexture)(GLenum target, GLuint texture) = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindTexture);
- GLuint (APIENTRY * glCreateShader)(GLenum type) = RESOLVE((GLuint (APIENTRY *)(GLenum )), glCreateShader);
- void (APIENTRY * glClearDepthf)(GLclampf depth) = RESOLVE((void (APIENTRY *)(GLclampf )), glClearDepthf);
- glGetString = RESOLVE((const GLubyte * (APIENTRY *)(GLenum )), glGetString);
-
- return glBindTexture && glCreateShader && glClearDepthf;
-}
-
-QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display)
- : m_display(display)
-{
-}
-
-bool QWindowsEGLStaticContext::initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc,
- EGLDisplay *display, EGLint *major, EGLint *minor)
-{
-#ifdef EGL_ANGLE_platform_angle
- if (libEGL.eglGetPlatformDisplayEXT
- && (preferredType & QWindowsOpenGLTester::AngleBackendMask)) {
- const EGLint anglePlatformAttributes[][5] = {
- { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE },
- { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE },
- { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
- EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_NONE }
- };
- const EGLint *attributes = nullptr;
- if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)
- attributes = anglePlatformAttributes[0];
- else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d9)
- attributes = anglePlatformAttributes[1];
- else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11Warp)
- attributes = anglePlatformAttributes[2];
- if (attributes) {
- *display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes);
- if (!libEGL.eglInitialize(*display, major, minor)) {
- libEGL.eglTerminate(*display);
- *display = EGL_NO_DISPLAY;
- *major = *minor = 0;
- return false;
- }
- }
- }
-#else // EGL_ANGLE_platform_angle
- Q_UNUSED(preferredType);
- Q_UNUSED(dc);
- Q_UNUSED(display);
- Q_UNUSED(major);
- Q_UNUSED(minor);
-#endif
- return true;
-}
-
-QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester::Renderers preferredType)
-{
- const HDC dc = QWindowsContext::instance()->displayContext();
- if (!dc){
- qWarning("%s: No Display", __FUNCTION__);
- return nullptr;
- }
-
- if (!libEGL.init()) {
- qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__);
- return nullptr;
- }
- if (!libGLESv2.init()) {
- qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__);
- return nullptr;
- }
-
- EGLDisplay display = EGL_NO_DISPLAY;
- EGLint major = 0;
- EGLint minor = 0;
-
- if (!initializeAngle(preferredType, dc, &display, &major, &minor)
- && (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)) {
- preferredType &= ~QWindowsOpenGLTester::AngleRendererD3d11;
- initializeAngle(preferredType, dc, &display, &major, &minor);
- }
-
- if (display == EGL_NO_DISPLAY)
- display = libEGL.eglGetDisplay(dc);
- if (!display) {
- qWarning("%s: Could not obtain EGL display", __FUNCTION__);
- return nullptr;
- }
-
- if (!major && !libEGL.eglInitialize(display, &major, &minor)) {
- int err = libEGL.eglGetError();
- qWarning("%s: Could not initialize EGL display: error 0x%x", __FUNCTION__, err);
- if (err == 0x3001)
- qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__);
- return nullptr;
- }
-
- qCDebug(lcQpaGl) << __FUNCTION__ << "Created EGL display" << display << 'v' <<major << '.' << minor;
- return new QWindowsEGLStaticContext(display);
-}
-
-QWindowsEGLStaticContext::~QWindowsEGLStaticContext()
-{
- qCDebug(lcQpaGl) << __FUNCTION__ << "Releasing EGL display " << m_display;
- libEGL.eglTerminate(m_display);
-}
-
-QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *context)
-{
- return new QWindowsEGLContext(this, context->format(), context->shareHandle());
-}
-
-void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig, int *err)
-{
- *err = 0;
- EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, nativeConfig,
- static_cast<EGLNativeWindowType>(nativeWindow), nullptr);
- if (surface == EGL_NO_SURFACE) {
- *err = libEGL.eglGetError();
- qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err);
- }
-
- return surface;
-}
-
-void QWindowsEGLStaticContext::destroyWindowSurface(void *nativeSurface)
-{
- libEGL.eglDestroySurface(m_display, nativeSurface);
-}
-
-QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EGLConfig config,
- const QSurfaceFormat &referenceFormat)
-{
- QSurfaceFormat format;
- EGLint redSize = 0;
- EGLint greenSize = 0;
- EGLint blueSize = 0;
- EGLint alphaSize = 0;
- EGLint depthSize = 0;
- EGLint stencilSize = 0;
- EGLint sampleCount = 0;
-
- libEGL.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
- libEGL.eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount);
-
- format.setRenderableType(QSurfaceFormat::OpenGLES);
- format.setVersion(referenceFormat.majorVersion(), referenceFormat.minorVersion());
- format.setProfile(referenceFormat.profile());
- format.setOptions(referenceFormat.options());
-
- format.setRedBufferSize(redSize);
- format.setGreenBufferSize(greenSize);
- format.setBlueBufferSize(blueSize);
- format.setAlphaBufferSize(alphaSize);
- format.setDepthBufferSize(depthSize);
- format.setStencilBufferSize(stencilSize);
- format.setSamples(sampleCount);
- format.setStereo(false);
- format.setSwapInterval(referenceFormat.swapInterval());
-
- // Clear the EGL error state because some of the above may
- // have errored out because the attribute is not applicable
- // to the surface type. Such errors don't matter.
- libEGL.eglGetError();
-
- return format;
-}
-
-/*!
- \class QWindowsEGLContext
- \brief Open EGL context.
-
- \section1 Using QWindowsEGLContext for Desktop with ANGLE
- \section2 Build Instructions
- \list
- \o Install the Direct X SDK
- \o Checkout and build ANGLE (SVN repository) as explained here:
- \l{https://chromium.googlesource.com/angle/angle/+/master/README.md}
- When building for 64bit, de-activate the "WarnAsError" option
- in every project file (as otherwise integer conversion
- warnings will break the build).
- \o Run configure.exe with the options "-opengl es2".
- \o Build qtbase and test some examples.
- \endlist
-
- \internal
-*/
-
-QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
- const QSurfaceFormat &format,
- QPlatformOpenGLContext *share)
- : m_staticContext(staticContext)
- , m_eglDisplay(staticContext->display())
-{
- if (!m_staticContext)
- return;
-
- m_eglConfig = chooseConfig(format);
- m_format = m_staticContext->formatFromConfig(m_eglDisplay, m_eglConfig, format);
- m_shareContext = share ? static_cast<QWindowsEGLContext *>(share)->m_eglContext : nullptr;
-
- QVector<EGLint> contextAttrs;
- const int major = m_format.majorVersion();
- const int minor = m_format.minorVersion();
- if (major > 3 || (major == 3 && minor > 0))
- qWarning("QWindowsEGLContext: ANGLE only partially supports OpenGL ES > 3.0");
- contextAttrs.append(EGL_CONTEXT_MAJOR_VERSION);
- contextAttrs.append(major);
- contextAttrs.append(EGL_CONTEXT_MINOR_VERSION);
- contextAttrs.append(minor);
- contextAttrs.append(EGL_NONE);
-
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData());
- if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
- m_shareContext = nullptr;
- m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, nullptr, contextAttrs.constData());
- }
-
- if (m_eglContext == EGL_NO_CONTEXT) {
- int err = QWindowsEGLStaticContext::libEGL.eglGetError();
- qWarning("QWindowsEGLContext: Failed to create context, eglError: %x, this: %p", err, this);
- // ANGLE gives bad alloc when it fails to reset a previously lost D3D device.
- // A common cause for this is disabling the graphics adapter used by the app.
- if (err == EGL_BAD_ALLOC)
- qWarning("QWindowsEGLContext: Graphics device lost. (Did the adapter get disabled?)");
- return;
- }
-
- // Make the context current to ensure the GL version query works. This needs a surface too.
- const EGLint pbufferAttributes[] = {
- EGL_WIDTH, 1,
- EGL_HEIGHT, 1,
- EGL_LARGEST_PBUFFER, EGL_FALSE,
- EGL_NONE
- };
- EGLSurface pbuffer = QWindowsEGLStaticContext::libEGL.eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, pbufferAttributes);
- if (pbuffer == EGL_NO_SURFACE)
- return;
-
- EGLDisplay prevDisplay = QWindowsEGLStaticContext::libEGL.eglGetCurrentDisplay();
- if (prevDisplay == EGL_NO_DISPLAY) // when no context is current
- prevDisplay = m_eglDisplay;
- EGLContext prevContext = QWindowsEGLStaticContext::libEGL.eglGetCurrentContext();
- EGLSurface prevSurfaceDraw = QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_DRAW);
- EGLSurface prevSurfaceRead = QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_READ);
-
- if (QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) {
- const GLubyte *s = QWindowsEGLStaticContext::libGLESv2.glGetString(GL_VERSION);
- if (s) {
- QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
- int major, minor;
- if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
- m_format.setMajorVersion(major);
- m_format.setMinorVersion(minor);
- }
- }
- m_format.setProfile(QSurfaceFormat::NoProfile);
- m_format.setOptions(QSurfaceFormat::FormatOptions());
- QWindowsEGLStaticContext::libEGL.eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext);
- }
- QWindowsEGLStaticContext::libEGL.eglDestroySurface(m_eglDisplay, pbuffer);
-}
-
-QWindowsEGLContext::~QWindowsEGLContext()
-{
- if (m_eglContext != EGL_NO_CONTEXT) {
- QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
- m_eglContext = EGL_NO_CONTEXT;
- }
-}
-
-bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
-{
- Q_ASSERT(surface->surface()->supportsOpenGL());
-
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
-
- auto *window = static_cast<QWindowsWindow *>(surface);
- window->aboutToMakeCurrent();
- int err = 0;
- auto eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
- if (eglSurface == EGL_NO_SURFACE) {
- if (err == EGL_CONTEXT_LOST) {
- m_eglContext = EGL_NO_CONTEXT;
- qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
- } else if (err == EGL_BAD_ACCESS) {
- // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters.
- qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this;
- // Simulate context loss as the context is useless.
- QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
- m_eglContext = EGL_NO_CONTEXT;
- }
- return false;
- }
-
- // shortcut: on some GPUs, eglMakeCurrent is not a cheap operation
- if (QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() == m_eglContext &&
- QWindowsEGLStaticContext::libEGL.eglGetCurrentDisplay() == m_eglDisplay &&
- QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_READ) == eglSurface &&
- QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_DRAW) == eglSurface) {
- return true;
- }
-
- const bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_eglContext);
- if (ok) {
- const int requestedSwapInterval = surface->format().swapInterval();
- if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) {
- m_swapInterval = requestedSwapInterval;
- QWindowsEGLStaticContext::libEGL.eglSwapInterval(m_staticContext->display(), m_swapInterval);
- }
- } else {
- err = QWindowsEGLStaticContext::libEGL.eglGetError();
- // EGL_CONTEXT_LOST (loss of the D3D device) is not necessarily fatal.
- // Qt Quick is able to recover for example.
- if (err == EGL_CONTEXT_LOST) {
- m_eglContext = EGL_NO_CONTEXT;
- qCDebug(lcQpaGl) << "Got EGL context lost in makeCurrent() for context" << this;
- // Drop the surface. Will recreate on the next makeCurrent.
- window->invalidateSurface();
- } else {
- qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this);
- }
- }
-
- return ok;
-}
-
-void QWindowsEGLContext::doneCurrent()
-{
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (!ok)
- qWarning("%s: Failed to make no context/surface current. eglError: %d, this: %p", __FUNCTION__,
- QWindowsEGLStaticContext::libEGL.eglGetError(), this);
-}
-
-void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
-{
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- auto *window = static_cast<QWindowsWindow *>(surface);
- int err = 0;
- auto eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
- if (eglSurface == EGL_NO_SURFACE) {
- if (err == EGL_CONTEXT_LOST) {
- m_eglContext = EGL_NO_CONTEXT;
- qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
- }
- return;
- }
-
- bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
- if (!ok) {
- err = QWindowsEGLStaticContext::libEGL.eglGetError();
- if (err == EGL_CONTEXT_LOST) {
- m_eglContext = EGL_NO_CONTEXT;
- qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()";
- } else {
- qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this);
- }
- }
-}
-
-QFunctionPointer QWindowsEGLContext::getProcAddress(const char *procName)
-{
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
-
- QFunctionPointer procAddress = nullptr;
-
- // Special logic for ANGLE extensions for blitFramebuffer and
- // renderbufferStorageMultisample. In version 2 contexts the extensions
- // must be used instead of the suffixless, version 3.0 functions.
- if (m_format.majorVersion() < 3) {
- if (!strcmp(procName, "glBlitFramebuffer") || !strcmp(procName, "glRenderbufferStorageMultisample")) {
- char extName[32 + 5 + 1];
- strcpy(extName, procName);
- strcat(extName, "ANGLE");
- procAddress = reinterpret_cast<QFunctionPointer>(QWindowsEGLStaticContext::libEGL.eglGetProcAddress(extName));
- }
- }
-
- if (!procAddress)
- procAddress = reinterpret_cast<QFunctionPointer>(QWindowsEGLStaticContext::libEGL.eglGetProcAddress(procName));
-
- // We support AllGLFunctionsQueryable, which means this function must be able to
- // return a function pointer for standard GLES2 functions too. These are not
- // guaranteed to be queryable via eglGetProcAddress().
- if (!procAddress) {
-#if defined(QT_STATIC) && !defined(QT_OPENGL_DYNAMIC)
- static struct StdFunc {
- const char *name;
- void *func;
- } standardFuncs[] = {
- { "glBindTexture", (void *) ::glBindTexture },
- { "glBlendFunc", (void *) ::glBlendFunc },
- { "glClear", (void *) ::glClear },
- { "glClearColor", (void *) ::glClearColor },
- { "glClearStencil", (void *) ::glClearStencil },
- { "glColorMask", (void *) ::glColorMask },
- { "glCopyTexImage2D", (void *) ::glCopyTexImage2D },
- { "glCopyTexSubImage2D", (void *) ::glCopyTexSubImage2D },
- { "glCullFace", (void *) ::glCullFace },
- { "glDeleteTextures", (void *) ::glDeleteTextures },
- { "glDepthFunc", (void *) ::glDepthFunc },
- { "glDepthMask", (void *) ::glDepthMask },
- { "glDisable", (void *) ::glDisable },
- { "glDrawArrays", (void *) ::glDrawArrays },
- { "glDrawElements", (void *) ::glDrawElements },
- { "glEnable", (void *) ::glEnable },
- { "glFinish", (void *) ::glFinish },
- { "glFlush", (void *) ::glFlush },
- { "glFrontFace", (void *) ::glFrontFace },
- { "glGenTextures", (void *) ::glGenTextures },
- { "glGetBooleanv", (void *) ::glGetBooleanv },
- { "glGetError", (void *) ::glGetError },
- { "glGetFloatv", (void *) ::glGetFloatv },
- { "glGetIntegerv", (void *) ::glGetIntegerv },
- { "glGetString", (void *) ::glGetString },
- { "glGetTexParameterfv", (void *) ::glGetTexParameterfv },
- { "glGetTexParameteriv", (void *) ::glGetTexParameteriv },
- { "glHint", (void *) ::glHint },
- { "glIsEnabled", (void *) ::glIsEnabled },
- { "glIsTexture", (void *) ::glIsTexture },
- { "glLineWidth", (void *) ::glLineWidth },
- { "glPixelStorei", (void *) ::glPixelStorei },
- { "glPolygonOffset", (void *) ::glPolygonOffset },
- { "glReadPixels", (void *) ::glReadPixels },
- { "glScissor", (void *) ::glScissor },
- { "glStencilFunc", (void *) ::glStencilFunc },
- { "glStencilMask", (void *) ::glStencilMask },
- { "glStencilOp", (void *) ::glStencilOp },
- { "glTexImage2D", (void *) ::glTexImage2D },
- { "glTexParameterf", (void *) ::glTexParameterf },
- { "glTexParameterfv", (void *) ::glTexParameterfv },
- { "glTexParameteri", (void *) ::glTexParameteri },
- { "glTexParameteriv", (void *) ::glTexParameteriv },
- { "glTexSubImage2D", (void *) ::glTexSubImage2D },
- { "glViewport", (void *) ::glViewport },
-
- { "glActiveTexture", (void *) ::glActiveTexture },
- { "glAttachShader", (void *) ::glAttachShader },
- { "glBindAttribLocation", (void *) ::glBindAttribLocation },
- { "glBindBuffer", (void *) ::glBindBuffer },
- { "glBindFramebuffer", (void *) ::glBindFramebuffer },
- { "glBindRenderbuffer", (void *) ::glBindRenderbuffer },
- { "glBlendColor", (void *) ::glBlendColor },
- { "glBlendEquation", (void *) ::glBlendEquation },
- { "glBlendEquationSeparate", (void *) ::glBlendEquationSeparate },
- { "glBlendFuncSeparate", (void *) ::glBlendFuncSeparate },
- { "glBufferData", (void *) ::glBufferData },
- { "glBufferSubData", (void *) ::glBufferSubData },
- { "glCheckFramebufferStatus", (void *) ::glCheckFramebufferStatus },
- { "glCompileShader", (void *) ::glCompileShader },
- { "glCompressedTexImage2D", (void *) ::glCompressedTexImage2D },
- { "glCompressedTexSubImage2D", (void *) ::glCompressedTexSubImage2D },
- { "glCreateProgram", (void *) ::glCreateProgram },
- { "glCreateShader", (void *) ::glCreateShader },
- { "glDeleteBuffers", (void *) ::glDeleteBuffers },
- { "glDeleteFramebuffers", (void *) ::glDeleteFramebuffers },
- { "glDeleteProgram", (void *) ::glDeleteProgram },
- { "glDeleteRenderbuffers", (void *) ::glDeleteRenderbuffers },
- { "glDeleteShader", (void *) ::glDeleteShader },
- { "glDetachShader", (void *) ::glDetachShader },
- { "glDisableVertexAttribArray", (void *) ::glDisableVertexAttribArray },
- { "glEnableVertexAttribArray", (void *) ::glEnableVertexAttribArray },
- { "glFramebufferRenderbuffer", (void *) ::glFramebufferRenderbuffer },
- { "glFramebufferTexture2D", (void *) ::glFramebufferTexture2D },
- { "glGenBuffers", (void *) ::glGenBuffers },
- { "glGenerateMipmap", (void *) ::glGenerateMipmap },
- { "glGenFramebuffers", (void *) ::glGenFramebuffers },
- { "glGenRenderbuffers", (void *) ::glGenRenderbuffers },
- { "glGetActiveAttrib", (void *) ::glGetActiveAttrib },
- { "glGetActiveUniform", (void *) ::glGetActiveUniform },
- { "glGetAttachedShaders", (void *) ::glGetAttachedShaders },
- { "glGetAttribLocation", (void *) ::glGetAttribLocation },
- { "glGetBufferParameteriv", (void *) ::glGetBufferParameteriv },
- { "glGetFramebufferAttachmentParameteriv", (void *) ::glGetFramebufferAttachmentParameteriv },
- { "glGetProgramiv", (void *) ::glGetProgramiv },
- { "glGetProgramInfoLog", (void *) ::glGetProgramInfoLog },
- { "glGetRenderbufferParameteriv", (void *) ::glGetRenderbufferParameteriv },
- { "glGetShaderiv", (void *) ::glGetShaderiv },
- { "glGetShaderInfoLog", (void *) ::glGetShaderInfoLog },
- { "glGetShaderPrecisionFormat", (void *) ::glGetShaderPrecisionFormat },
- { "glGetShaderSource", (void *) ::glGetShaderSource },
- { "glGetUniformfv", (void *) ::glGetUniformfv },
- { "glGetUniformiv", (void *) ::glGetUniformiv },
- { "glGetUniformLocation", (void *) ::glGetUniformLocation },
- { "glGetVertexAttribfv", (void *) ::glGetVertexAttribfv },
- { "glGetVertexAttribiv", (void *) ::glGetVertexAttribiv },
- { "glGetVertexAttribPointerv", (void *) ::glGetVertexAttribPointerv },
- { "glIsBuffer", (void *) ::glIsBuffer },
- { "glIsFramebuffer", (void *) ::glIsFramebuffer },
- { "glIsProgram", (void *) ::glIsProgram },
- { "glIsRenderbuffer", (void *) ::glIsRenderbuffer },
- { "glIsShader", (void *) ::glIsShader },
- { "glLinkProgram", (void *) ::glLinkProgram },
- { "glReleaseShaderCompiler", (void *) ::glReleaseShaderCompiler },
- { "glRenderbufferStorage", (void *) ::glRenderbufferStorage },
- { "glSampleCoverage", (void *) ::glSampleCoverage },
- { "glShaderBinary", (void *) ::glShaderBinary },
- { "glShaderSource", (void *) ::glShaderSource },
- { "glStencilFuncSeparate", (void *) ::glStencilFuncSeparate },
- { "glStencilMaskSeparate", (void *) ::glStencilMaskSeparate },
- { "glStencilOpSeparate", (void *) ::glStencilOpSeparate },
- { "glUniform1f", (void *) ::glUniform1f },
- { "glUniform1fv", (void *) ::glUniform1fv },
- { "glUniform1i", (void *) ::glUniform1i },
- { "glUniform1iv", (void *) ::glUniform1iv },
- { "glUniform2f", (void *) ::glUniform2f },
- { "glUniform2fv", (void *) ::glUniform2fv },
- { "glUniform2i", (void *) ::glUniform2i },
- { "glUniform2iv", (void *) ::glUniform2iv },
- { "glUniform3f", (void *) ::glUniform3f },
- { "glUniform3fv", (void *) ::glUniform3fv },
- { "glUniform3i", (void *) ::glUniform3i },
- { "glUniform3iv", (void *) ::glUniform3iv },
- { "glUniform4f", (void *) ::glUniform4f },
- { "glUniform4fv", (void *) ::glUniform4fv },
- { "glUniform4i", (void *) ::glUniform4i },
- { "glUniform4iv", (void *) ::glUniform4iv },
- { "glUniformMatrix2fv", (void *) ::glUniformMatrix2fv },
- { "glUniformMatrix3fv", (void *) ::glUniformMatrix3fv },
- { "glUniformMatrix4fv", (void *) ::glUniformMatrix4fv },
- { "glUseProgram", (void *) ::glUseProgram },
- { "glValidateProgram", (void *) ::glValidateProgram },
- { "glVertexAttrib1f", (void *) ::glVertexAttrib1f },
- { "glVertexAttrib1fv", (void *) ::glVertexAttrib1fv },
- { "glVertexAttrib2f", (void *) ::glVertexAttrib2f },
- { "glVertexAttrib2fv", (void *) ::glVertexAttrib2fv },
- { "glVertexAttrib3f", (void *) ::glVertexAttrib3f },
- { "glVertexAttrib3fv", (void *) ::glVertexAttrib3fv },
- { "glVertexAttrib4f", (void *) ::glVertexAttrib4f },
- { "glVertexAttrib4fv", (void *) ::glVertexAttrib4fv },
- { "glVertexAttribPointer", (void *) ::glVertexAttribPointer },
-
- { "glClearDepthf", (void *) ::glClearDepthf },
- { "glDepthRangef", (void *) ::glDepthRangef }
- };
- for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i)
- if (!qstrcmp(procName, standardFuncs[i].name))
- return reinterpret_cast<QFunctionPointer>(standardFuncs[i].func);
-#else
- procAddress = reinterpret_cast<QFunctionPointer>(QWindowsEGLStaticContext::libGLESv2.resolve(procName));
-#endif
-}
-
- if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaGl) << __FUNCTION__ << procName << QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() << "returns" << procAddress;
-
- return procAddress;
-}
-
-static QVector<EGLint> createConfigAttributesFromFormat(const QSurfaceFormat &format)
-{
- int redSize = format.redBufferSize();
- int greenSize = format.greenBufferSize();
- int blueSize = format.blueBufferSize();
- int alphaSize = format.alphaBufferSize();
- int depthSize = format.depthBufferSize();
- int stencilSize = format.stencilBufferSize();
- int sampleCount = format.samples();
-
- QVector<EGLint> configAttributes;
- configAttributes.reserve(16);
-
- configAttributes.append(EGL_RED_SIZE);
- configAttributes.append(redSize > 0 ? redSize : 0);
-
- configAttributes.append(EGL_GREEN_SIZE);
- configAttributes.append(greenSize > 0 ? greenSize : 0);
-
- configAttributes.append(EGL_BLUE_SIZE);
- configAttributes.append(blueSize > 0 ? blueSize : 0);
-
- configAttributes.append(EGL_ALPHA_SIZE);
- configAttributes.append(alphaSize > 0 ? alphaSize : 0);
-
- configAttributes.append(EGL_DEPTH_SIZE);
- configAttributes.append(depthSize > 0 ? depthSize : 0);
-
- configAttributes.append(EGL_STENCIL_SIZE);
- configAttributes.append(stencilSize > 0 ? stencilSize : 0);
-
- configAttributes.append(EGL_SAMPLES);
- configAttributes.append(sampleCount > 0 ? sampleCount : 0);
-
- configAttributes.append(EGL_SAMPLE_BUFFERS);
- configAttributes.append(sampleCount > 0);
-
- return configAttributes;
-}
-
-static bool reduceConfigAttributes(QVector<EGLint> *configAttributes)
-{
- int i = -1;
-
- i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
- if (i >= 0) {
- configAttributes->remove(i,2);
- }
-
- i = configAttributes->indexOf(EGL_BUFFER_SIZE);
- if (i >= 0) {
- if (configAttributes->at(i+1) == 16) {
- configAttributes->remove(i,2);
- return true;
- }
- }
-
- i = configAttributes->indexOf(EGL_SAMPLES);
- if (i >= 0) {
- EGLint value = configAttributes->value(i+1, 0);
- if (value > 1)
- configAttributes->replace(i+1, qMin(EGLint(16), value / 2));
- else
- configAttributes->remove(i, 2);
- return true;
- }
-
- i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS);
- if (i >= 0) {
- configAttributes->remove(i,2);
- return true;
- }
-
- i = configAttributes->indexOf(EGL_ALPHA_SIZE);
- if (i >= 0) {
- configAttributes->remove(i,2);
-#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
- i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA);
- if (i >= 0) {
- configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB);
- configAttributes->replace(i+1,true);
-
- }
-#endif
- return true;
- }
-
- i = configAttributes->indexOf(EGL_STENCIL_SIZE);
- if (i >= 0) {
- if (configAttributes->at(i + 1) > 1)
- configAttributes->replace(i + 1, 1);
- else
- configAttributes->remove(i, 2);
- return true;
- }
-
- i = configAttributes->indexOf(EGL_DEPTH_SIZE);
- if (i >= 0) {
- if (configAttributes->at(i + 1) > 1)
- configAttributes->replace(i + 1, 1);
- else
- configAttributes->remove(i, 2);
- return true;
- }
-#ifdef EGL_BIND_TO_TEXTURE_RGB
- i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB);
- if (i >= 0) {
- configAttributes->remove(i,2);
- return true;
- }
-#endif
-
- return false;
-}
-
-EGLConfig QWindowsEGLContext::chooseConfig(const QSurfaceFormat &format)
-{
- QVector<EGLint> configureAttributes = createConfigAttributesFromFormat(format);
- configureAttributes.append(EGL_SURFACE_TYPE);
- configureAttributes.append(EGL_WINDOW_BIT);
- configureAttributes.append(EGL_RENDERABLE_TYPE);
- configureAttributes.append(EGL_OPENGL_ES2_BIT);
- configureAttributes.append(EGL_NONE);
-
- EGLDisplay display = m_staticContext->display();
- EGLConfig cfg = nullptr;
- do {
- // Get the number of matching configurations for this set of properties.
- EGLint matching = 0;
- if (!QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), nullptr, 0, &matching) || !matching)
- continue;
-
- // Fetch all of the matching configurations and find the
- // first that matches the pixel format we wanted.
- int i = configureAttributes.indexOf(EGL_RED_SIZE);
- int confAttrRed = configureAttributes.at(i+1);
- i = configureAttributes.indexOf(EGL_GREEN_SIZE);
- int confAttrGreen = configureAttributes.at(i+1);
- i = configureAttributes.indexOf(EGL_BLUE_SIZE);
- int confAttrBlue = configureAttributes.at(i+1);
- i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
- int confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);
-
- QVector<EGLConfig> configs(matching);
- QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), configs.data(), configs.size(), &matching);
- if (!cfg && matching > 0)
- cfg = configs.constFirst();
-
- EGLint red = 0;
- EGLint green = 0;
- EGLint blue = 0;
- EGLint alpha = 0;
- for (const EGLConfig &config : configs) {
- if (confAttrRed)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red);
- if (confAttrGreen)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &green);
- if (confAttrBlue)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blue);
- if (confAttrAlpha)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alpha);
-
- if (red == confAttrRed && green == confAttrGreen
- && blue == confAttrBlue && alpha == confAttrAlpha)
- return config;
- }
- } while (reduceConfigAttributes(&configureAttributes));
-
- if (!cfg)
- qWarning("Cannot find EGLConfig, returning null config");
-
- return cfg;
-}
-
-QT_END_NAMESPACE