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.
|
surface). Other than that, no further customization is necessary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline void bindApi(const QSurfaceFormat &format)
|
// Constants from EGL_KHR_create_context
|
||||||
{
|
#ifndef EGL_CONTEXT_MINOR_VERSION_KHR
|
||||||
switch (format.renderableType()) {
|
#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
|
||||||
case QSurfaceFormat::OpenVG:
|
#endif
|
||||||
eglBindAPI(EGL_OPENVG_API);
|
#ifndef EGL_CONTEXT_FLAGS_KHR
|
||||||
break;
|
#define EGL_CONTEXT_FLAGS_KHR 0x30FC
|
||||||
#ifdef EGL_VERSION_1_4
|
#endif
|
||||||
case QSurfaceFormat::DefaultRenderableType:
|
#ifndef EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR
|
||||||
#ifndef QT_NO_OPENGL
|
#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
|
||||||
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::DesktopGL)
|
#endif
|
||||||
eglBindAPI(EGL_OPENGL_API);
|
#ifndef EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
|
||||||
else
|
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
|
||||||
#endif // QT_NO_OPENGL
|
#endif
|
||||||
eglBindAPI(EGL_OPENGL_ES_API);
|
#ifndef EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
|
||||||
break;
|
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
|
||||||
case QSurfaceFormat::OpenGL:
|
#endif
|
||||||
eglBindAPI(EGL_OPENGL_API);
|
#ifndef EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
|
||||||
break;
|
#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
|
#endif
|
||||||
case QSurfaceFormat::OpenGLES:
|
|
||||||
default:
|
|
||||||
eglBindAPI(EGL_OPENGL_ES_API);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display)
|
QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display)
|
||||||
: m_eglDisplay(display)
|
: m_eglDisplay(display)
|
||||||
@ -114,14 +131,55 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
|
|||||||
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
|
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
|
||||||
{
|
{
|
||||||
m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
|
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;
|
m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;
|
||||||
|
|
||||||
QVector<EGLint> contextAttrs;
|
QVector<EGLint> contextAttrs;
|
||||||
contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
|
contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
|
||||||
contextAttrs.append(format.majorVersion());
|
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);
|
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());
|
m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData());
|
||||||
if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
|
if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
|
||||||
m_shareContext = 0;
|
m_shareContext = 0;
|
||||||
@ -133,6 +191,7 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
// Make the context current to ensure the GL version query works. This needs a surface too.
|
// Make the context current to ensure the GL version query works. This needs a surface too.
|
||||||
const EGLint pbufferAttributes[] = {
|
const EGLint pbufferAttributes[] = {
|
||||||
EGL_WIDTH, 1,
|
EGL_WIDTH, 1,
|
||||||
@ -145,25 +204,52 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) {
|
if (eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) {
|
||||||
const GLubyte *s = glGetString(GL_VERSION);
|
if (m_format.renderableType() == QSurfaceFormat::OpenGL
|
||||||
if (s) {
|
|| m_format.renderableType() == QSurfaceFormat::OpenGLES) {
|
||||||
QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
|
const GLubyte *s = glGetString(GL_VERSION);
|
||||||
int major, minor;
|
if (s) {
|
||||||
if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
|
QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
|
||||||
m_format.setMajorVersion(major);
|
int major, minor;
|
||||||
m_format.setMinorVersion(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);
|
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
}
|
}
|
||||||
eglDestroySurface(m_eglDisplay, pbuffer);
|
eglDestroySurface(m_eglDisplay, pbuffer);
|
||||||
|
#endif // QT_NO_OPENGL
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
|
bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
|
||||||
{
|
{
|
||||||
Q_ASSERT(surface->surface()->supportsOpenGL());
|
Q_ASSERT(surface->surface()->supportsOpenGL());
|
||||||
|
|
||||||
bindApi(m_format);
|
eglBindAPI(m_api);
|
||||||
|
|
||||||
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
|
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
|
||||||
|
|
||||||
@ -231,7 +317,7 @@ QEGLPlatformContext::~QEGLPlatformContext()
|
|||||||
|
|
||||||
void QEGLPlatformContext::doneCurrent()
|
void QEGLPlatformContext::doneCurrent()
|
||||||
{
|
{
|
||||||
bindApi(m_format);
|
eglBindAPI(m_api);
|
||||||
bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
qWarning("QEGLPlatformContext::doneCurrent(): eglError: %d, this: %p \n", eglGetError(), this);
|
qWarning("QEGLPlatformContext::doneCurrent(): eglError: %d, this: %p \n", eglGetError(), this);
|
||||||
@ -239,7 +325,7 @@ void QEGLPlatformContext::doneCurrent()
|
|||||||
|
|
||||||
void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
|
void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
|
||||||
{
|
{
|
||||||
bindApi(m_format);
|
eglBindAPI(m_api);
|
||||||
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
|
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
|
||||||
bool ok = eglSwapBuffers(m_eglDisplay, eglSurface);
|
bool ok = eglSwapBuffers(m_eglDisplay, eglSurface);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
@ -248,7 +334,7 @@ void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
|
|||||||
|
|
||||||
void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) ()
|
void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) ()
|
||||||
{
|
{
|
||||||
bindApi(m_format);
|
eglBindAPI(m_api);
|
||||||
return eglGetProcAddress(procName.constData());
|
return eglGetProcAddress(procName.constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ private:
|
|||||||
EGLDisplay m_eglDisplay;
|
EGLDisplay m_eglDisplay;
|
||||||
EGLConfig m_eglConfig;
|
EGLConfig m_eglConfig;
|
||||||
QSurfaceFormat m_format;
|
QSurfaceFormat m_format;
|
||||||
|
EGLenum m_api;
|
||||||
int m_swapInterval;
|
int m_swapInterval;
|
||||||
bool m_swapIntervalEnvChecked;
|
bool m_swapIntervalEnvChecked;
|
||||||
int m_swapIntervalFromEnv;
|
int m_swapIntervalFromEnv;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user