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.cpp814
1 files changed, 786 insertions, 28 deletions
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index d5ca06bb3f..6ceddf865c 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -46,23 +46,282 @@
#include <QtCore/QDebug>
#include <QtGui/QOpenGLContext>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-
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.
+ 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
\ingroup qt-lighthouse-win
*/
+QWindowsLibEGL QWindowsEGLStaticContext::libEGL;
+QWindowsLibGLESv2 QWindowsEGLStaticContext::libGLESv2;
+
+#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 += QLatin1Char('@') + QString::number(argSize);
+ argSize = argSize < 0 ? 0 : argSize + 4;
+ proc = (void *) ::GetProcAddress(lib, nameStr.toLatin1().constData());
+ }
+ return proc;
+}
+#else
+static void *resolveFunc(HMODULE lib, const char *name)
+{
+# ifndef Q_OS_WINCE
+ return (void *) ::GetProcAddress(lib, name);
+# else
+ return (void *) ::GetProcAddress(lib, (const wchar_t *) QString::fromLatin1(name).utf16());
+# endif // Q_OS_WINCE
+}
+#endif // Q_CC_MINGW
+
+void *QWindowsLibEGL::resolve(const char *name)
+{
+ void *proc = m_lib ? resolveFunc(m_lib, name) : 0;
+ if (!proc)
+ qErrnoWarning(::GetLastError(), "Failed to resolve EGL function %s", name);
+
+ return proc;
+}
+
+bool QWindowsLibEGL::init()
+{
+#ifdef QT_DEBUG
+ const char dllName[] = "libEGLd.dll";
+#else
+ const char dllName[] = "libEGL.dll";
+#endif
+
+ qCDebug(lcQpaGl) << "Qt: Using EGL from" << dllName;
+
+ m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16());
+ if (!m_lib) {
+ qErrnoWarning(::GetLastError(), "Failed to load %s", dllName);
+ return false;
+ }
+
+ eglGetError = reinterpret_cast<EGLint (EGLAPIENTRY *)(void)>(resolve("eglGetError"));
+ eglGetDisplay = reinterpret_cast<EGLDisplay (EGLAPIENTRY *)(EGLNativeDisplayType)>(resolve("eglGetDisplay"));
+ eglInitialize = reinterpret_cast<EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLint *, EGLint *)>(resolve("eglInitialize"));
+ eglTerminate = reinterpret_cast<EGLBoolean (EGLAPIENTRY *)(EGLDisplay)>(resolve("eglTerminate"));
+ eglChooseConfig = reinterpret_cast<EGLBoolean (EGLAPIENTRY *)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)>(resolve("eglChooseConfig"));
+ eglGetConfigAttrib = reinterpret_cast<EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLint, EGLint *)>(resolve("eglGetConfigAttrib"));
+ eglCreateWindowSurface = reinterpret_cast<EGLSurface (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLNativeWindowType, const EGLint *)>(resolve("eglCreateWindowSurface"));
+ eglCreatePbufferSurface = reinterpret_cast<EGLSurface (EGLAPIENTRY *)(EGLDisplay , EGLConfig, const EGLint *)>(resolve("eglCreatePbufferSurface"));
+ eglDestroySurface = reinterpret_cast<EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface )>(resolve("eglDestroySurface"));
+ eglBindAPI = reinterpret_cast<EGLBoolean (EGLAPIENTRY * )(EGLenum )>(resolve("eglBindAPI"));
+ eglSwapInterval = reinterpret_cast<EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLint )>(resolve("eglSwapInterval"));
+ eglCreateContext = reinterpret_cast<EGLContext (EGLAPIENTRY *)(EGLDisplay , EGLConfig , EGLContext , const EGLint *)>(resolve("eglCreateContext"));
+ eglDestroyContext = reinterpret_cast<EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLContext)>(resolve("eglDestroyContext"));
+ eglMakeCurrent = reinterpret_cast<EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface , EGLSurface , EGLContext )>(resolve("eglMakeCurrent"));
+ eglGetCurrentContext = reinterpret_cast<EGLContext (EGLAPIENTRY *)(void)>(resolve("eglGetCurrentContext"));
+ eglGetCurrentSurface = reinterpret_cast<EGLSurface (EGLAPIENTRY *)(EGLint )>(resolve("eglGetCurrentSurface"));
+ eglGetCurrentDisplay = reinterpret_cast<EGLDisplay (EGLAPIENTRY *)(void)>(resolve("eglGetCurrentDisplay"));
+ eglSwapBuffers = reinterpret_cast<EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)>(resolve("eglSwapBuffers"));
+ eglGetProcAddress = reinterpret_cast<__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)>(resolve("eglGetProcAddress"));
+
+ return eglGetError && eglGetDisplay && eglInitialize;
+}
+
+void *QWindowsLibGLESv2::resolve(const char *name)
+{
+ void *proc = m_lib ? resolveFunc(m_lib, name) : 0;
+ if (!proc)
+ qWarning() << "Failed to resolve OpenGL ES function" << name;
+
+ return proc;
+}
+
+bool QWindowsLibGLESv2::init()
+{
+#ifdef QT_DEBUG
+ const char dllName[] = "libGLESv2d.dll";
+#else
+ const char dllName[] = "libGLESv2.dll";
+#endif
+
+ qCDebug(lcQpaGl) << "Qt: Using OpenGL ES 2.0 from" << dllName;
+
+ m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16());
+ if (!m_lib) {
+ qErrnoWarning(::GetLastError(), "Failed to load %s", dllName);
+ return false;
+ }
+
+ glBindTexture = reinterpret_cast<void (APIENTRY *)(GLenum , GLuint )>(resolve("glBindTexture"));
+ glBlendFunc = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum )>(resolve("glBlendFunc"));
+ glClear = reinterpret_cast<void (APIENTRY *)(GLbitfield )>(resolve("glClear"));
+ glClearColor = reinterpret_cast<void (APIENTRY *)(GLfloat , GLfloat , GLfloat , GLfloat )>(resolve("glClearColor"));
+ glClearStencil = reinterpret_cast<void (APIENTRY *)(GLint )>(resolve("glClearStencil"));
+ glColorMask = reinterpret_cast<void (APIENTRY *)(GLboolean , GLboolean , GLboolean , GLboolean )>(resolve("glColorMask"));
+ glCopyTexImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLenum , GLint , GLint , GLsizei , GLsizei , GLint )>(resolve("glCopyTexImage2D"));
+ glCopyTexSubImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLint , GLint , GLsizei , GLsizei )>(resolve("glCopyTexSubImage2D"));
+ glCullFace = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glCullFace"));
+ glDeleteTextures = reinterpret_cast<void (APIENTRY *)(GLsizei , const GLuint *)>(resolve("glDeleteTextures"));
+ glDepthFunc = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glDepthFunc"));
+ glDepthMask = reinterpret_cast<void (APIENTRY *)(GLboolean )>(resolve("glDepthMask"));
+ glDisable = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glDisable"));
+ glDrawArrays = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLsizei )>(resolve("glDrawArrays"));
+ glDrawElements = reinterpret_cast<void (APIENTRY *)(GLenum , GLsizei , GLenum , const GLvoid *)>(resolve("glDrawElements"));
+ glEnable = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glEnable"));
+ glFinish = reinterpret_cast<void (APIENTRY *)()>(resolve("glFinish"));
+ glFlush = reinterpret_cast<void (APIENTRY *)()>(resolve("glFlush"));
+ glFrontFace = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glFrontFace"));
+ glGenTextures = reinterpret_cast<void (APIENTRY *)(GLsizei , GLuint *)>(resolve("glGenTextures"));
+ glGetBooleanv = reinterpret_cast<void (APIENTRY *)(GLenum , GLboolean *)>(resolve("glGetBooleanv"));
+ glGetError = reinterpret_cast<GLenum (APIENTRY *)()>(resolve("glGetError"));
+ glGetFloatv = reinterpret_cast<void (APIENTRY *)(GLenum , GLfloat *)>(resolve("glGetFloatv"));
+ glGetIntegerv = reinterpret_cast<void (APIENTRY *)(GLenum , GLint *)>(resolve("glGetIntegerv"));
+ glGetString = reinterpret_cast<const GLubyte * (APIENTRY *)(GLenum )>(resolve("glGetString"));
+ glGetTexParameterfv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLfloat *)>(resolve("glGetTexParameterfv"));
+ glGetTexParameteriv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint *)>(resolve("glGetTexParameteriv"));
+ glHint = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum )>(resolve("glHint"));
+ glIsEnabled = reinterpret_cast<GLboolean (APIENTRY *)(GLenum )>(resolve("glIsEnabled"));
+ glIsTexture = reinterpret_cast<GLboolean (APIENTRY *)(GLuint )>(resolve("glIsTexture"));
+ glLineWidth = reinterpret_cast<void (APIENTRY *)(GLfloat )>(resolve("glLineWidth"));
+ glPixelStorei = reinterpret_cast<void (APIENTRY *)(GLenum , GLint )>(resolve("glPixelStorei"));
+ glPolygonOffset = reinterpret_cast<void (APIENTRY *)(GLfloat , GLfloat )>(resolve("glPolygonOffset"));
+ glReadPixels = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , GLvoid *)>(resolve("glReadPixels"));
+ glScissor = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )>(resolve("glScissor"));
+ glStencilFunc = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLuint )>(resolve("glStencilFunc"));
+ glStencilMask = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glStencilMask"));
+ glStencilOp = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLenum )>(resolve("glStencilOp"));
+ glTexImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(resolve("glTexImage2D"));
+ glTexParameterf = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLfloat )>(resolve("glTexParameterf"));
+ glTexParameterfv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , const GLfloat *)>(resolve("glTexParameterfv"));
+ glTexParameteri = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint )>(resolve("glTexParameteri"));
+ glTexParameteriv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , const GLint *)>(resolve("glTexParameteriv"));
+ glTexSubImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(resolve("glTexSubImage2D"));
+ glViewport = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )>(resolve("glViewport"));
+
+ glActiveTexture = reinterpret_cast<void (APIENTRY *)(GLenum)>(resolve("glActiveTexture"));
+ glAttachShader = reinterpret_cast<void (APIENTRY *)(GLuint , GLuint )>(resolve("glAttachShader"));
+ glBindAttribLocation = reinterpret_cast<void (APIENTRY *)(GLuint , GLuint , const GLchar* )>(resolve("glBindAttribLocation"));
+ glBindBuffer = reinterpret_cast<void (APIENTRY *)(GLenum , GLuint )>(resolve("glBindBuffer"));
+ glBindFramebuffer = reinterpret_cast<void (APIENTRY *)(GLenum , GLuint )>(resolve("glBindFramebuffer"));
+ glBindRenderbuffer = reinterpret_cast<void (APIENTRY *)(GLenum , GLuint )>(resolve("glBindRenderbuffer"));
+ glBlendColor = reinterpret_cast<void (APIENTRY *)(GLclampf , GLclampf , GLclampf , GLclampf )>(resolve("glBlendColor"));
+ glBlendEquation = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glBlendEquation"));
+ glBlendEquationSeparate = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum )>(resolve("glBlendEquationSeparate"));
+ glBlendFuncSeparate = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLenum , GLenum )>(resolve("glBlendFuncSeparate"));
+ glBufferData = reinterpret_cast<void (APIENTRY *)(GLenum , qopengl_GLsizeiptr , const GLvoid* , GLenum )>(resolve("glBufferData"));
+ glBufferSubData = reinterpret_cast<void (APIENTRY *)(GLenum , qopengl_GLintptr , qopengl_GLsizeiptr , const GLvoid* )>(resolve("glBufferSubData"));
+ glCheckFramebufferStatus = reinterpret_cast<GLenum (APIENTRY *)(GLenum )>(resolve("glCheckFramebufferStatus"));
+ glCompileShader = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glCompileShader"));
+ glCompressedTexImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLenum , GLsizei , GLsizei, GLint, GLsizei, const GLvoid* )>(resolve("glCompressedTexImage2D"));
+ glCompressedTexSubImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid* )>(resolve("glCompressedTexSubImage2D"));
+ glCreateProgram = reinterpret_cast<GLuint (APIENTRY *)(void)>(resolve("glCreateProgram"));
+ glCreateShader = reinterpret_cast<GLuint (APIENTRY *)(GLenum )>(resolve("glCreateShader"));
+ glDeleteBuffers = reinterpret_cast<void (APIENTRY *)(GLsizei , const GLuint*)>(resolve("glDeleteBuffers"));
+ glDeleteFramebuffers = reinterpret_cast<void (APIENTRY *)(GLsizei , const GLuint* )>(resolve("glDeleteFramebuffers"));
+ glDeleteProgram = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glDeleteProgram"));
+ glDeleteRenderbuffers = reinterpret_cast<void (APIENTRY *)(GLsizei , const GLuint* )>(resolve("glDeleteRenderbuffers"));
+ glDeleteShader = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glDeleteShader"));
+ glDetachShader = reinterpret_cast<void (APIENTRY *)(GLuint , GLuint )>(resolve("glDetachShader"));
+ glDisableVertexAttribArray = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glDisableVertexAttribArray"));
+ glEnableVertexAttribArray = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glEnableVertexAttribArray"));
+ glFramebufferRenderbuffer = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLenum , GLuint )>(resolve("glFramebufferRenderbuffer"));
+ glFramebufferTexture2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLenum , GLuint , GLint )>(resolve("glFramebufferTexture2D"));
+ glGenBuffers = reinterpret_cast<void (APIENTRY *)(GLsizei , GLuint* )>(resolve("glGenBuffers"));
+ glGenerateMipmap = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glGenerateMipmap"));
+ glGenFramebuffers = reinterpret_cast<void (APIENTRY *)(GLsizei , GLuint* )>(resolve("glGenFramebuffers"));
+ glGenRenderbuffers = reinterpret_cast<void (APIENTRY *)(GLsizei , GLuint* )>(resolve("glGenRenderbuffers"));
+ glGetActiveAttrib = reinterpret_cast<void (APIENTRY *)(GLuint , GLuint , GLsizei , GLsizei* , GLint* , GLenum* , GLchar* )>(resolve("glGetActiveAttrib"));
+ glGetActiveUniform = reinterpret_cast<void (APIENTRY *)(GLuint , GLuint , GLsizei , GLsizei* , GLint* , GLenum* , GLchar* )>(resolve("glGetActiveUniform"));
+ glGetAttachedShaders = reinterpret_cast<void (APIENTRY *)(GLuint , GLsizei , GLsizei*, GLuint* )>(resolve("glGetAttachedShaders"));
+ glGetAttribLocation = reinterpret_cast<int (APIENTRY *)(GLuint , const GLchar* )>(resolve("glGetAttribLocation"));
+ glGetBufferParameteriv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint* )>(resolve("glGetBufferParameteriv"));
+ glGetFramebufferAttachmentParameteriv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum, GLenum , GLint* )>(resolve("glGetFramebufferAttachmentParameteriv"));
+ glGetProgramiv = reinterpret_cast<void (APIENTRY *)(GLuint , GLenum , GLint* )>(resolve("glGetProgramiv"));
+ glGetProgramInfoLog = reinterpret_cast<void (APIENTRY *)(GLuint , GLsizei , GLsizei* , GLchar* )>(resolve("glGetProgramInfoLog"));
+ glGetRenderbufferParameteriv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint* )>(resolve("glGetRenderbufferParameteriv"));
+ glGetShaderiv = reinterpret_cast<void (APIENTRY *)(GLuint , GLenum , GLint* )>(resolve("glGetShaderiv"));
+ glGetShaderInfoLog = reinterpret_cast<void (APIENTRY *)(GLuint , GLsizei , GLsizei*, GLchar*)>(resolve("glGetShaderInfoLog"));
+ glGetShaderPrecisionFormat = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint* , GLint* )>(resolve("glGetShaderPrecisionFormat"));
+ glGetShaderSource = reinterpret_cast<void (APIENTRY *)(GLuint , GLsizei , GLsizei* , GLchar* )>(resolve("glGetShaderSource"));
+ glGetUniformfv = reinterpret_cast<void (APIENTRY *)(GLuint , GLint , GLfloat*)>(resolve("glGetUniformfv"));
+ glGetUniformiv = reinterpret_cast<void (APIENTRY *)(GLuint , GLint , GLint*)>(resolve("glGetUniformiv"));
+ glGetUniformLocation = reinterpret_cast<int (APIENTRY *)(GLuint , const GLchar* )>(resolve("glGetUniformLocation"));
+ glGetVertexAttribfv = reinterpret_cast<void (APIENTRY *)(GLuint , GLenum , GLfloat* )>(resolve("glGetVertexAttribfv"));
+ glGetVertexAttribiv = reinterpret_cast<void (APIENTRY *)(GLuint , GLenum , GLint* )>(resolve("glGetVertexAttribiv"));
+ glGetVertexAttribPointerv = reinterpret_cast<void (APIENTRY *)(GLuint , GLenum , GLvoid** pointer)>(resolve("glGetVertexAttribPointerv"));
+ glIsBuffer = reinterpret_cast<GLboolean (APIENTRY *)(GLuint )>(resolve("glIsBuffer"));
+ glIsFramebuffer = reinterpret_cast<GLboolean (APIENTRY *)(GLuint )>(resolve("glIsFramebuffer"));
+ glIsProgram = reinterpret_cast<GLboolean (APIENTRY *)(GLuint )>(resolve("glIsProgram"));
+ glIsRenderbuffer = reinterpret_cast<GLboolean (APIENTRY *)(GLuint )>(resolve("glIsRenderbuffer"));
+ glIsShader = reinterpret_cast<GLboolean (APIENTRY *)(GLuint )>(resolve("glIsShader"));
+ glLinkProgram = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glLinkProgram"));
+ glReleaseShaderCompiler = reinterpret_cast<void (APIENTRY *)(void)>(resolve("glReleaseShaderCompiler"));
+ glRenderbufferStorage = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLsizei , GLsizei )>(resolve("glRenderbufferStorage"));
+ glSampleCoverage = reinterpret_cast<void (APIENTRY *)(GLclampf , GLboolean )>(resolve("glSampleCoverage"));
+ glShaderBinary = reinterpret_cast<void (APIENTRY *)(GLsizei , const GLuint*, GLenum , const GLvoid* , GLsizei )>(resolve("glShaderBinary"));
+ glShaderSource = reinterpret_cast<void (APIENTRY *)(GLuint , GLsizei , const GLchar* *, const GLint* )>(resolve("glShaderSource"));
+ glStencilFuncSeparate = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint , GLuint )>(resolve("glStencilFuncSeparate"));
+ glStencilMaskSeparate = reinterpret_cast<void (APIENTRY *)(GLenum , GLuint )>(resolve("glStencilMaskSeparate"));
+ glStencilOpSeparate = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLenum , GLenum )>(resolve("glStencilOpSeparate"));
+ glUniform1f = reinterpret_cast<void (APIENTRY *)(GLint , GLfloat )>(resolve("glUniform1f"));
+ glUniform1fv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , const GLfloat* )>(resolve("glUniform1fv"));
+ glUniform1i = reinterpret_cast<void (APIENTRY *)(GLint , GLint )>(resolve("glUniform1i"));
+ glUniform1iv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , const GLint* )>(resolve("glUniform1iv"));
+ glUniform2f = reinterpret_cast<void (APIENTRY *)(GLint , GLfloat , GLfloat )>(resolve("glUniform2f"));
+ glUniform2fv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , const GLfloat* )>(resolve("glUniform2fv"));
+ glUniform2i = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLint )>(resolve("glUniform2i"));
+ glUniform2iv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , const GLint* )>(resolve("glUniform2iv"));
+ glUniform3f = reinterpret_cast<void (APIENTRY *)(GLint , GLfloat , GLfloat , GLfloat )>(resolve("glUniform3f"));
+ glUniform3fv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , const GLfloat* )>(resolve("glUniform3fv"));
+ glUniform3i = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLint , GLint )>(resolve("glUniform3i"));
+ glUniform3iv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , const GLint* )>(resolve("glUniform3iv"));
+ glUniform4f = reinterpret_cast<void (APIENTRY *)(GLint , GLfloat , GLfloat , GLfloat , GLfloat )>(resolve("glUniform4f"));
+ glUniform4fv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , const GLfloat* )>(resolve("glUniform4fv"));
+ glUniform4i = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLint , GLint , GLint )>(resolve("glUniform4i"));
+ glUniform4iv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , const GLint* )>(resolve("glUniform4iv"));
+ glUniformMatrix2fv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )>(resolve("glUniformMatrix2fv"));
+ glUniformMatrix3fv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )>(resolve("glUniformMatrix3fv"));
+ glUniformMatrix4fv = reinterpret_cast<void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )>(resolve("glUniformMatrix4fv"));
+ glUseProgram = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glUseProgram"));
+ glValidateProgram = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glValidateProgram"));
+ glVertexAttrib1f = reinterpret_cast<void (APIENTRY *)(GLuint , GLfloat )>(resolve("glVertexAttrib1f"));
+ glVertexAttrib1fv = reinterpret_cast<void (APIENTRY *)(GLuint , const GLfloat* )>(resolve("glVertexAttrib1fv"));
+ glVertexAttrib2f = reinterpret_cast<void (APIENTRY *)(GLuint , GLfloat , GLfloat )>(resolve("glVertexAttrib2f"));
+ glVertexAttrib2fv = reinterpret_cast<void (APIENTRY *)(GLuint , const GLfloat* )>(resolve("glVertexAttrib2fv"));
+ glVertexAttrib3f = reinterpret_cast<void (APIENTRY *)(GLuint , GLfloat , GLfloat , GLfloat )>(resolve("glVertexAttrib3f"));
+ glVertexAttrib3fv = reinterpret_cast<void (APIENTRY *)(GLuint , const GLfloat* )>(resolve("glVertexAttrib3fv"));
+ glVertexAttrib4f = reinterpret_cast<void (APIENTRY *)(GLuint , GLfloat , GLfloat , GLfloat , GLfloat )>(resolve("glVertexAttrib4f"));
+ glVertexAttrib4fv = reinterpret_cast<void (APIENTRY *)(GLuint , const GLfloat* )>(resolve("glVertexAttrib4fv"));
+ glVertexAttribPointer = reinterpret_cast<void (APIENTRY *)(GLuint , GLint, GLenum, GLboolean, GLsizei, const GLvoid* )>(resolve("glVertexAttribPointer"));
+
+ glClearDepthf = reinterpret_cast<void (APIENTRY *)(GLclampf )>(resolve("glClearDepthf"));
+ glDepthRangef = reinterpret_cast<void (APIENTRY *)(GLclampf , GLclampf )>(resolve("glDepthRangef"));
+
+ return glBindTexture && glCreateShader && glClearDepthf;
+}
+
QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display, int version)
: m_display(display), m_version(version)
{
@@ -76,7 +335,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
return 0;
}
- EGLDisplay display = eglGetDisplay((EGLNativeDisplayType)dc);
+ if (!libEGL.init()) {
+ qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO);
+ return 0;
+ }
+ if (!libGLESv2.init()) {
+ qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO);
+ return 0;
+ }
+
+ EGLDisplay display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc);
if (!display) {
qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO);
return 0;
@@ -84,9 +352,11 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
EGLint major;
EGLint minor;
- if (!eglInitialize(display, &major, &minor)) {
- qWarning("%s: Could not initialize egl display: error %d\n",
- Q_FUNC_INFO, eglGetError());
+ if (!libEGL.eglInitialize(display, &major, &minor)) {
+ int err = libEGL.eglGetError();
+ qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err);
+ if (err == 0x3001)
+ qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", Q_FUNC_INFO);
return 0;
}
@@ -97,7 +367,70 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
QWindowsEGLStaticContext::~QWindowsEGLStaticContext()
{
qCDebug(lcQpaGl) << __FUNCTION__ << "Releasing EGL display " << m_display;
- eglTerminate(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)
+{
+ EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, (EGLConfig) nativeConfig,
+ (EGLNativeWindowType) nativeWindow, 0);
+ if (surface == EGL_NO_SURFACE)
+ qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, libEGL.eglGetError());
+
+ return surface;
+}
+
+void QWindowsEGLStaticContext::destroyWindowSurface(void *nativeSurface)
+{
+ libEGL.eglDestroySurface(m_display, (EGLSurface) 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;
}
/*!
@@ -121,40 +454,465 @@ QWindowsEGLStaticContext::~QWindowsEGLStaticContext()
\ingroup qt-lighthouse-win
*/
-QWindowsEGLContext::QWindowsEGLContext(const QWindowsEGLStaticContextPtr &staticContext,
+QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
const QSurfaceFormat &format,
QPlatformOpenGLContext *share)
- : QEGLPlatformContext(format, share, staticContext->display())
- , m_staticContext(staticContext)
+ : m_staticContext(staticContext)
+ , m_eglDisplay(staticContext->display())
+ , m_api(EGL_OPENGL_ES_API)
+ , m_swapInterval(-1)
{
+ 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 : 0;
+
+ QVector<EGLint> contextAttrs;
+ contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
+ contextAttrs.append(m_format.majorVersion());
+ 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 = 0;
+ m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, 0, contextAttrs.constData());
+ }
+
+ if (m_eglContext == EGL_NO_CONTEXT) {
+ qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ 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;
+
+ 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(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
+ 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::hasThreadedOpenGLCapability()
+bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
{
- return false;
+ Q_ASSERT(surface->surface()->supportsOpenGL());
+
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+
+ QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
+ EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig));
+ Q_ASSERT(eglSurface);
+
+ // 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 {
+ qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ }
+
+ return ok;
}
-EGLSurface QWindowsEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
+void QWindowsEGLContext::doneCurrent()
{
- const QWindowsWindow *window = static_cast<const QWindowsWindow *>(surface);
- return window->eglSurfaceHandle();
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+ bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (!ok)
+ qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
}
-bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
+void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
{
- bool ok = false;
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
- if (EGLSurface eglSurface = window->ensureEglSurfaceHandle(m_staticContext, eglConfig())) {
- ok = eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, eglContext());
- if (!ok)
- qWarning("%s: eglMakeCurrent() failed, eglError: 0x%x, this: %p \n",
- Q_FUNC_INFO, eglGetError(), this);
+ EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig));
+ Q_ASSERT(eglSurface);
+
+ bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
+ if (!ok)
+ qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+}
+
+QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &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().
+ static struct StdFunc {
+ const char *name;
+ void *func;
+ } standardFuncs[] = {
+ { "glBindTexture", (void *) QWindowsEGLStaticContext::libGLESv2.glBindTexture },
+ { "glBlendFunc", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendFunc },
+ { "glClear", (void *) QWindowsEGLStaticContext::libGLESv2.glClear },
+ { "glClearColor", (void *) QWindowsEGLStaticContext::libGLESv2.glClearColor },
+ { "glClearStencil", (void *) QWindowsEGLStaticContext::libGLESv2.glClearStencil },
+ { "glColorMask", (void *) QWindowsEGLStaticContext::libGLESv2.glColorMask },
+ { "glCopyTexImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCopyTexImage2D },
+ { "glCopyTexSubImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCopyTexSubImage2D },
+ { "glCullFace", (void *) QWindowsEGLStaticContext::libGLESv2.glCullFace },
+ { "glDeleteTextures", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteTextures },
+ { "glDepthFunc", (void *) QWindowsEGLStaticContext::libGLESv2.glDepthFunc },
+ { "glDepthMask", (void *) QWindowsEGLStaticContext::libGLESv2.glDepthMask },
+ { "glDisable", (void *) QWindowsEGLStaticContext::libGLESv2.glDisable },
+ { "glDrawArrays", (void *) QWindowsEGLStaticContext::libGLESv2.glDrawArrays },
+ { "glDrawElements", (void *) QWindowsEGLStaticContext::libGLESv2.glDrawElements },
+ { "glEnable", (void *) QWindowsEGLStaticContext::libGLESv2.glEnable },
+ { "glFinish", (void *) QWindowsEGLStaticContext::libGLESv2.glFinish },
+ { "glFlush", (void *) QWindowsEGLStaticContext::libGLESv2.glFlush },
+ { "glFrontFace", (void *) QWindowsEGLStaticContext::libGLESv2.glFrontFace },
+ { "glGenTextures", (void *) QWindowsEGLStaticContext::libGLESv2.glGenTextures },
+ { "glGetBooleanv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetBooleanv },
+ { "glGetError", (void *) QWindowsEGLStaticContext::libGLESv2.glGetError },
+ { "glGetFloatv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetFloatv },
+ { "glGetIntegerv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetIntegerv },
+ { "glGetString", (void *) QWindowsEGLStaticContext::libGLESv2.glGetString },
+ { "glGetTexParameterfv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetTexParameterfv },
+ { "glGetTexParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetTexParameteriv },
+ { "glHint", (void *) QWindowsEGLStaticContext::libGLESv2.glHint },
+ { "glIsEnabled", (void *) QWindowsEGLStaticContext::libGLESv2.glIsEnabled },
+ { "glIsTexture", (void *) QWindowsEGLStaticContext::libGLESv2.glIsTexture },
+ { "glLineWidth", (void *) QWindowsEGLStaticContext::libGLESv2.glLineWidth },
+ { "glPixelStorei", (void *) QWindowsEGLStaticContext::libGLESv2.glPixelStorei },
+ { "glPolygonOffset", (void *) QWindowsEGLStaticContext::libGLESv2.glPolygonOffset },
+ { "glReadPixels", (void *) QWindowsEGLStaticContext::libGLESv2.glReadPixels },
+ { "glScissor", (void *) QWindowsEGLStaticContext::libGLESv2.glScissor },
+ { "glStencilFunc", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilFunc },
+ { "glStencilMask", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilMask },
+ { "glStencilOp", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilOp },
+ { "glTexImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glTexImage2D },
+ { "glTexParameterf", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameterf },
+ { "glTexParameterfv", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameterfv },
+ { "glTexParameteri", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameteri },
+ { "glTexParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameteriv },
+ { "glTexSubImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glTexSubImage2D },
+ { "glViewport", (void *) QWindowsEGLStaticContext::libGLESv2.glViewport },
+
+ { "glActiveTexture", (void *) QWindowsEGLStaticContext::libGLESv2.glActiveTexture },
+ { "glAttachShader", (void *) QWindowsEGLStaticContext::libGLESv2.glAttachShader },
+ { "glBindAttribLocation", (void *) QWindowsEGLStaticContext::libGLESv2.glBindAttribLocation },
+ { "glBindBuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glBindBuffer },
+ { "glBindFramebuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glBindFramebuffer },
+ { "glBindRenderbuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glBindRenderbuffer },
+ { "glBlendColor", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendColor },
+ { "glBlendEquation", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendEquation },
+ { "glBlendEquationSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendEquationSeparate },
+ { "glBlendFuncSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendFuncSeparate },
+ { "glBufferData", (void *) QWindowsEGLStaticContext::libGLESv2.glBufferData },
+ { "glBufferSubData", (void *) QWindowsEGLStaticContext::libGLESv2.glBufferSubData },
+ { "glCheckFramebufferStatus", (void *) QWindowsEGLStaticContext::libGLESv2.glCheckFramebufferStatus },
+ { "glCompileShader", (void *) QWindowsEGLStaticContext::libGLESv2.glCompileShader },
+ { "glCompressedTexImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCompressedTexImage2D },
+ { "glCompressedTexSubImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCompressedTexSubImage2D },
+ { "glCreateProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glCreateProgram },
+ { "glCreateShader", (void *) QWindowsEGLStaticContext::libGLESv2.glCreateShader },
+ { "glDeleteBuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteBuffers },
+ { "glDeleteFramebuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteFramebuffers },
+ { "glDeleteProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteProgram },
+ { "glDeleteRenderbuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteRenderbuffers },
+ { "glDeleteShader", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteShader },
+ { "glDetachShader", (void *) QWindowsEGLStaticContext::libGLESv2.glDetachShader },
+ { "glDisableVertexAttribArray", (void *) QWindowsEGLStaticContext::libGLESv2.glDisableVertexAttribArray },
+ { "glEnableVertexAttribArray", (void *) QWindowsEGLStaticContext::libGLESv2.glEnableVertexAttribArray },
+ { "glFramebufferRenderbuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glFramebufferRenderbuffer },
+ { "glFramebufferTexture2D", (void *) QWindowsEGLStaticContext::libGLESv2.glFramebufferTexture2D },
+ { "glGenBuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glGenBuffers },
+ { "glGenerateMipmap", (void *) QWindowsEGLStaticContext::libGLESv2.glGenerateMipmap },
+ { "glGenFramebuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glGenFramebuffers },
+ { "glGenRenderbuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glGenRenderbuffers },
+ { "glGetActiveAttrib", (void *) QWindowsEGLStaticContext::libGLESv2.glGetActiveAttrib },
+ { "glGetActiveUniform", (void *) QWindowsEGLStaticContext::libGLESv2.glGetActiveUniform },
+ { "glGetAttachedShaders", (void *) QWindowsEGLStaticContext::libGLESv2.glGetAttachedShaders },
+ { "glGetAttribLocation", (void *) QWindowsEGLStaticContext::libGLESv2.glGetAttribLocation },
+ { "glGetBufferParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetBufferParameteriv },
+ { "glGetFramebufferAttachmentParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetFramebufferAttachmentParameteriv },
+ { "glGetProgramiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetProgramiv },
+ { "glGetProgramInfoLog", (void *) QWindowsEGLStaticContext::libGLESv2.glGetProgramInfoLog },
+ { "glGetRenderbufferParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetRenderbufferParameteriv },
+ { "glGetShaderiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderiv },
+ { "glGetShaderInfoLog", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderInfoLog },
+ { "glGetShaderPrecisionFormat", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderPrecisionFormat },
+ { "glGetShaderSource", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderSource },
+ { "glGetUniformfv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetUniformfv },
+ { "glGetUniformiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetUniformiv },
+ { "glGetUniformLocation", (void *) QWindowsEGLStaticContext::libGLESv2.glGetUniformLocation },
+ { "glGetVertexAttribfv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetVertexAttribfv },
+ { "glGetVertexAttribiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetVertexAttribiv },
+ { "glGetVertexAttribPointerv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetVertexAttribPointerv },
+ { "glIsBuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glIsBuffer },
+ { "glIsFramebuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glIsFramebuffer },
+ { "glIsProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glIsProgram },
+ { "glIsRenderbuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glIsRenderbuffer },
+ { "glIsShader", (void *) QWindowsEGLStaticContext::libGLESv2.glIsShader },
+ { "glLinkProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glLinkProgram },
+ { "glReleaseShaderCompiler", (void *) QWindowsEGLStaticContext::libGLESv2.glReleaseShaderCompiler },
+ { "glRenderbufferStorage", (void *) QWindowsEGLStaticContext::libGLESv2.glRenderbufferStorage },
+ { "glSampleCoverage", (void *) QWindowsEGLStaticContext::libGLESv2.glSampleCoverage },
+ { "glShaderBinary", (void *) QWindowsEGLStaticContext::libGLESv2.glShaderBinary },
+ { "glShaderSource", (void *) QWindowsEGLStaticContext::libGLESv2.glShaderSource },
+ { "glStencilFuncSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilFuncSeparate },
+ { "glStencilMaskSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilMaskSeparate },
+ { "glStencilOpSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilOpSeparate },
+ { "glUniform1f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1f },
+ { "glUniform1fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1fv },
+ { "glUniform1i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1i },
+ { "glUniform1iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1iv },
+ { "glUniform2f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2f },
+ { "glUniform2fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2fv },
+ { "glUniform2i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2i },
+ { "glUniform2iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2iv },
+ { "glUniform3f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3f },
+ { "glUniform3fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3fv },
+ { "glUniform3i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3i },
+ { "glUniform3iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3iv },
+ { "glUniform4f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4f },
+ { "glUniform4fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4fv },
+ { "glUniform4i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4i },
+ { "glUniform4iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4iv },
+ { "glUniformMatrix2fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniformMatrix2fv },
+ { "glUniformMatrix3fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniformMatrix3fv },
+ { "glUniformMatrix4fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniformMatrix4fv },
+ { "glUseProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glUseProgram },
+ { "glValidateProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glValidateProgram },
+ { "glVertexAttrib1f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib1f },
+ { "glVertexAttrib1fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib1fv },
+ { "glVertexAttrib2f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib2f },
+ { "glVertexAttrib2fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib2fv },
+ { "glVertexAttrib3f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib3f },
+ { "glVertexAttrib3fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib3fv },
+ { "glVertexAttrib4f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib4f },
+ { "glVertexAttrib4fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib4fv },
+ { "glVertexAttribPointer", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttribPointer },
+
+ { "glClearDepthf", (void *) QWindowsEGLStaticContext::libGLESv2.glClearDepthf },
+ { "glDepthRangef", (void *) QWindowsEGLStaticContext::libGLESv2.glDepthRangef }
+ };
+ for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i)
+ if (procName == standardFuncs[i].name)
+ return reinterpret_cast<QFunctionPointer>(standardFuncs[i].func);
+
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+ QFunctionPointer procAddress = reinterpret_cast<QFunctionPointer>(QWindowsEGLStaticContext::libEGL.eglGetProcAddress(procName.constData()));
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaGl) << __FUNCTION__ << procName << QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() << "returns" << procAddress;
+ if (!procAddress)
+ qWarning("%s: Unable to resolve '%s'", __FUNCTION__, procName.constData());
+ 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);
}
- return ok;
+
+ 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 = 0;
+ do {
+ // Get the number of matching configurations for this set of properties.
+ EGLint matching = 0;
+ if (!QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), 0, 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.first();
+
+ EGLint red = 0;
+ EGLint green = 0;
+ EGLint blue = 0;
+ EGLint alpha = 0;
+ for (int i = 0; i < configs.size(); ++i) {
+ if (confAttrRed)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &red);
+ if (confAttrGreen)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &green);
+ if (confAttrBlue)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &blue);
+ if (confAttrAlpha)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &alpha);
+
+ if (red == confAttrRed && green == confAttrGreen
+ && blue == confAttrBlue && alpha == confAttrAlpha)
+ return configs[i];
+ }
+ } while (reduceConfigAttributes(&configureAttributes));
+
+ if (!cfg)
+ qWarning("Cannot find EGLConfig, returning null config");
+
+ return cfg;
}
QT_END_NAMESPACE