Add EGL_KHR_create_context support
[ChangeLog] GLES3 and desktop OpenGL are now fully supported with EGL Task-number: QTBUG-37332 Change-Id: Ic695db573d90b3a204941d105a370f5c63182b63 Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
This commit is contained in:
parent
08b9e51c47
commit
4b3d11efc0
@ -64,31 +64,48 @@ QT_BEGIN_NAMESPACE
|
||||
surface). Other than that, no further customization is necessary.
|
||||
*/
|
||||
|
||||
static inline void bindApi(const QSurfaceFormat &format)
|
||||
{
|
||||
switch (format.renderableType()) {
|
||||
case QSurfaceFormat::OpenVG:
|
||||
eglBindAPI(EGL_OPENVG_API);
|
||||
break;
|
||||
#ifdef EGL_VERSION_1_4
|
||||
case QSurfaceFormat::DefaultRenderableType:
|
||||
#ifndef QT_NO_OPENGL
|
||||
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::DesktopGL)
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
else
|
||||
#endif // QT_NO_OPENGL
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
break;
|
||||
case QSurfaceFormat::OpenGL:
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
break;
|
||||
// Constants from EGL_KHR_create_context
|
||||
#ifndef EGL_CONTEXT_MINOR_VERSION_KHR
|
||||
#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
|
||||
#endif
|
||||
#ifndef EGL_CONTEXT_FLAGS_KHR
|
||||
#define EGL_CONTEXT_FLAGS_KHR 0x30FC
|
||||
#endif
|
||||
#ifndef EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR
|
||||
#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
|
||||
#endif
|
||||
#ifndef EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
|
||||
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
|
||||
#endif
|
||||
#ifndef EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
|
||||
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
|
||||
#endif
|
||||
#ifndef EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
|
||||
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
|
||||
#endif
|
||||
#ifndef EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
|
||||
#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
|
||||
#endif
|
||||
|
||||
// Constants for OpenGL which are not available in the ES headers.
|
||||
#ifndef GL_CONTEXT_FLAGS
|
||||
#define GL_CONTEXT_FLAGS 0x821E
|
||||
#endif
|
||||
#ifndef GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
|
||||
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
|
||||
#endif
|
||||
#ifndef GL_CONTEXT_FLAG_DEBUG_BIT
|
||||
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
|
||||
#endif
|
||||
#ifndef GL_CONTEXT_PROFILE_MASK
|
||||
#define GL_CONTEXT_PROFILE_MASK 0x9126
|
||||
#endif
|
||||
#ifndef GL_CONTEXT_CORE_PROFILE_BIT
|
||||
#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
|
||||
#endif
|
||||
#ifndef GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
|
||||
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
|
||||
#endif
|
||||
case QSurfaceFormat::OpenGLES:
|
||||
default:
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display)
|
||||
: m_eglDisplay(display)
|
||||
@ -114,14 +131,55 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
|
||||
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
|
||||
{
|
||||
m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
|
||||
// m_format now has the renderableType() resolved (it cannot be Default anymore)
|
||||
// but does not yet contain version, profile, options.
|
||||
m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;
|
||||
|
||||
QVector<EGLint> contextAttrs;
|
||||
contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
|
||||
contextAttrs.append(format.majorVersion());
|
||||
const bool hasKHRCreateContext = q_hasEglExtension(m_eglDisplay, "EGL_KHR_create_context");
|
||||
if (hasKHRCreateContext) {
|
||||
contextAttrs.append(EGL_CONTEXT_MINOR_VERSION_KHR);
|
||||
contextAttrs.append(format.minorVersion());
|
||||
int flags = 0;
|
||||
// The debug bit is supported both for OpenGL and OpenGL ES.
|
||||
if (format.testOption(QSurfaceFormat::DebugContext))
|
||||
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||
// The fwdcompat bit is only for OpenGL 3.0+.
|
||||
if (m_format.renderableType() == QSurfaceFormat::OpenGL
|
||||
&& format.majorVersion() >= 3
|
||||
&& !format.testOption(QSurfaceFormat::DeprecatedFunctions))
|
||||
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||
if (flags) {
|
||||
contextAttrs.append(EGL_CONTEXT_FLAGS_KHR);
|
||||
contextAttrs.append(flags);
|
||||
}
|
||||
// Profiles are OpenGL only and mandatory in 3.2+. The value is silently ignored for < 3.2.
|
||||
if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
|
||||
contextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
|
||||
contextAttrs.append(format.profile() == QSurfaceFormat::CoreProfile
|
||||
? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
|
||||
: EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
|
||||
}
|
||||
}
|
||||
contextAttrs.append(EGL_NONE);
|
||||
|
||||
bindApi(m_format);
|
||||
switch (m_format.renderableType()) {
|
||||
case QSurfaceFormat::OpenVG:
|
||||
m_api = EGL_OPENVG_API;
|
||||
break;
|
||||
#ifdef EGL_VERSION_1_4
|
||||
case QSurfaceFormat::OpenGL:
|
||||
m_api = EGL_OPENGL_API;
|
||||
break;
|
||||
#endif // EGL_VERSION_1_4
|
||||
default:
|
||||
m_api = EGL_OPENGL_ES_API;
|
||||
break;
|
||||
}
|
||||
|
||||
eglBindAPI(m_api);
|
||||
m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData());
|
||||
if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
|
||||
m_shareContext = 0;
|
||||
@ -133,6 +191,7 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
// Make the context current to ensure the GL version query works. This needs a surface too.
|
||||
const EGLint pbufferAttributes[] = {
|
||||
EGL_WIDTH, 1,
|
||||
@ -145,25 +204,52 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont
|
||||
return;
|
||||
|
||||
if (eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) {
|
||||
const GLubyte *s = 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);
|
||||
if (m_format.renderableType() == QSurfaceFormat::OpenGL
|
||||
|| m_format.renderableType() == QSurfaceFormat::OpenGLES) {
|
||||
const GLubyte *s = 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());
|
||||
if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
|
||||
// Check profile and options.
|
||||
if (m_format.majorVersion() < 3) {
|
||||
m_format.setOption(QSurfaceFormat::DeprecatedFunctions);
|
||||
} else {
|
||||
GLint value = 0;
|
||||
glGetIntegerv(GL_CONTEXT_FLAGS, &value);
|
||||
if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
|
||||
m_format.setOption(QSurfaceFormat::DeprecatedFunctions);
|
||||
if (value & GL_CONTEXT_FLAG_DEBUG_BIT)
|
||||
m_format.setOption(QSurfaceFormat::DebugContext);
|
||||
if (m_format.version() >= qMakePair(3, 2)) {
|
||||
value = 0;
|
||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
|
||||
if (value & GL_CONTEXT_CORE_PROFILE_BIT)
|
||||
m_format.setProfile(QSurfaceFormat::CoreProfile);
|
||||
else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
|
||||
m_format.setProfile(QSurfaceFormat::CompatibilityProfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
eglDestroySurface(m_eglDisplay, pbuffer);
|
||||
#endif // QT_NO_OPENGL
|
||||
}
|
||||
|
||||
bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
|
||||
{
|
||||
Q_ASSERT(surface->surface()->supportsOpenGL());
|
||||
|
||||
bindApi(m_format);
|
||||
eglBindAPI(m_api);
|
||||
|
||||
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
|
||||
|
||||
@ -231,7 +317,7 @@ QEGLPlatformContext::~QEGLPlatformContext()
|
||||
|
||||
void QEGLPlatformContext::doneCurrent()
|
||||
{
|
||||
bindApi(m_format);
|
||||
eglBindAPI(m_api);
|
||||
bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (!ok)
|
||||
qWarning("QEGLPlatformContext::doneCurrent(): eglError: %d, this: %p \n", eglGetError(), this);
|
||||
@ -239,7 +325,7 @@ void QEGLPlatformContext::doneCurrent()
|
||||
|
||||
void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
|
||||
{
|
||||
bindApi(m_format);
|
||||
eglBindAPI(m_api);
|
||||
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
|
||||
bool ok = eglSwapBuffers(m_eglDisplay, eglSurface);
|
||||
if (!ok)
|
||||
@ -248,7 +334,7 @@ void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
|
||||
|
||||
void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) ()
|
||||
{
|
||||
bindApi(m_format);
|
||||
eglBindAPI(m_api);
|
||||
return eglGetProcAddress(procName.constData());
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,7 @@ private:
|
||||
EGLDisplay m_eglDisplay;
|
||||
EGLConfig m_eglConfig;
|
||||
QSurfaceFormat m_format;
|
||||
EGLenum m_api;
|
||||
int m_swapInterval;
|
||||
bool m_swapIntervalEnvChecked;
|
||||
int m_swapIntervalFromEnv;
|
||||
|
Loading…
x
Reference in New Issue
Block a user