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.cpp829
1 files changed, 801 insertions, 28 deletions
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index d5ca06bb3f..c62875d0ef 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,297 @@
#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;
+
+#ifndef QT_STATIC
+
+#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;
+}
+
+#endif // !QT_STATIC
+
+#ifndef QT_STATIC
+# define RESOLVE(signature, name) signature(resolve( #name ));
+#else
+# define RESOLVE(signature, name) signature(&::name);
+#endif
+
+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;
+
+#ifndef QT_STATIC
+ 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((__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
+
+ return eglGetError && eglGetDisplay && eglInitialize;
+}
+
+#ifndef QT_STATIC
+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;
+}
+#endif // !QT_STATIC
+
+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;
+#ifndef QT_STATIC
+ m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16());
+ if (!m_lib) {
+ qErrnoWarning(::GetLastError(), "Failed to load %s", dllName);
+ return false;
+ }
+#endif // !QT_STATIC
+
+ glBindTexture = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindTexture);
+ glBlendFunc = RESOLVE((void (APIENTRY *)(GLenum , GLenum )), glBlendFunc);
+ glClear = RESOLVE((void (APIENTRY *)(GLbitfield )), glClear);
+ glClearColor = RESOLVE((void (APIENTRY *)(GLfloat , GLfloat , GLfloat , GLfloat )), glClearColor);
+ glClearStencil = RESOLVE((void (APIENTRY *)(GLint )), glClearStencil);
+ glColorMask = RESOLVE((void (APIENTRY *)(GLboolean , GLboolean , GLboolean , GLboolean )), glColorMask);
+ glCopyTexImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLenum , GLint , GLint , GLsizei , GLsizei , GLint )), glCopyTexImage2D);
+ glCopyTexSubImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLint , GLint , GLsizei , GLsizei )), glCopyTexSubImage2D);
+ glCullFace = RESOLVE((void (APIENTRY *)(GLenum )), glCullFace);
+ glDeleteTextures = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint *)), glDeleteTextures);
+ glDepthFunc = RESOLVE((void (APIENTRY *)(GLenum )), glDepthFunc);
+ glDepthMask = RESOLVE((void (APIENTRY *)(GLboolean )), glDepthMask);
+ glDisable = RESOLVE((void (APIENTRY *)(GLenum )), glDisable);
+ glDrawArrays = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLsizei )), glDrawArrays);
+ glDrawElements = RESOLVE((void (APIENTRY *)(GLenum , GLsizei , GLenum , const GLvoid *)), glDrawElements);
+ glEnable = RESOLVE((void (APIENTRY *)(GLenum )), glEnable);
+ glFinish = RESOLVE((void (APIENTRY *)()), glFinish);
+ glFlush = RESOLVE((void (APIENTRY *)()), glFlush);
+ glFrontFace = RESOLVE((void (APIENTRY *)(GLenum )), glFrontFace);
+ glGenTextures = RESOLVE((void (APIENTRY *)(GLsizei , GLuint *)), glGenTextures);
+ glGetBooleanv = RESOLVE((void (APIENTRY *)(GLenum , GLboolean *)), glGetBooleanv);
+ glGetError = RESOLVE((GLenum (APIENTRY *)()), glGetError);
+ glGetFloatv = RESOLVE((void (APIENTRY *)(GLenum , GLfloat *)), glGetFloatv);
+ glGetIntegerv = RESOLVE((void (APIENTRY *)(GLenum , GLint *)), glGetIntegerv);
+ glGetString = RESOLVE((const GLubyte * (APIENTRY *)(GLenum )), glGetString);
+ glGetTexParameterfv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLfloat *)), glGetTexParameterfv);
+ glGetTexParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint *)), glGetTexParameteriv);
+ glHint = RESOLVE((void (APIENTRY *)(GLenum , GLenum )), glHint);
+ glIsEnabled = RESOLVE((GLboolean (APIENTRY *)(GLenum )), glIsEnabled);
+ glIsTexture = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsTexture);
+ glLineWidth = RESOLVE((void (APIENTRY *)(GLfloat )), glLineWidth);
+ glPixelStorei = RESOLVE((void (APIENTRY *)(GLenum , GLint )), glPixelStorei);
+ glPolygonOffset = RESOLVE((void (APIENTRY *)(GLfloat , GLfloat )), glPolygonOffset);
+ glReadPixels = RESOLVE((void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , GLvoid *)), glReadPixels);
+ glScissor = RESOLVE((void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )), glScissor);
+ glStencilFunc = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLuint )), glStencilFunc);
+ glStencilMask = RESOLVE((void (APIENTRY *)(GLuint )), glStencilMask);
+ glStencilOp = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum )), glStencilOp);
+ glTexImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)), glTexImage2D);
+ glTexParameterf = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLfloat )), glTexParameterf);
+ glTexParameterfv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , const GLfloat *)), glTexParameterfv);
+ glTexParameteri = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint )), glTexParameteri);
+ glTexParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , const GLint *)), glTexParameteriv);
+ glTexSubImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)), glTexSubImage2D);
+ glViewport = RESOLVE((void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )), glViewport);
+
+ glActiveTexture = RESOLVE((void (APIENTRY *)(GLenum)), glActiveTexture);
+ glAttachShader = RESOLVE((void (APIENTRY *)(GLuint , GLuint )), glAttachShader);
+ glBindAttribLocation = RESOLVE((void (APIENTRY *)(GLuint , GLuint , const GLchar* )), glBindAttribLocation);
+ glBindBuffer = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindBuffer);
+ glBindFramebuffer = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindFramebuffer);
+ glBindRenderbuffer = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindRenderbuffer);
+ glBlendColor = RESOLVE((void (APIENTRY *)(GLclampf , GLclampf , GLclampf , GLclampf )), glBlendColor);
+ glBlendEquation = RESOLVE((void (APIENTRY *)(GLenum )), glBlendEquation);
+ glBlendEquationSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum )), glBlendEquationSeparate);
+ glBlendFuncSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLenum )), glBlendFuncSeparate);
+ glBufferData = RESOLVE((void (APIENTRY *)(GLenum , qopengl_GLsizeiptr , const GLvoid* , GLenum )), glBufferData);
+ glBufferSubData = RESOLVE((void (APIENTRY *)(GLenum , qopengl_GLintptr , qopengl_GLsizeiptr , const GLvoid* )), glBufferSubData);
+ glCheckFramebufferStatus = RESOLVE((GLenum (APIENTRY *)(GLenum )), glCheckFramebufferStatus);
+ glCompileShader = RESOLVE((void (APIENTRY *)(GLuint )), glCompileShader);
+ glCompressedTexImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLenum , GLsizei , GLsizei, GLint, GLsizei, const GLvoid* )), glCompressedTexImage2D);
+ glCompressedTexSubImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid* )), glCompressedTexSubImage2D);
+ glCreateProgram = RESOLVE((GLuint (APIENTRY *)(void)), glCreateProgram);
+ glCreateShader = RESOLVE((GLuint (APIENTRY *)(GLenum )), glCreateShader);
+ glDeleteBuffers = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint*)), glDeleteBuffers);
+ glDeleteFramebuffers = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint* )), glDeleteFramebuffers);
+ glDeleteProgram = RESOLVE((void (APIENTRY *)(GLuint )), glDeleteProgram);
+ glDeleteRenderbuffers = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint* )), glDeleteRenderbuffers);
+ glDeleteShader = RESOLVE((void (APIENTRY *)(GLuint )), glDeleteShader);
+ glDetachShader = RESOLVE((void (APIENTRY *)(GLuint , GLuint )), glDetachShader);
+ glDisableVertexAttribArray = RESOLVE((void (APIENTRY *)(GLuint )), glDisableVertexAttribArray);
+ glEnableVertexAttribArray = RESOLVE((void (APIENTRY *)(GLuint )), glEnableVertexAttribArray);
+ glFramebufferRenderbuffer = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLuint )), glFramebufferRenderbuffer);
+ glFramebufferTexture2D = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLuint , GLint )), glFramebufferTexture2D);
+ glGenBuffers = RESOLVE((void (APIENTRY *)(GLsizei , GLuint* )), glGenBuffers);
+ glGenerateMipmap = RESOLVE((void (APIENTRY *)(GLenum )), glGenerateMipmap);
+ glGenFramebuffers = RESOLVE((void (APIENTRY *)(GLsizei , GLuint* )), glGenFramebuffers);
+ glGenRenderbuffers = RESOLVE((void (APIENTRY *)(GLsizei , GLuint* )), glGenRenderbuffers);
+ glGetActiveAttrib = RESOLVE((void (APIENTRY *)(GLuint , GLuint , GLsizei , GLsizei* , GLint* , GLenum* , GLchar* )), glGetActiveAttrib);
+ glGetActiveUniform = RESOLVE((void (APIENTRY *)(GLuint , GLuint , GLsizei , GLsizei* , GLint* , GLenum* , GLchar* )), glGetActiveUniform);
+ glGetAttachedShaders = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei*, GLuint* )), glGetAttachedShaders);
+ glGetAttribLocation = RESOLVE((int (APIENTRY *)(GLuint , const GLchar* )), glGetAttribLocation);
+ glGetBufferParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint* )), glGetBufferParameteriv);
+ glGetFramebufferAttachmentParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum, GLenum , GLint* )), glGetFramebufferAttachmentParameteriv);
+ glGetProgramiv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLint* )), glGetProgramiv);
+ glGetProgramInfoLog = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei* , GLchar* )), glGetProgramInfoLog);
+ glGetRenderbufferParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint* )), glGetRenderbufferParameteriv);
+ glGetShaderiv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLint* )), glGetShaderiv);
+ glGetShaderInfoLog = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei*, GLchar*)), glGetShaderInfoLog);
+ glGetShaderPrecisionFormat = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint* , GLint* )), glGetShaderPrecisionFormat);
+ glGetShaderSource = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei* , GLchar* )), glGetShaderSource);
+ glGetUniformfv = RESOLVE((void (APIENTRY *)(GLuint , GLint , GLfloat*)), glGetUniformfv);
+ glGetUniformiv = RESOLVE((void (APIENTRY *)(GLuint , GLint , GLint*)), glGetUniformiv);
+ glGetUniformLocation = RESOLVE((int (APIENTRY *)(GLuint , const GLchar* )), glGetUniformLocation);
+ glGetVertexAttribfv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLfloat* )), glGetVertexAttribfv);
+ glGetVertexAttribiv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLint* )), glGetVertexAttribiv);
+ glGetVertexAttribPointerv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLvoid** pointer)), glGetVertexAttribPointerv);
+ glIsBuffer = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsBuffer);
+ glIsFramebuffer = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsFramebuffer);
+ glIsProgram = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsProgram);
+ glIsRenderbuffer = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsRenderbuffer);
+ glIsShader = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsShader);
+ glLinkProgram = RESOLVE((void (APIENTRY *)(GLuint )), glLinkProgram);
+ glReleaseShaderCompiler = RESOLVE((void (APIENTRY *)(void)), glReleaseShaderCompiler);
+ glRenderbufferStorage = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLsizei , GLsizei )), glRenderbufferStorage);
+ glSampleCoverage = RESOLVE((void (APIENTRY *)(GLclampf , GLboolean )), glSampleCoverage);
+ glShaderBinary = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint*, GLenum , const GLvoid* , GLsizei )), glShaderBinary);
+ glShaderSource = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , const GLchar* *, const GLint* )), glShaderSource);
+ glStencilFuncSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint , GLuint )), glStencilFuncSeparate);
+ glStencilMaskSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glStencilMaskSeparate);
+ glStencilOpSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLenum )), glStencilOpSeparate);
+ glUniform1f = RESOLVE((void (APIENTRY *)(GLint , GLfloat )), glUniform1f);
+ glUniform1fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform1fv);
+ glUniform1i = RESOLVE((void (APIENTRY *)(GLint , GLint )), glUniform1i);
+ glUniform1iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform1iv);
+ glUniform2f = RESOLVE((void (APIENTRY *)(GLint , GLfloat , GLfloat )), glUniform2f);
+ glUniform2fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform2fv);
+ glUniform2i = RESOLVE((void (APIENTRY *)(GLint , GLint , GLint )), glUniform2i);
+ glUniform2iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform2iv);
+ glUniform3f = RESOLVE((void (APIENTRY *)(GLint , GLfloat , GLfloat , GLfloat )), glUniform3f);
+ glUniform3fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform3fv);
+ glUniform3i = RESOLVE((void (APIENTRY *)(GLint , GLint , GLint , GLint )), glUniform3i);
+ glUniform3iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform3iv);
+ glUniform4f = RESOLVE((void (APIENTRY *)(GLint , GLfloat , GLfloat , GLfloat , GLfloat )), glUniform4f);
+ glUniform4fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform4fv);
+ glUniform4i = RESOLVE((void (APIENTRY *)(GLint , GLint , GLint , GLint , GLint )), glUniform4i);
+ glUniform4iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform4iv);
+ glUniformMatrix2fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )), glUniformMatrix2fv);
+ glUniformMatrix3fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )), glUniformMatrix3fv);
+ glUniformMatrix4fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )), glUniformMatrix4fv);
+ glUseProgram = RESOLVE((void (APIENTRY *)(GLuint )), glUseProgram);
+ glValidateProgram = RESOLVE((void (APIENTRY *)(GLuint )), glValidateProgram);
+ glVertexAttrib1f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat )), glVertexAttrib1f);
+ glVertexAttrib1fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib1fv);
+ glVertexAttrib2f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat , GLfloat )), glVertexAttrib2f);
+ glVertexAttrib2fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib2fv);
+ glVertexAttrib3f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat , GLfloat , GLfloat )), glVertexAttrib3f);
+ glVertexAttrib3fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib3fv);
+ glVertexAttrib4f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat , GLfloat , GLfloat , GLfloat )), glVertexAttrib4f);
+ glVertexAttrib4fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib4fv);
+ glVertexAttribPointer = RESOLVE((void (APIENTRY *)(GLuint , GLint, GLenum, GLboolean, GLsizei, const GLvoid* )), glVertexAttribPointer);
+
+ glClearDepthf = RESOLVE((void (APIENTRY *)(GLclampf )), glClearDepthf);
+ glDepthRangef = RESOLVE((void (APIENTRY *)(GLclampf , GLclampf )), glDepthRangef);
+
+ return glBindTexture && glCreateShader && glClearDepthf;
+}
+
QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display, int version)
: m_display(display), m_version(version)
{
@@ -76,7 +350,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 +367,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 +382,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 +469,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 && QWindowsContext::verbose)
+ 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